Skip to content

Commit cf0f44b

Browse files
authored
feat: 增加扫描执行集群配置管理页面 #2762
* feat: 增加扫描执行集群配置管理页面 #2762 * feat: 增加扫描执行集群配置管理页面 #2762 * feat: 增加扫描执行集群配置管理页面 #2762
1 parent c8d8ca1 commit cf0f44b

File tree

4 files changed

+441
-12
lines changed

4 files changed

+441
-12
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import request from '@/utils/request'
2+
3+
const PREFIX_SERVICES = 'analyst/api/execution/clusters'
4+
5+
export function clusters() {
6+
return request({
7+
url: `${PREFIX_SERVICES}`,
8+
method: 'get'
9+
})
10+
}
11+
12+
export function update(body) {
13+
return request({
14+
url: `${PREFIX_SERVICES}/${body.name}`,
15+
method: 'put',
16+
data: body
17+
})
18+
}
19+
20+
export function create(body) {
21+
return request({
22+
url: `${PREFIX_SERVICES}`,
23+
method: 'post',
24+
data: body
25+
})
26+
}
27+
28+
export function remove(name) {
29+
return request({
30+
url: `${PREFIX_SERVICES}/${name}`,
31+
method: 'delete'
32+
})
33+
}

src/frontend/devops-op/src/router/index.js

+13-12
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export const ROUTER_NAME_FILE_SYSTEM_RECORD = 'FileSystemRecord'
2626
export const ROUTER_NAME_REPO_CONFIG = 'RepoConfig'
2727
export const ROUTER_NAME_RATE_LIMITER_CONFIG = 'RateLimiterConfig'
2828
export const ROUTER_NAME_PRELOAD_CONFIG = 'PreloadConfig'
29+
export const ROUTER_NAME_EXECUTION_CLUSTERS_CONFIG = 'ExecutionClustersConfig'
2930

3031
Vue.use(Router)
3132

