From 24ea849db3e600a92718bc8318226f838646a687 Mon Sep 17 00:00:00 2001
From: Hu gang <18768366022@163.com>
Date: Mon, 18 Dec 2023 09:30:17 +0800
Subject: [PATCH] fix adapt rollback tasks and fix some bug
(cherry picked from commit 64fc4858726c896d6d5064d59c1ea9370b182ded)
---
001-bugfix-and-adapt-rollback-tasks.patch | 1025 +++++++++++++++++++++
002-fix-hotpatch-remove-filter.patch | 24 +
003-change-search-placeholder.patch | 24 +
004-modify-search-key-for-hostlist.patch | 38 +
aops-hermes-v1.4.0.tar.gz | Bin 883781 -> 765190 bytes
aops-hermes.spec | 18 +-
6 files changed, 1126 insertions(+), 3 deletions(-)
create mode 100644 001-bugfix-and-adapt-rollback-tasks.patch
create mode 100644 002-fix-hotpatch-remove-filter.patch
create mode 100644 003-change-search-placeholder.patch
create mode 100644 004-modify-search-key-for-hostlist.patch
diff --git a/001-bugfix-and-adapt-rollback-tasks.patch b/001-bugfix-and-adapt-rollback-tasks.patch
new file mode 100644
index 0000000..a389f0b
--- /dev/null
+++ b/001-bugfix-and-adapt-rollback-tasks.patch
@@ -0,0 +1,1025 @@
+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();
+ }
+ };
+
+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 @@
+
+
+
+- 重置条件
++
++
+
+
+
+@@ -59,26 +60,19 @@
+ >{{ hostName }}
+ {{ isMana ? '是' : '否' }}
+- {{ hostStatusMap[status] }}
++
++
++ {{ hostStatusMap[status] }}
++
+ {{ scene ? (scene === 'normal' ? '通用' : scene) : '暂无' }}
+
+-
+ 编辑
+- |
+- 删除
++ >编辑
++
++ 删除
+
+-
+
+
+
+@@ -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 @@
+
+
+
+- 生成回滚任务
++ 生成回滚任务
+
+
+
+@@ -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: (
+-
+- 回滚后无法恢复
+-
+- 请确认回滚CVE修复任务:
+-
+- ),
+- icon: () => ,
+- 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: () => ,
+ 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 @@
+-
+
+
+
+@@ -30,7 +29,7 @@
+ {{ cveStatusTextMap[resultItem.status] }}
+
+
+- {{ rollStatusTextMap[resultItem.status] }}
++ {{ rollStatusTextMap[resultItem.task_result.result] }}
+
+
+ {{ repoStatusTextMap[resultItem.task_result.status] }}
+@@ -39,8 +38,13 @@
+ {{ resultItem.task_result.repo }}
+
+
+- 检查项:
+-
++ 检查项:
++ 无
++
+
+
+
+
+
+-
+-
RPM回滚情况:
++
++
RPM回滚详情:
+
+
+-
+-
结果:
+- {{ rollStatusTextMap[rpm.result] }}
+-
+-
+-
++
++ 已安装rpm:
++ {{ rpm.installed_rpm }}
++
++
++ 目标rpm:
++ {{ rpm.target_rpm }}
++
++
+
+
+-
+-
Log:
+-
{{ resultItem.log }}
+-
++
Log:
++
+
+
+
+-
CVE修复情况:
++
热补丁移除情况:
+
+
+
+-
结果: {{ statusResultTextMap[cve.result] }}
++
结果: {{ removeStatusResult[cve.result] }}
+
+
+
Log:
+@@ -132,7 +134,16 @@
+
Log:
+
{{ resultItem.task_result.log }}
+
+-
++
+
+
+
+@@ -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
{route.breadcrumbName};
++ }
+ return
{route.breadcrumbName};
+ }
+ }
+@@ -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] }}
+
+
{
+- 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
diff --git a/002-fix-hotpatch-remove-filter.patch b/002-fix-hotpatch-remove-filter.patch
new file mode 100644
index 0000000..8f600eb
--- /dev/null
+++ b/002-fix-hotpatch-remove-filter.patch
@@ -0,0 +1,24 @@
+From a747433cfaf40104eb56d9d3dea6d86ed5d5b82d Mon Sep 17 00:00:00 2001
+From: Hu gang <18768366022@163.com>
+Date: Mon, 18 Dec 2023 10:27:00 +0800
+Subject: [PATCH] fix: fix hotpathch remove filter failed
+
+---
+ src/views/leaks/LeakTaskDetail.vue | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/src/views/leaks/LeakTaskDetail.vue b/src/views/leaks/LeakTaskDetail.vue
+index f7f7438..00438d7 100644
+--- a/src/views/leaks/LeakTaskDetail.vue
++++ b/src/views/leaks/LeakTaskDetail.vue
+@@ -661,6 +661,8 @@ export default {
+ // 出发排序、筛选、分页时,重新请求主机列表
+ if (this.taskType === 'cve fix' || this.taskType === 'cve rollback') {
+ this.getCveList();
++ } else if (this.taskType === 'hotpatch remove') {
++ this.getCveListWithHotpathRemove();
+ } else {
+ this.getHostList();
+ }
+--
+Gitee
diff --git a/003-change-search-placeholder.patch b/003-change-search-placeholder.patch
new file mode 100644
index 0000000..86caad3
--- /dev/null
+++ b/003-change-search-placeholder.patch
@@ -0,0 +1,24 @@
+From 2cc872cddbc8331941507167b23a977aa0b543ad Mon Sep 17 00:00:00 2001
+From: Hu gang <18768366022@163.com>
+Date: Mon, 18 Dec 2023 11:05:17 +0800
+Subject: [PATCH] chore: change search input palceholder
+
+---
+ src/views/leaks/LeakTaskDetail.vue | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/views/leaks/LeakTaskDetail.vue b/src/views/leaks/LeakTaskDetail.vue
+index 00438d7..766a1cf 100644
+--- a/src/views/leaks/LeakTaskDetail.vue
++++ b/src/views/leaks/LeakTaskDetail.vue
+@@ -103,7 +103,7 @@
+
+
+
+--
+Gitee
diff --git a/004-modify-search-key-for-hostlist.patch b/004-modify-search-key-for-hostlist.patch
new file mode 100644
index 0000000..e5585ec
--- /dev/null
+++ b/004-modify-search-key-for-hostlist.patch
@@ -0,0 +1,38 @@
+From 3289156212ecda06c35ace47af0a6033ff41ea1d Mon Sep 17 00:00:00 2001
+From: Hu gang <18768366022@163.com>
+Date: Mon, 18 Dec 2023 15:17:42 +0800
+Subject: [PATCH] chore: change search key
+
+---
+ src/views/assests/HostManagement.vue | 2 +-
+ src/views/leaks/LeakTaskDetail.vue | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/src/views/assests/HostManagement.vue b/src/views/assests/HostManagement.vue
+index 77e0ed8..e3c1635 100644
+--- a/src/views/assests/HostManagement.vue
++++ b/src/views/assests/HostManagement.vue
+@@ -18,7 +18,7 @@
+
+
+
+-
++
+
+
+
+diff --git a/src/views/leaks/LeakTaskDetail.vue b/src/views/leaks/LeakTaskDetail.vue
+index 766a1cf..81f0a88 100644
+--- a/src/views/leaks/LeakTaskDetail.vue
++++ b/src/views/leaks/LeakTaskDetail.vue
+@@ -103,7 +103,7 @@
+
+
+
+--
+Gitee
diff --git a/aops-hermes-v1.4.0.tar.gz b/aops-hermes-v1.4.0.tar.gz
index 59650412f9cb1cf38ec92a9d01e921c3b77df5c2..7b38de4c8ba8cf241854754b3dcc1e09714735fc 100644
GIT binary patch
literal 765190
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