Projects
Eulaceura:Mainline:GA
aops-hermes
_service:obs_scm:001-bugfix-and-adapt-rollback-...
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:obs_scm:001-bugfix-and-adapt-rollback-tasks.patch of Package aops-hermes
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
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2