mirror of https://github.com/openspug/spug
add batch delete hosts
parent
ce69718202
commit
b64342a192
|
@ -98,22 +98,30 @@ class HostView(View):
|
||||||
|
|
||||||
def delete(self, request):
|
def delete(self, request):
|
||||||
form, error = JsonParser(
|
form, error = JsonParser(
|
||||||
Argument('id', type=int, help='请指定操作对象')
|
Argument('id', type=int, required=False),
|
||||||
|
Argument('group_id', type=int, required=False),
|
||||||
).parse(request.GET)
|
).parse(request.GET)
|
||||||
if error is None:
|
if error is None:
|
||||||
deploy = Deploy.objects.filter(host_ids__regex=fr'[^0-9]{form.id}[^0-9]').annotate(
|
if form.id:
|
||||||
app_name=F('app__name'),
|
host_ids = [form.id]
|
||||||
env_name=F('env__name')
|
elif form.group_id:
|
||||||
).first()
|
group = Group.objects.get(pk=form.group_id)
|
||||||
if deploy:
|
host_ids = [x.id for x in group.hosts.all()]
|
||||||
return json_response(error=f'应用【{deploy.app_name}】在【{deploy.env_name}】的发布配置关联了该主机,请解除关联后再尝试删除该主机')
|
else:
|
||||||
task = Task.objects.filter(targets__regex=fr'[^0-9]{form.id}[^0-9]').first()
|
return json_response(error='参数错误')
|
||||||
if task:
|
for host_id in host_ids:
|
||||||
return json_response(error=f'任务计划中的任务【{task.name}】关联了该主机,请解除关联后再尝试删除该主机')
|
regex = fr'[^0-9]{host_id}[^0-9]'
|
||||||
detection = Detection.objects.filter(type__in=('3', '4'), targets__regex=fr'[^0-9]{form.id}[^0-9]').first()
|
deploy = Deploy.objects.filter(host_ids__regex=regex) \
|
||||||
if detection:
|
.annotate(app_name=F('app__name'), env_name=F('env__name')).first()
|
||||||
return json_response(error=f'监控中心的任务【{detection.name}】关联了该主机,请解除关联后再尝试删除该主机')
|
if deploy:
|
||||||
Host.objects.filter(pk=form.id).delete()
|
return json_response(error=f'应用【{deploy.app_name}】在【{deploy.env_name}】的发布配置关联了该主机,请解除关联后再尝试删除该主机')
|
||||||
|
task = Task.objects.filter(targets__regex=fr'[^0-9]{form.id}[^0-9]').first()
|
||||||
|
if task:
|
||||||
|
return json_response(error=f'任务计划中的任务【{task.name}】关联了该主机,请解除关联后再尝试删除该主机')
|
||||||
|
detection = Detection.objects.filter(type__in=('3', '4'), targets__regex=regex).first()
|
||||||
|
if detection:
|
||||||
|
return json_response(error=f'监控中心的任务【{detection.name}】关联了该主机,请解除关联后再尝试删除该主机')
|
||||||
|
Host.objects.filter(id__in=host_ids).delete()
|
||||||
return json_response(error=error)
|
return json_response(error=error)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -5,13 +5,14 @@
|
||||||
*/
|
*/
|
||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from 'mobx-react';
|
||||||
import { Input, Card, Tree, Dropdown, Menu, Switch, Tooltip, message } from 'antd';
|
import { Input, Card, Tree, Dropdown, Menu, Switch, Tooltip, Modal } from 'antd';
|
||||||
import {
|
import {
|
||||||
FolderOutlined,
|
FolderOutlined,
|
||||||
FolderAddOutlined,
|
FolderAddOutlined,
|
||||||
EditOutlined,
|
EditOutlined,
|
||||||
DeleteOutlined,
|
DeleteOutlined,
|
||||||
CopyOutlined,
|
CopyOutlined,
|
||||||
|
CloseOutlined,
|
||||||
ScissorOutlined,
|
ScissorOutlined,
|
||||||
LoadingOutlined,
|
LoadingOutlined,
|
||||||
QuestionCircleOutlined
|
QuestionCircleOutlined
|
||||||
|
@ -50,19 +51,32 @@ export default observer(function () {
|
||||||
<Menu.Item key="3" icon={<CopyOutlined/>} onClick={() => store.showSelector(true)}>添加至分组</Menu.Item>
|
<Menu.Item key="3" icon={<CopyOutlined/>} onClick={() => store.showSelector(true)}>添加至分组</Menu.Item>
|
||||||
<Menu.Item key="4" icon={<ScissorOutlined/>} onClick={() => store.showSelector(false)}>移动至分组</Menu.Item>
|
<Menu.Item key="4" icon={<ScissorOutlined/>} onClick={() => store.showSelector(false)}>移动至分组</Menu.Item>
|
||||||
<Menu.Divider/>
|
<Menu.Divider/>
|
||||||
<Menu.Item key="5" icon={<DeleteOutlined/>} danger onClick={handleRemove}>删除此分组</Menu.Item>
|
<Menu.Item key="5" icon={<CloseOutlined/>} danger onClick={handleRemoveHosts}>删除主机</Menu.Item>
|
||||||
|
<Menu.Item key="6" icon={<DeleteOutlined/>} danger onClick={handleRemove}>删除此分组</Menu.Item>
|
||||||
</Menu>
|
</Menu>
|
||||||
)
|
)
|
||||||
|
|
||||||
function handleSubmit() {
|
function handleSubmit() {
|
||||||
if (!store.group.title) {
|
if (store.group.title) {
|
||||||
return message.error('请输入分组名称')
|
setLoading(true);
|
||||||
|
const {key, parent_id, title} = store.group;
|
||||||
|
http.post('/api/host/group/', {id: key || undefined, parent_id, name: title})
|
||||||
|
.then(() => setAction(''))
|
||||||
|
.finally(() => setLoading(false))
|
||||||
|
} else {
|
||||||
|
if (store.group.key === 0) store.treeData = bakTreeData
|
||||||
|
setAction('')
|
||||||
}
|
}
|
||||||
setLoading(true);
|
}
|
||||||
const {key, parent_id, title} = store.group;
|
|
||||||
http.post('/api/host/group/', {id: key || undefined, parent_id, name: title})
|
function handleRemoveHosts() {
|
||||||
.then(() => setAction(''))
|
const group = store.group;
|
||||||
.finally(() => setLoading(false))
|
Modal.confirm({
|
||||||
|
title: '操作确认',
|
||||||
|
content: `批量删除【${group.title}】分组内的 ${group.all_host_ids.length} 个主机?`,
|
||||||
|
onOk: () => http.delete('/api/host/', {params: {group_id: group.key}})
|
||||||
|
.then(store.initial)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleRemove() {
|
function handleRemove() {
|
||||||
|
@ -102,13 +116,6 @@ export default observer(function () {
|
||||||
.then(() => setLoading(false))
|
.then(() => setLoading(false))
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleBlur() {
|
|
||||||
if (store.group.key === 0) {
|
|
||||||
store.treeData = bakTreeData
|
|
||||||
}
|
|
||||||
setAction('')
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleRightClick(v) {
|
function handleRightClick(v) {
|
||||||
if (hasPermission('admin')) {
|
if (hasPermission('admin')) {
|
||||||
store.group = v.node;
|
store.group = v.node;
|
||||||
|
@ -131,7 +138,7 @@ export default observer(function () {
|
||||||
defaultValue={nodeData.title}
|
defaultValue={nodeData.title}
|
||||||
suffix={loading ? <LoadingOutlined/> : <span/>}
|
suffix={loading ? <LoadingOutlined/> : <span/>}
|
||||||
onClick={e => e.stopPropagation()}
|
onClick={e => e.stopPropagation()}
|
||||||
onBlur={handleBlur}
|
onBlur={handleSubmit}
|
||||||
onChange={e => store.group.title = e.target.value}
|
onChange={e => store.group.title = e.target.value}
|
||||||
onPressEnter={handleSubmit}/>
|
onPressEnter={handleSubmit}/>
|
||||||
} else if (action === 'del' && nodeData.key === store.group.key) {
|
} else if (action === 'del' && nodeData.key === store.group.key) {
|
||||||
|
|
Loading…
Reference in New Issue