代码拉取完成,页面将自动刷新
From bba113a5899bb0b17916b2179e1f5594756dc58e Mon Sep 17 00:00:00 2001
From: Hu gang <18768366022@163.com>
Date: Wed, 13 Dec 2023 15:15:59 +0800
Subject: [PATCH] feat: add host management status, adaptation rollback tsak
---
src/api/assest.js | 1 +
src/api/leaks.js | 24 +--
src/config/router.config.js | 4 +
src/vendor/ant-design-pro/utils/request.js | 14 +-
src/views/assests/HostDetail.vue | 39 ++--
src/views/assests/HostManagement.vue | 82 ++++---
src/views/leaks/LeakTaskDetail.vue | 203 ++++++++++--------
src/views/leaks/LeakTaskList.vue | 4 +
src/views/leaks/TaskResultReport.vue | 76 +++++--
.../components/CreateRepairTaskDrawer.vue | 36 ++--
10 files changed, 277 insertions(+), 206 deletions(-)
diff --git a/src/api/assest.js b/src/api/assest.js
index a0f70ec..94015d3 100644
--- a/src/api/assest.js
+++ b/src/api/assest.js
@@ -55,6 +55,7 @@ export function hostList({tableInfo, ...parameter}) {
...parameter,
host_group_list: tableInfo.filters.host_group_name || [],
management,
+ search_key: tableInfo.filters.searchKey,
sort: tableInfo.sorter.field,
direction: directionMap[tableInfo.sorter.order],
page: tableInfo.pagination.current,
diff --git a/src/api/leaks.js b/src/api/leaks.js
index 8daf70d..c6f704b 100644
--- a/src/api/leaks.js
+++ b/src/api/leaks.js
@@ -44,15 +44,15 @@ const api = {
getRpmUnderCve: '/vulnerability/cve/packages/host/get', // 查询cve影响的rpm包的主机列表
getCvefixLeakRpm: '/vulnerability/task/cve/rpm/get', // 修复任务详情中cve列表的二级package
getCveRpmHostUnderLeak: '/vulnerability/task/cve/rpm/host/get', // 查询修复任务下的cve影响的rpm包的主机列表
- getCveListInFixDetail: '/vulnerability/task/cve-fix/info/get', // 新接口取代api.getCveUnderCveTask 获取修复任务详情下的cve列表
getRpmListInFixDetail: '/vulnerability/task/cve-fix/rpm/get', // 新接口取代api.getCvefixLeakRpm,获取修复任务详情下指定主机和任务下的rpm列表
getCveFixReport: '/vulnerability/task/cve-fix/result/get', // 新接口取代api.getCveTaskResult ,获取修复任务的报告
- getCveRollvackReport: ' /vulnerability/task/rollback/result/get', // 获取回滚任务报告
+ getCveRollvackReport: '/vulnerability/task/cve-rollback/result/get', // 获取回滚任务报告
generateHotPathRemoveTask: '/vulnerability/task/hotpatch-remove/generate', // 新接口取代api.generateRollbackTask ,生成热补丁移除任务
- getRpmListInRollbackDetail: '/vulnerability/task/rollback/rpm/get', // 获取回滚任务详情列表下的rpm信息
- getCveListInRollbackDetail: '/vulnerability/task/rollback/cve-info/get', // 获取回滚任务详情下的列表信息
+ getRpmListInRollbackDetail: '/vulnerability/task/cve-rollback/rpm/get', // 获取回滚任务详情列表下的rpm信息
generateRollbackTask: '/vulnerability/task/cve-rollback/generate', // 生成回滚任务
+ getCveListInRollbackDetail: '/vulnerability/task/cve-rollback/info/get', // 获取回滚任务详情下的列表信息
getCveHotpatchRemoveDetail: '/vulnerability/task/hotpatch-remove/info/get', // 获取热补丁移除任务详情
+ getCveListInFixDetail: '/vulnerability/task/cve-fix/info/get', // 新接口取代api.getCveUnderCveTask 获取修复任务详情下的cve列表
getHotpatchRemoveTaskReport: '/vulnerability/task/hotpatch-remove/result/get', // 获取热补丁移除任务报告
getAllHostInDetail: '/vulnerability/task/host/get' // 获取详情页面下所有的hostid
};
@@ -132,6 +132,7 @@ export function getCveListInRollbackDetail({tableInfo, ...params}) {
task_id: params.taskId,
direction: sorterMap[tableInfo.sorter.order],
filter: {
+ search_key: tableInfo.filters.searchKey,
status: tableInfo.filters.status
},
page: tableInfo.pagination.current,
@@ -140,7 +141,7 @@ export function getCveListInRollbackDetail({tableInfo, ...params}) {
});
}
-// 创建热补丁回退任务
+// 创建热补丁移除任务
export function generateHotPatchRemoveTask(params) {
return request({
url: api.generateHotPathRemoveTask,
@@ -196,6 +197,7 @@ export function getCveListInFixDetail({tableInfo, ...params}) {
task_id: params.taskId,
direction: sorterMap[tableInfo.sorter.order],
filter: {
+ search_key: tableInfo.filters.searchKey,
status: tableInfo.filters.status
},
page: tableInfo.pagination.current,
@@ -267,18 +269,6 @@ export function getCveFixRpm(parameters) {
});
}
-// export function generateRollbackTask(parameters) {
-// return request({
-// url: api.generateRollbackTask,
-// method: 'post',
-// data: {
-// task_name: parameters.task_name,
-// description: parameters.description,
-// info: parameters.info || []
-// }
-// });
-// }
-
export function getCveExport(parameter) {
return request({
url: api.getCveExport,
diff --git a/src/config/router.config.js b/src/config/router.config.js
index b92011f..5f1d4df 100644
--- a/src/config/router.config.js
+++ b/src/config/router.config.js
@@ -575,6 +575,10 @@ export const asyncRouterMap = [
breadcrumbName: routeMap.leaks.children.leakTaskView.children.leakTaskList.title,
path: routeMap.leaks.children.leakTaskView.children.leakTaskList.path
},
+ {
+ breadcrumbName: routeMap.leaks.children.leakTaskView.children.leakTaskDetail.title,
+ path: routeMap.leaks.children.leakTaskView.children.leakTaskDetail.path
+ },
{
breadcrumbName: routeMap.leaks.children.leakTaskView.children.taskResultReport.title,
path: routeMap.leaks.children.leakTaskView.children.taskResultReport.path
diff --git a/src/vendor/ant-design-pro/utils/request.js b/src/vendor/ant-design-pro/utils/request.js
index d9320d8..661bfd0 100644
--- a/src/vendor/ant-design-pro/utils/request.js
+++ b/src/vendor/ant-design-pro/utils/request.js
@@ -101,7 +101,7 @@ request.interceptors.response.use((response) => {
const code = response.data.code || response.status;
// 不处理所有2xx的状态码
if (!code.toString().match(/^2[0-9]{2,2}$/)) {
- let err = null;
+ // let err = null;
switch (code) {
case '1201':
if (!timestamp1 || timestamp1 + 1632252465 < new Date().getTime()) {
@@ -166,10 +166,14 @@ request.interceptors.response.use((response) => {
});
return retryRequest;
default:
- err = new Error(response.data.message);
- err.data = response.data.data;
- err.response = response.data;
- throw err;
+ notification.error({
+ message: response.data.label,
+ description: response.data.message
+ });
+ // err = new Error(response.data.message);
+ // err.data = response.data.data;
+ // err.response = response.data;
+ // throw err;
}
}
if (response.headers['content-type'] === 'application/octet-stream') {
diff --git a/src/views/assests/HostDetail.vue b/src/views/assests/HostDetail.vue
index 8286caf..6eadb05 100644
--- a/src/views/assests/HostDetail.vue
+++ b/src/views/assests/HostDetail.vue
@@ -49,38 +49,37 @@ export default {
};
},
methods: {
- fetchHostInfo(This) {
- const _this = This;
- This.basicHostInfoIsLoading = true;
- getHostDetail(This.hostId, true)
- .then(function (res) {
- _this.basicHostInfo = res.data.host_infos[0];
- _this.scene = This.basicHostInfo.scene;
+ fetchHostInfo() {
+ this.basicHostInfoIsLoading = true;
+ getHostDetail(Number(this.hostId), true)
+ .then((res) => {
+ this.basicHostInfo = res.data.host_infos[0];
+ this.scene = this.basicHostInfo.scene;
})
- .catch(function (err) {
- _this.$message.error(err.response.message);
+ .catch((err) => {
+ this.$message.error(err.response.message);
})
.finally(() => {
- _this.basicHostInfoIsLoading = false;
+ this.basicHostInfoIsLoading = false;
});
- This.basicInfoIsLoading = true;
- getHostDetail(This.hostId, false)
- .then(function (res) {
- _this.basicInfo = res.data.host_infos[0];
+ this.basicInfoIsLoading = true;
+ getHostDetail(Number(this.hostId), false)
+ .then((res) => {
+ this.basicInfo = res.data.host_infos[0];
})
- .catch(function (err) {
- _this.$message.error(err.response.message);
+ .catch((err) => {
+ this.$message.error(err.response.message);
})
.finally(() => {
- _this.basicInfoIsLoading = false;
+ this.basicInfoIsLoading = false;
});
},
reFetchHostInfo() {
- this.$options.methods.fetchHostInfo(this);
+ this.fetchHostInfo();
}
},
- mounted: function () {
- this.$options.methods.fetchHostInfo(this);
+ mounted() {
+ this.fetchHostInfo();
}
};
</script>
diff --git a/src/views/assests/HostManagement.vue b/src/views/assests/HostManagement.vue
index aaa86a8..77e0ed8 100644
--- a/src/views/assests/HostManagement.vue
+++ b/src/views/assests/HostManagement.vue
@@ -17,7 +17,8 @@
</a-alert>
</a-col>
<a-col>
- <a-button @click="handleReset">重置条件</a-button>
+ <!-- <a-button @click="handleReset">重置条件</a-button> -->
+ <a-input-search placeholder="按主机名或主机ip搜索" style="width: 200px" @search="handleSearch" />
</a-col>
</a-row>
</a-col>
@@ -59,26 +60,19 @@
>{{ hostName }}</router-link
>
<span slot="isManagement" slot-scope="isMana">{{ isMana ? '是' : '否' }}</span>
- <span slot="statusItem" slot-scope="status">{{ hostStatusMap[status] }}</span>
+ <span slot="statusItem" slot-scope="status">
+ <a-spin v-if="!status && status !== 0"></a-spin>
+ <span v-else>{{ hostStatusMap[status] }}</span>
+ </span>
<span slot="scene" slot-scope="scene">{{ scene ? (scene === 'normal' ? '通用' : scene) : '暂无' }}</span>
<span slot="action" slot-scope="record">
- <!-- <a @click="openDetail(record.host_id)">查看</a>
- ----后续增加-----
- <a-divider type="vertical" />
- <span>编辑</span>
- ----------------
- <a-divider type="vertical" /> -->
<router-link
:to="{path: `hosts-management/host-edit`, query: {hostId: record.host_id, pageType: 'edit'}}"
@click="editHost(record)"
- >编辑</router-link
- >
- <span> | </span>
- <a @click="deleteHost(record)">删除</a>
+ >编辑
+ </router-link>
+ <a @click="deleteHost(record)" class="delete-button"> 删除</a>
</span>
- <!-- <div slot="expandedRowRender" style="margin: 0">
- <host-terminal />
- </div> -->
</a-table>
</div>
</a-card>
@@ -94,7 +88,7 @@ import MyPageHeaderWrapper from '@/views/utils/MyPageHeaderWrapper';
import {getSelectedRow} from '@/views/utils/getSelectedRow';
import HostDetailDrawer from './components/HostDetailDrawer';
// import HostTerminal from '@/views/assests/components/HostTerminal';
-import {hostList, deleteHost, hostGroupList} from '@/api/assest';
+import {hostList, deleteHost, hostGroupList, getHostListWithStatus} from '@/api/assest';
const hostStatusMap = {
0: '在线',
@@ -214,6 +208,9 @@ export default {
}
},
methods: {
+ async getAllHostStatus() {
+ const res = await getHostListWithStatus();
+ },
handleTableChange(pagination, filters, sorter) {
// 存储翻页状态
this.pagination = pagination;
@@ -230,14 +227,13 @@ export default {
this.selectedRowsAll = getSelectedRow(selectedRowKeys, this.selectedRowsAll, this.tableData, 'host_id');
},
// 获取列表数据
- getHostList() {
- const _this = this;
+ async getHostList() {
this.tableIsLoading = true;
const pagination = this.pagination || {};
const filters = this.filters || {};
const sorter = this.sorter || {};
- hostList({
+ const hostListRes = await hostList({
tableInfo: {
pagination: {
current: pagination.current,
@@ -249,22 +245,28 @@ export default {
order: sorter.order
}
}
- })
- .then(function (res) {
- _this.tableData = res.data.host_infos || [];
- _this.pagination = {
- ..._this.pagination,
- current: pagination.current,
- pageSize: pagination.pageSize,
- total: res.data.total_count || (res.data.total_count === 0 ? 0 : pagination.total)
- };
- })
- .catch(function (err) {
- _this.$message.error(err.response.message);
- })
- .finally(function () {
- _this.tableIsLoading = false;
- });
+ });
+ if (hostListRes) {
+ this.tableData = hostListRes.data.host_infos || [];
+ this.pagination = {
+ ...this.pagination,
+ current: pagination.current,
+ pageSize: pagination.pageSize,
+ total: hostListRes.data.total_count || (hostListRes.data.total_count === 0 ? 0 : pagination.total)
+ };
+ const hostIdList = this.tableData.map((item) => item.host_id);
+ this.tableIsLoading = false;
+ const res = await getHostListWithStatus(hostIdList);
+ if (res) {
+ this.tableData.forEach((item) => {
+ const s = res.data.find((s) => item.host_id === s.host_id);
+ if (s) {
+ item.status = s.status;
+ }
+ });
+ this.tableData = JSON.parse(JSON.stringify(this.tableData));
+ }
+ }
},
editHost(record) {
this.$message.success('连接到主机' + record.host_ip);
@@ -384,6 +386,16 @@ export default {
duration: 5
});
},
+ handleSearch(text = '') {
+ this.pagination = defaultPagination;
+ this.sorter = null;
+ if (!this.filters) {
+ this.filters = {};
+ }
+ this.selectedRowKeys = [];
+ this.filters.searchKey = text !== '' ? text : undefined;
+ this.getHostList();
+ },
handleReset() {
this.pagination = defaultPagination;
this.sorter = null;
diff --git a/src/views/leaks/LeakTaskDetail.vue b/src/views/leaks/LeakTaskDetail.vue
index 27e919e..f7f7438 100644
--- a/src/views/leaks/LeakTaskDetail.vue
+++ b/src/views/leaks/LeakTaskDetail.vue
@@ -111,7 +111,9 @@
</a-row>
</a-col>
<a-col v-if="taskType === 'cve fix'">
- <a-button type="primary" @click="generateRollbackTask">生成回滚任务</a-button>
+ <a-button type="primary" @click="generateRollbackTask" :loading="isRollBackButtonLoading"
+ >生成回滚任务</a-button
+ >
</a-col>
</a-row>
<!-- 热补丁移除任务 -->
@@ -236,12 +238,13 @@ import {
getTaskProgress,
generateRollbackTask,
getCveProgressUnderCveTask,
- getAllHostInDetail
+ getAllHostInDetail,
+ getHostScanStatus
} from '@/api/leaks';
import configs from '@/config/defaultSettings';
const taskTypeMap = {
- 'cve fix': '漏洞修复',
+ 'cve fix': 'cve修复',
'repo set': 'REPO设置',
'cve rollback': 'cve回滚',
'hotpatch remove': '热补丁移除'
@@ -307,6 +310,8 @@ export default {
},
data() {
return {
+ // 生成回滚任务按钮是否loading
+ isRollBackButtonLoading: false,
expandedRowKeys: [],
rpmrecord: {},
propType: '',
@@ -379,7 +384,7 @@ export default {
{
dataIndex: 'host_name',
key: 'host_name',
- title: '主机',
+ title: '主机名',
scopedSlots: {customRender: 'hostName'}
},
{
@@ -391,7 +396,7 @@ export default {
{
dataIndex: 'cve_num',
key: 'cve_num',
- title: '修复的CVE',
+ title: 'CVE数量',
scopedSlots: {customRender: 'cveNum'}
},
{
@@ -405,26 +410,27 @@ export default {
{text: '修复成功', value: 'succeed'},
{text: '待修复', value: 'fail'},
{text: '运行中', value: 'running'},
- {text: '未知', value: 'None'}
+ {text: '未知', value: 'unknown'}
]
: [
{text: '回滚成功', value: 'succeed'},
{text: '待回滚', value: 'fail'},
{text: '运行中', value: 'running'},
- {text: '未知', value: 'None'}
+ {text: '未知', value: 'unknown'}
],
filteredValue: filters.status || null,
onFilter: (value, record) => record.status.includes(value)
}
];
},
+
repoColumns() {
let {filters} = this;
filters = filters || {};
return [
{
dataIndex: 'host_name',
- title: '主机名称',
+ title: '主机名',
scopedSlots: {customRender: 'host_name'}
},
{
@@ -452,27 +458,28 @@ export default {
},
// 展开后的列表列号
innerColumns() {
+ const {taskType} = this;
return [
{
dataIndex: 'installed_rpm',
key: 'installed_rpm',
- title: '受影响rpm'
+ title: taskType === 'cve fix' ? '受影响rpm' : '已安装rpm'
},
{
- dataIndex: 'available_rpm',
- key: 'available_rpm',
- title: '待安装rpm',
- scopedSlots: {customRender: 'available_rpm'}
+ dataIndex: taskType === 'cve fix' ? 'available_rpm' : 'target_rpm',
+ key: taskType === 'cve fix' ? 'available_rpm' : 'target_rpm',
+ title: taskType === 'cve fix' ? '待安装rpm' : '目标rpm',
+ scopedSlots: {customRender: 'rpm'}
},
{
dataIndex: 'cves',
key: 'cves',
- title: '修复cve'
+ title: 'CVE'
},
{
dataIndex: 'status',
key: 'rpm_status',
- title: '状态',
+ title: this.taskType === 'cve fix' ? '修复状态' : '回滚状态',
scopedSlots: {customRender: 'status'},
filter:
this.taskType === 'cve fix'
@@ -480,13 +487,13 @@ export default {
{text: '修复成功', value: 'succeed'},
{text: '待修复', value: 'fail'},
{text: '运行中', value: 'running'},
- {text: '未知', value: 'None'}
+ {text: '未知', value: 'unknown'}
]
: [
{text: '回滚成功', value: 'succeed'},
{text: '待回滚', value: 'fail'},
{text: '运行中', value: 'running'},
- {text: '未知', value: 'None'}
+ {text: '未知', value: 'unknown'}
]
}
];
@@ -563,50 +570,43 @@ export default {
clearInterval(this.jumpModalInterval);
this.isRollbackModelvisible = false;
this.$router.push({
- path: `/leaks/task/${this.taskType}/${this.rollbackTaskId}`,
+ path: `/leaks/task/cve rollback/${this.rollbackTaskId}`,
query: {
task_id: this.rollbackTaskId
}
});
+ this.expandedRowKeys = [];
+ this.taskType = 'cve rollback';
this.taskId = this.rollbackTaskId;
localStorage.setItem('taskId', this.taskId);
this.getInitalData();
},
async generateRollbackTask() {
+ this.isRollBackButtonLoading = true;
if (this.detail.statuses['running'] > 0) {
this.$warning({
title: '有任务正在运行,不能回滚。'
});
+ this.isRollBackButtonLoading = false;
return;
}
- this.$confirm({
- title: (
- <p>
- 回滚后无法恢复
- <br />
- 请确认回滚CVE修复任务:
- </p>
- ),
- icon: () => <a-icon type="exclamation-circle" />,
- onOk: async () => {
- const res = await generateRollbackTask(this.taskId);
- if (res) {
- this.rollbackTaskId = res.data.task_id;
- this.countDown = 5;
- this.isRollbackModelvisible = true;
- this.jumpModalInterval = setInterval(() => {
- this.countDown = this.countDown - 1;
- if (this.countDown === 0) {
- clearInterval(this.jumpModalInterval);
- this.isRollbackModelvisible = false;
- }
- }, 1000);
+ const res = await generateRollbackTask(this.taskId);
+ if (res) {
+ this.rollbackTaskId = res.data.task_id;
+ this.countDown = 5;
+ this.isRollbackModelvisible = true;
+ this.jumpModalInterval = setInterval(() => {
+ this.countDown = this.countDown - 1;
+ if (this.countDown === 0) {
+ clearInterval(this.jumpModalInterval);
+ this.isRollbackModelvisible = false;
}
- }
- });
+ }, 1000);
+ this.isRollBackButtonLoading = false;
+ } else {
+ }
},
dateFormat,
-
jumptoResult(value) {
this.$router.push({
path: `/leaks/task-report/${this.taskType}/${this.taskId}`,
@@ -633,7 +633,6 @@ export default {
});
return res || null;
},
-
// 展开详情列表
async expand(expanded, record) {
if (!expanded) return;
@@ -739,7 +738,7 @@ export default {
current: pagination.current,
pageSize: pagination.pageSize
},
- filters: filters,
+ filters,
sorter: {
field: sorter.field,
order: sorter.order
@@ -770,7 +769,7 @@ export default {
return res || null;
},
// 获取热补丁回退列表
- async getCveListWithHotpathRemove() {
+ async getCveListWithHotpathRemove(needScan = false) {
this.tableIsLoading = true;
const pagination = this.pagination || {};
const filters = this.filters || {};
@@ -800,12 +799,13 @@ export default {
this.tableIsLoading = false;
await this.updateCveProgress(
this.taskId,
- res.data.result.map((cve) => cve.cve_id)
+ res.data.result.map((cve) => cve.cve_id),
+ needScan
);
}
},
- // for cve task
- async getCveList() {
+ // 获取cve列表(修复,回滚)
+ async getCveList(needScan = false) {
this.tableIsLoading = true;
const res = this.taskType === 'cve fix' ? await this.getCveListWithFix() : await this.getCveListWithRollback();
if (res) {
@@ -814,34 +814,67 @@ export default {
rpms: []
}));
this.reportvisible = this.getReportVisible(res.data.result);
- this.expandedRowKeys = [];
+ // this.expandedRowKeys = [];
this.pagination = {
...this.pagination,
total: res.data.total_count || (res.data.total_count === 0 ? 0 : this.pagination.total)
};
- await this.updateHostProgress();
+ !this.reportvisible && (await this.updateHostProgress(needScan));
this.tableIsLoading = false;
}
},
// 修复,回滚任务running时刷新列表状态
- async updateHostProgress() {
+ async updateHostProgress(needScan = false) {
clearTimeout(this.CveScanStatueTimeout);
const res = this.taskType === 'cve fix' ? await this.getCveListWithFix() : await this.getCveListWithRollback();
const progressRes = res.data.result;
- this.tableData = progressRes.map((item) => ({
- ...item,
- rpms: []
- }));
+ progressRes.forEach((item) => {
+ const i = this.tableData.findIndex((t) => t.host_id === item.host_id);
+ if (i > -1 && this.tableData[i].status !== item.status) {
+ this.tableData[i].status = item.status;
+ if (this.expandedRowKeys.includes(this.tableData[i].host_id)) this.expand(true, this.tableData[i]);
+ }
+ });
+
const list = progressRes.filter((item) => item.status === 'running');
this.reportvisible = list.length === 0;
if (list.length > 0) {
this.CveScanStatueTimeout = setTimeout(() => {
- this.updateHostProgress();
+ this.updateHostProgress(needScan);
}, configs.taskProgressUpdateInterval);
+ } else {
+ needScan && (await this.sacnHostAfterExcute());
}
},
- // 更新热补丁回退的执行进度
- async updateCveProgress(taskId, cveList) {
+
+ // 在任务执行完成之后进行主机扫描
+ async sacnHostAfterExcute() {
+ const hostList = await this.getAllHostId();
+ const res = await getHostScanStatus({hostList});
+ if (!res) return;
+ const hostStatusList = res.data.result;
+ const needScanList = Object.keys(hostStatusList).map((h) => {
+ if (hostStatusList[h] !== 3 && hostList.includes(Number(h))) return Number(h);
+ });
+ this.scanLeakAfterExecuteTask(needScanList);
+ },
+ // 返回扫描状态的主机
+ getScanningHost(scanMap, hostList) {
+ const arr = [];
+ hostList.forEach((host) => {
+ if (scanMap[host.host_id] === 3) {
+ arr.push(host);
+ }
+ });
+ return arr;
+ },
+ /**
+ * 更新热补丁回退的执行进度
+ * @param {*} taskId 任务id
+ * @param {*} cveList cve 列表
+ * @param {*} needScan 是否需要扫描主机
+ */
+ async updateCveProgress(taskId, cveList, needScan = false) {
clearTimeout(this.CveScanStatueTimeout);
const processRes = await getCveProgressUnderCveTask({
taskId,
@@ -852,8 +885,10 @@ export default {
this.runningCveIds = this.getRunningCve(processRes.data.result);
if (this.runningCveIds.length > 0) {
this.CveScanStatueTimeout = setTimeout(() => {
- this.updateCveProgress(taskId, cveList);
+ this.updateCveProgress(taskId, cveList, needScan);
}, configs.taskProgressUpdateInterval);
+ } else {
+ needScan && (await this.sacnHostAfterExcute());
}
},
// 将查询到的cve进度更新到表格数据中,用于数据展示
@@ -954,26 +989,23 @@ export default {
title: `确定执行任务${this.detail.task_name}?`,
icon: () => <a-icon type="exclamation-circle" />,
okText: '执行',
- onOk: () => {
- return executeTask(this.taskId)
- .then((res) => {
- this.$message.success(res.message);
- this.scanLeakAfterExecuteTask();
- // 执行任务成功后刷新
- setTimeout(() => {
- this.getInitalData();
- this.expandedRowKeys = [];
- }, 3000);
- })
- .catch((err) => {
- this.$message.error(err.response.message);
- });
+ onOk: async () => {
+ const excuteRes = await executeTask(this.taskId);
+ if (excuteRes) {
+ // 获取详情任务所有处理的hostid列表
+ this.$message.success(excuteRes.message);
+ // 执行任务成功后刷新
+ setTimeout(() => {
+ this.getInitalData(true);
+ this.expandedRowKeys = [];
+ }, 3000);
+ }
}
});
},
- async scanLeakAfterExecuteTask() {
+ async scanLeakAfterExecuteTask(hostList) {
await scanHost({
- hostList: this.hostList,
+ hostList,
filter: null
});
},
@@ -981,7 +1013,7 @@ export default {
async getAllHostId() {
const res = await getAllHostInDetail(this.taskId);
if (res) {
- this.hostList = res.data;
+ return res.data;
}
},
showHostListUnderCve(type, record) {
@@ -992,16 +1024,17 @@ export default {
closeHostListUnderCve() {
this.hostListUnderCveVisible = false;
},
- getInitalData() {
+ /**
+ * isFresh 是第一次初始化还是后续的刷新数据
+ */
+ getInitalData(isFresh = false) {
this.getInfo();
- // 获取详情任务所有处理的hostid列表
- this.getAllHostId();
if (this.taskType === 'repo set') {
this.getHostList();
} else if (this.taskType === 'hotpatch remove') {
- this.getCveListWithHotpathRemove();
+ this.getCveListWithHotpathRemove(isFresh);
} else {
- this.getCveList();
+ this.getCveList(isFresh);
}
},
@@ -1023,9 +1056,9 @@ export default {
}
if (this.taskType === 'cve fix' || this.taskType === 'cve rollback') {
if (text !== '') {
- this.filters.host_name = text;
+ this.filters.searchKey = text;
} else {
- this.filters.host_name = undefined;
+ this.filters.searchKey = undefined;
}
this.getCveList();
} else {
@@ -1065,7 +1098,7 @@ export default {
localStorage.setItem('taskId', this.taskId);
},
mounted() {
- this.getInitalData();
+ this.getInitalData(false);
},
beforeDestroy() {
// 离开页面前,若当前存在轮询,清除轮询
diff --git a/src/views/leaks/LeakTaskList.vue b/src/views/leaks/LeakTaskList.vue
index be0ce82..08cb5e4 100644
--- a/src/views/leaks/LeakTaskList.vue
+++ b/src/views/leaks/LeakTaskList.vue
@@ -193,6 +193,10 @@ export default {
{
text: 'cve rollback',
value: 'cve rollback'
+ },
+ {
+ text: 'hotpatch remove',
+ value: 'hotpatch remove'
}
]
},
diff --git a/src/views/leaks/TaskResultReport.vue b/src/views/leaks/TaskResultReport.vue
index ca8d031..e702b06 100644
--- a/src/views/leaks/TaskResultReport.vue
+++ b/src/views/leaks/TaskResultReport.vue
@@ -1,4 +1,3 @@
-<!-- eslint-disable vue/max-attributes-per-line -->
<template>
<page-header-wrapper :breadcrumb="breadcrumb">
<a-card :bordered="false" class="aops-theme">
@@ -30,7 +29,7 @@
{{ cveStatusTextMap[resultItem.status] }}
</a-descriptions-item>
<a-descriptions-item label="状态" v-if="resultItem.task_type === 'cve rollback'">
- {{ rollStatusTextMap[resultItem.status] }}
+ {{ rollStatusTextMap[resultItem.task_result.result] }}
</a-descriptions-item>
<a-descriptions-item label="状态" v-if="resultItem.task_type === 'repo set'">
{{ repoStatusTextMap[resultItem.task_result.status] }}
@@ -39,8 +38,13 @@
{{ resultItem.task_result.repo }}
</a-descriptions-item>
</a-descriptions>
- <p class="reuslt-item-title">检查项:</p>
- <a-row>
+ <span class="reuslt-item-title">检查项:</span>
+ <span
+ v-if="resultItem.task_result.check_items && resultItem.task_result.check_items.length === 0"
+ style="margin-left: 10px"
+ >无</span
+ >
+ <a-row v-else>
<a-col span="8">
<a-descriptions :column="{sm: 1}" bordered size="small">
<a-descriptions-item
@@ -79,33 +83,31 @@
</div>
</div>
<!-- 回滚任务 -->
- <div v-if="taskType === 'cve rollback'" style="margin-left: 50px">
- <p class="reuslt-item-title" style="margin-top: 12px">RPM回滚情况:</p>
+ <div v-if="taskType === 'cve rollback'">
+ <p class="reuslt-item-title" style="margin-top: 12px">RPM回滚详情:</p>
<a-collapse v-if="resultItem.task_result.rpms.length !== 0" :bordered="false">
<a-collapse-panel
v-for="(rpm, rkidx) in resultItem.task_result.rpms"
:key="rkidx"
- :header="`${rpm.installed_rpm}`"
+ :header="`${rpm.cves}`"
>
- <div class="cve-item">
- <p class="reuslt-item-title">结果:</p>
- {{ rollStatusTextMap[rpm.result] }}
- </div>
- <div class="cve-item">
- <p class="reuslt-item-title" style="margin-top: 12px">Log:</p>
- <p class="result-log" v-html="logFormat(rpm.log)"></p>
- </div>
- <a-badge :status="statusResultValueMap[rpm.result]" slot="extra" />
+ <p>
+ <span class="title">已安装rpm:</span>
+ <span> {{ rpm.installed_rpm }}</span>
+ </p>
+ <p>
+ <span class="title">目标rpm:</span>
+ <span> {{ rpm.target_rpm }}</span>
+ </p>
+ <a-badge :status="statusResultValueMap[resultItem.task_result.result]" slot="extra" />
</a-collapse-panel>
</a-collapse>
- <div v-else class="cve-item">
- <p class="reuslt-item-title" style="margin-top: 12px">Log:</p>
- <p class="result-log">{{ resultItem.log }}</p>
- </div>
+ <p class="reuslt-item-title" style="margin-top: 16px">Log:</p>
+ <p class="result-log" v-html="logFormat(resultItem.task_result.log)"></p>
</div>
<!-- 热补丁移除任务 -->
<div v-if="taskType === 'hotpatch remove'" style="margin-left: 50px">
- <p class="reuslt-item-title" style="margin-top: 12px">CVE修复情况:</p>
+ <p class="reuslt-item-title" style="margin-top: 12px">热补丁移除情况:</p>
<a-collapse v-if="resultItem.task_result.cves.length !== 0" :bordered="false">
<a-collapse-panel
v-for="(cve, rkidx) in resultItem.task_result.cves"
@@ -113,7 +115,7 @@
:header="`${cve.cve_id}`"
>
<div class="cve-item">
- <p class="reuslt-item-title">结果: {{ statusResultTextMap[cve.result] }}</p>
+ <p class="reuslt-item-title">结果: {{ removeStatusResult[cve.result] }}</p>
</div>
<div class="cve-item">
<p class="reuslt-item-title" style="margin-top: 12px">Log:</p>
@@ -132,7 +134,16 @@
<p class="reuslt-item-title" style="margin-top: 16px">Log:</p>
<p class="result-log">{{ resultItem.task_result.log }}</p>
</div>
- <a-badge :status="statusValueMap[resultItem.status]" slot="extra" />
+ <a-badge
+ :status="
+ taskType === 'repo set'
+ ? statusValueMap[resultItem.task_result.status]
+ : taskType === 'cve fix' || taskType === 'hotpatch remove'
+ ? statusValueMap[resultItem.status]
+ : statusValueMap[resultItem.task_result.result]
+ "
+ slot="extra"
+ />
</a-collapse-panel>
</a-collapse>
</div>
@@ -188,6 +199,13 @@ const statusResultTextMap = {
unknown: '未知'
};
+const removeStatusResult = {
+ succeed: '移除成功',
+ fail: '待移除',
+ running: '运行中',
+ unknown: '未知'
+};
+
const statusResultValueMap = {
succeed: 'success',
unfixed: 'error',
@@ -210,6 +228,13 @@ export default {
props: {
routes,
itemRender: ({route, params, routes, paths, h}) => {
+ if (route.path === '/leaks/task/:taskType/:taskId') {
+ const path = {
+ path: `/leaks/task/${this.$route.query.taskType}/${this.$route.query.taskId}`,
+ query: {taskId: this.$route.query.taskId}
+ };
+ return <router-link to={path}>{route.breadcrumbName}</router-link>;
+ }
return <router-link to={route.path}>{route.breadcrumbName}</router-link>;
}
}
@@ -218,6 +243,7 @@ export default {
},
data() {
return {
+ removeStatusResult,
taskId: this.$route.query.taskId,
taskType: this.$route.query.taskType,
latestExecuteTime: this.$route.query.latestExecuteTime,
@@ -293,6 +319,10 @@ export default {
font-weight: 500;
color: rgba(0, 0, 0, 0.85);
}
+.title {
+ font-weight: bold;
+ margin-right: 5px;
+}
/deep/ .ant-descriptions-item {
.ant-descriptions-item-label {
font-weight: 500;
diff --git a/src/views/leaks/components/CreateRepairTaskDrawer.vue b/src/views/leaks/components/CreateRepairTaskDrawer.vue
index 5977bfb..b302439 100644
--- a/src/views/leaks/components/CreateRepairTaskDrawer.vue
+++ b/src/views/leaks/components/CreateRepairTaskDrawer.vue
@@ -4,7 +4,7 @@
{{ taskTypsbutton[taskType] }}
</a-button>
<a-drawer
- :title="`生成任务${taskType === 'repo set' ? ' 设置REPO' : ''}`"
+ :title="taskTypsbutton[taskType]"
closable
@close="handleCancel"
:get-container="false"
@@ -227,7 +227,7 @@ const taskTypsbutton = {
'cve fix': '生成修复任务',
'repo set': '设置REPO',
'cve rollback': '生成回滚任务',
- 'hotpatch remove': '热补丁移除'
+ 'hotpatch remove': '热补丁移除任务'
};
const taskTypsEnum = {
'cve fix': 'cve修复',
@@ -814,25 +814,19 @@ export default {
break;
} else {
// make request
- generateTask(params)
- .then((res) => {
- this.$message.success(res.message);
- if (excuteASAP) {
- const task = res.data.filter((item) => item.fix_way === 'hotpatch');
- this.handleExcuteASAP(task[0].task_id, res.data);
- } else {
- this.visible = false;
- this.handleGenerateSuccess(res.data, 'CVE修复', 'normal');
- }
- })
- .catch((err) => {
- this.$message.error(err.response.message);
- })
- .finally(() => {
- if (!excuteASAP) {
- this.submitLoading = false;
- }
- });
+ generateTask(params).then((res) => {
+ this.$message.success(res.message);
+ if (excuteASAP) {
+ // 如果同时存在冷热补丁两种任务,则选择热补丁任务立即执行,如果只有单个任务,则执行该任务
+ const task =
+ res.data.length > 1 ? res.data.filter((item) => item.fix_way === 'hotpatch') : res.data;
+ this.handleExcuteASAP(task[0].task_id, res.data);
+ } else {
+ this.visible = false;
+ this.handleGenerateSuccess(res.data, 'CVE修复', 'normal');
+ }
+ });
+ this.submitLoading = false;
break;
}
case 'repo set':
--
Gitee
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。