@@ -174,6 +175,12 @@ export const asyncRoutes = [
174175
name: ROUTER_NAME_PROJECT_METRICS,
175176
meta: { title: '仓库大小统计', icon: 'file' },
176177
component: () => import('@/views/node/ProjectMetrics')
178+
},
179+
{
180+
path: 'preloadConfig',
181+
name: ROUTER_NAME_PRELOAD_CONFIG,
182+
meta: { title: '制品预加载配置', icon: 'service-config' },
183+
component: () => import('@/views/preload/index')
177184
}
178185
]
179186
},
@@ -261,6 +268,12 @@ export const asyncRoutes = [
261268
name: ROUTER_NAME_PROJECT_SCAN_CONFIGURATIONS,
262269
component: () => import('@/views/scan/ProjectScanConfiguration'),
263270
meta: { title: '项目配置', icon: 'setting' }
271+
},
272+
{
273+
path: 'executionClustersConfig',
274+
name: ROUTER_NAME_EXECUTION_CLUSTERS_CONFIG,
275+
meta: { title: '扫描执行集群配置', icon: 'service-config' },
276+
component: () => import('@/views/execution-clusters/index')
264277
}
265278
]
266279
},
@@ -327,18 +340,6 @@ export const asyncRoutes = [
327340
}
328341
]
329342
},
330-
{
331-
path: '/preload-config',
332-
component: Layout,
333-
children: [
334-
{
335-
path: '/',
336-
name: ROUTER_NAME_PRELOAD_CONFIG,
337-
meta: { title: '制品预加载配置', icon: 'service-config' },
338-
component: () => import('@/views/preload/index')
339-
}
340-
]
341-
},
342343
// 404 page must be placed at the end !!!
343344
{ path: '*', redirect: '/404', hidden: true }
344345
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,276 @@
1+
<template>
2+
<el-dialog :title="showMode? '详情': (createMode?'创建扫描执行集群配置':'更新扫描执行集群配置')" :visible.sync="showDialog" :before-close="close">
3+
<el-form ref="form" :rules="rules" :model="executionCluster" status-icon label-position="left" label-width="185px">
4+
<el-form-item ref="project-form-item" label="执行集群名" prop="name" :rules="[{ required: true, message: '执行集群名不能为空'}]">
5+
<el-input v-model="executionCluster.name" style="height: 40px ; width: 500px;" :disabled="!createMode" />
6+
</el-form-item>
7+
<el-form-item ref="project-form-item" label="描述" prop="description">
8+
<el-input v-model="executionCluster.description" style="height: 40px ; width: 500px;" :disabled="showMode" />
9+
</el-form-item>
10+
<el-form-item label="集群类型" prop="type">
11+
<el-select
12+
v-model="executionCluster.type"
13+
placeholder="请选择"
14+
:disabled="showMode"
15+
>
16+
<el-option
17+
v-for="item in options"
18+
:key="item.value"
19+
:label="item.label"
20+
:value="item.value"
21+
/>
22+
</el-select>
23+
</el-form-item>
24+
<el-form-item v-if="executionCluster.type !== 'docker'" label="命名空间" prop="kubernetesProperties.namespace" :rules="[{ required: true, message: '命名空间不能为空'}]">
25+
<el-input v-model="executionCluster.kubernetesProperties.namespace" style="height: 40px ; width: 500px;" :disabled="showMode" />
26+
</el-form-item>
27+
<el-form-item v-if="executionCluster.type !== 'docker'" label="apiServer" prop="apiServer">
28+
<el-input v-model="executionCluster.kubernetesProperties.apiServer" style="height: 40px ; width: 500px;" :disabled="showMode" />
29+
</el-form-item>
30+
<el-form-item v-if="executionCluster.type !== 'docker'" label="certificateAuthorityData" prop="certificateAuthorityData">
31+
<el-input v-model="executionCluster.kubernetesProperties.certificateAuthorityData" style="height: 40px ; width: 500px;" :disabled="showMode" />
32+
</el-form-item>
33+
<el-form-item v-if="executionCluster.type !== 'docker'" label="token" prop="token">
34+
<el-input v-model="executionCluster.kubernetesProperties.token" style="height: 40px ; width: 500px;" :disabled="showMode" />
35+
</el-form-item>
36+
<el-form-item v-if="executionCluster.type !== 'docker'" label="clientCertificateData" prop="clientCertificateData">
37+
<el-input v-model="executionCluster.kubernetesProperties.clientCertificateData" style="height: 40px ; width: 500px;" :disabled="showMode" />
38+
</el-form-item>
39+
<el-form-item v-if="executionCluster.type !== 'docker'" label="clientKeyData" prop="clientCertificateData">
40+
<el-input v-model="executionCluster.kubernetesProperties.clientKeyData" style="height: 40px ; width: 500px;" :disabled="showMode" />
41+
</el-form-item>
42+
<el-form-item v-if="executionCluster.type !== 'docker'" label="最大使用内存(B)" prop="kubernetesProperties.limitMem" :rules="[{ required: true, message: '最大使用内存不能为空'}]">
43+
<el-input-number v-model="executionCluster.kubernetesProperties.limitMem" style="height: 40px ; width: 200px;" controls-position="right" :min="1" :disabled="showMode" />
44+
</el-form-item>
45+
<el-form-item v-if="executionCluster.type !== 'docker'" label="最大临时内存(B)" prop="kubernetesProperties.limitStorage" :rules="[{ required: true, message: '最大临时内存不能为空'}]">
46+
<el-input-number v-model="executionCluster.kubernetesProperties.limitStorage" style="height: 40px ; width: 200px;" controls-position="right" :min="1" :disabled="showMode" />
47+
</el-form-item>
48+
<el-form-item v-if="executionCluster.type !== 'docker'" label="最大cpu" prop="kubernetesProperties.limitCpu" :rules="[{ required: true, message: '最大cpu不能为空'}]">
49+
<el-input-number v-model="executionCluster.kubernetesProperties.limitCpu" style="height: 40px ; width: 200px;" controls-position="right" :min="1" :disabled="showMode" />
50+
</el-form-item>
51+
<el-form-item v-if="executionCluster.type === 'k8s_job'" label="最大保留时间(秒)" prop="jobTtlSecondsAfterFinished">
52+
<el-input-number v-model="executionCluster.jobTtlSecondsAfterFinished" style="height: 40px ; width: 200px;" controls-position="right" :min="1" :disabled="showMode" />
53+
</el-form-item>
54+
<el-form-item v-if="executionCluster.type === 'k8s_job'" label="执行完是否删除" prop="cleanJobAfterSuccess">
55+
<el-switch
56+
v-model="executionCluster.cleanJobAfterSuccess"
57+
active-color="#13ce66"
58+
inactive-color="#ff4949"
59+
:disabled="showMode"
60+
/>
61+
</el-form-item>
62+
<el-form-item v-if="executionCluster.type === 'k8s_deployment'" label="扫描器" prop="scanner" :rules="[{ required: true, message: '扫描器不能为空'}]">
63+
<el-select
64+
v-model="executionCluster.scanner"
65+
placeholder="请选择"
66+
:disabled="showMode"
67+
>
68+
<el-option
69+
v-for="item in scannerOptions"
70+
:key="item.value"
71+
:label="item.label"
72+
:value="item.value"
73+
/>
74+
</el-select>
75+
</el-form-item>
76+
<el-form-item v-if="executionCluster.type === 'k8s_deployment'" label="最大副本数" prop="maxReplicas" :rules="[{ required: true, message: '最大副本数不能为空'}]">
77+
<el-input-number v-model="executionCluster.maxReplicas" style="height: 40px ; width: 200px;" controls-position="right" :min="1" :disabled="showMode" />
78+
</el-form-item>
79+
<el-form-item v-if="executionCluster.type === 'k8s_deployment'" label="最小副本数" prop="minReplicas" :rules="[{ required: true, message: '最小副本数不能为空'}]">
80+
<el-input-number v-model="executionCluster.minReplicas" style="height: 40px ; width: 200px;" controls-position="right" :min="1" :disabled="showMode" />
81+
</el-form-item>
82+
<el-form-item v-if="executionCluster.type === 'k8s_deployment'" label="扩容阈值" prop="scaleThreshold" :rules="[{ required: true, message: '扩容阈值不能为空'}]">
83+
<el-input-number v-model="executionCluster.scaleThreshold" style="height: 40px ; width: 200px;" controls-position="right" :min="1" :disabled="showMode" />
84+
</el-form-item>
85+
<el-form-item v-if="executionCluster.type === 'k8s_deployment'" label="扫描器重试次数" prop="pullRetry" :rules="[{ required: true, message: '扫描器重试次数不能为空'}]">
86+
<el-input-number v-model="executionCluster.pullRetry" style="height: 40px ; width: 200px;" controls-position="right" :min="1" :disabled="showMode" />
87+
</el-form-item>
88+
<el-form-item v-if="executionCluster.type === 'docker'" label="host" prop="host" :rules="[{ required: true, message: 'host不能为空'}]">
89+
<el-input v-model="executionCluster.host" style="height: 40px ; width: 500px;" :disabled="showMode" />
90+
</el-form-item>
91+
<el-form-item v-if="executionCluster.type === 'docker'" label="版本" prop="version" :rules="[{ required: true, message: '版本不能为空'}]">
92+
<el-input v-model="executionCluster.version" style="height: 40px ; width: 500px;" :disabled="showMode" />
93+
</el-form-item>
94+
<el-form-item v-if="executionCluster.type === 'docker'" label="连接超时时长(毫秒)" prop="connectTimeout" :rules="[{ required: true, message: '连接超时时长不能为空'}]">
95+
<el-input-number v-model="executionCluster.connectTimeout" style="height: 40px ; width: 200px;" controls-position="right" :min="0" :disabled="showMode" />
96+
</el-form-item>
97+
<el-form-item v-if="executionCluster.type === 'docker'" label="读取超时时长(毫秒)" prop="readTimeout" :rules="[{ required: true, message: '读取超时时长不能为空'}]">
98+
<el-input-number v-model="executionCluster.readTimeout" style="height: 40px ; width: 200px;" controls-position="right" :min="0" :disabled="showMode" />
99+
</el-form-item>
100+
<el-form-item v-if="executionCluster.type === 'docker'" label="最大任务数" prop="maxTaskCount" :rules="[{ required: true, message: '最大任务数不能为空'}]">
101+
<el-input-number v-model="executionCluster.maxTaskCount" style="height: 40px ; width: 200px;" controls-position="right" :min="0" :disabled="showMode" />
102+
</el-form-item>
103+
</el-form>
104+
<div v-if="!showMode" slot="footer">
105+
<el-button @click="close">取 消</el-button>
106+
<el-button type="primary" @click="handleUpdate()">确 定</el-button>
107+
</div>
108+
</el-dialog>
109+
</template>
110+
<script>
111+
import _ from 'lodash'
112+
import { scanners } from '@/api/scan'
113+
import { create, update } from '@/api/executionClusters'
114+
115+
export default {
116+
name: 'EditClusterConfigDialog',
117+
props: {
118+
visible: Boolean,
119+
createMode: {
120+
type: Boolean,
121+
default: false
122+
},
123+
showMode: {
124+
type: Boolean,
125+
default: false
126+
},
127+
/**
128+
* 仅在更新模式时有值
129+
*/
130+
updatingClusterConfig: {
131+
type: Object,
132+
default: undefined
133+
}
134+
},
135+
data() {
136+
return {
137+
repoCache: {},
138+
showDialog: this.visible,
139+
executionCluster: this.newCluster(),
140+
data: '',
141+
rules: {},
142+
options: [
143+
{ value: 'k8s_job',
144+
label: 'k8s_job' },
145+
{ value: 'k8s_deployment',
146+
label: 'k8s_deployment'
147+
},
148+
{ value: 'docker',
149+
label: 'docker' }
150+
],
151+
scannerOptions: []
152+
}
153+
},
154+
watch: {
155+
visible: function(newVal) {
156+
if (newVal) {
157+
this.resetStrategy()
158+
this.showDialog = true
159+
} else {
160+
this.close()
161+
}
162+
}
163+
},
164+
created() {
165+
scanners().then(res => {
166+
res.data.forEach(item => {
167+
const scanner = {
168+
label: item.name,
169+
value: item.name
170+
}
171+
this.scannerOptions.push(scanner)
172+
})
173+
})
174+
},
175+
methods: {
176+
resetStrategy() {
177+
if (this.createMode) {
178+
this.executionCluster = this.newCluster()
179+
} else {
180+
this.executionCluster = _.cloneDeep(this.updatingClusterConfig)
181+
if (!this.executionCluster.kubernetesProperties) {
182+
this.executionCluster.kubernetesProperties = {
183+
namespace: '',
184+
apiServer: '',
185+
certificateAuthorityData: '',
186+
token: '',
187+
clientCertificateData: '',
188+
clientKeyData: '',
189+
limitMem: 1,
190+
limitStorage: 1,
191+
limitCpu: 1
192+
}
193+
}
194+
}
195+
this.$nextTick(() => {
196+
this.$refs['form'].clearValidate()
197+
})
198+
},
199+
newCluster() {
200+
const Cluster = {
201+
name: '',
202+
type: 'k8s_job',
203+
description: '',
204+
kubernetesProperties: {
205+
namespace: '',
206+
apiServer: '',
207+
certificateAuthorityData: '',
208+
token: '',
209+
clientCertificateData: '',
210+
clientKeyData: '',
211+
limitMem: 1,
212+
limitStorage: 1,
213+
limitCpu: 1
214+
},
215+
jobTtlSecondsAfterFinished: 1,
216+
cleanJobAfterSuccess: true,
217+
scanner: '',
218+
maxReplicas: 1,
219+
minReplicas: 1,
220+
scaleThreshold: 1,
221+
pullRetry: 1,
222+
host: 'unix://var/run/docker.sock',
223+
version: '1.23',
224+
connectTimeout: 5000,
225+
readTimeout: 0,
226+
maxTaskCount: 1
227+
}
228+
return Cluster
229+
},
230+
close(changed) {
231+
this.showDialog = false
232+
this.$refs['form'].resetFields()
233+
if (changed === true) {
234+
this.$emit('updated')
235+
}
236+
this.$emit('update:visible', false)
237+
},
238+
handleUpdate() {
239+
this.$refs['form'].validate((valid) => {
240+
if (valid) {
241+
if (this.executionCluster.kubernetesProperties.apiServer === '') {
242+
this.executionCluster.kubernetesProperties.apiServer === null
243+
}
244+
if (this.executionCluster.kubernetesProperties.certificateAuthorityData === '') {
245+
this.executionCluster.kubernetesProperties.certificateAuthorityData === null
246+
}
247+
if (this.executionCluster.kubernetesProperties.token === '') {
248+
this.executionCluster.kubernetesProperties.token === null
249+
}
250+
if (this.executionCluster.kubernetesProperties.clientCertificateData === '') {
251+
this.executionCluster.kubernetesProperties.clientCertificateData === null
252+
}
253+
if (this.executionCluster.kubernetesProperties.clientKeyData === '') {
254+
this.executionCluster.kubernetesProperties.clientKeyData === null
255+
}
256+
if (this.createMode) {
257+
create(this.executionCluster).then(() => {
258+
this.$message.success('新建配置成功')
259+
this.close(true)
260+
})
261+
} else {
262+
update(this.executionCluster).then(() => {
263+
this.$message.success('更新配置成功')
264+
this.close(true)
265+
})
266+
}
267+
}
268+
})
269+
}
270+
}
271+
}
272+
</script>
273+
274+
<style scoped>
275+
276+
</style>

0 commit comments

Comments
 (0)