Skip to content

Commit

Permalink
feat: 增加扫描执行集群配置管理页面 #2762
Browse files Browse the repository at this point in the history
* feat: 增加扫描执行集群配置管理页面 #2762

* feat: 增加扫描执行集群配置管理页面 #2762

* feat: 增加扫描执行集群配置管理页面 #2762
  • Loading branch information
lannoy0523 authored Nov 25, 2024
1 parent c8d8ca1 commit cf0f44b
Show file tree
Hide file tree
Showing 4 changed files with 441 additions and 12 deletions.
33 changes: 33 additions & 0 deletions src/frontend/devops-op/src/api/executionClusters.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import request from '@/utils/request'

const PREFIX_SERVICES = 'analyst/api/execution/clusters'

export function clusters() {
return request({
url: `${PREFIX_SERVICES}`,
method: 'get'
})
}

export function update(body) {
return request({
url: `${PREFIX_SERVICES}/${body.name}`,
method: 'put',
data: body
})
}

export function create(body) {
return request({
url: `${PREFIX_SERVICES}`,
method: 'post',
data: body
})
}

export function remove(name) {
return request({
url: `${PREFIX_SERVICES}/${name}`,
method: 'delete'
})
}
25 changes: 13 additions & 12 deletions src/frontend/devops-op/src/router/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export const ROUTER_NAME_FILE_SYSTEM_RECORD = 'FileSystemRecord'
export const ROUTER_NAME_REPO_CONFIG = 'RepoConfig'
export const ROUTER_NAME_RATE_LIMITER_CONFIG = 'RateLimiterConfig'
export const ROUTER_NAME_PRELOAD_CONFIG = 'PreloadConfig'
export const ROUTER_NAME_EXECUTION_CLUSTERS_CONFIG = 'ExecutionClustersConfig'

Vue.use(Router)

Expand Down Expand Up @@ -174,6 +175,12 @@ export const asyncRoutes = [
name: ROUTER_NAME_PROJECT_METRICS,
meta: { title: '仓库大小统计', icon: 'file' },
component: () => import('@/views/node/ProjectMetrics')
},
{
path: 'preloadConfig',
name: ROUTER_NAME_PRELOAD_CONFIG,
meta: { title: '制品预加载配置', icon: 'service-config' },
component: () => import('@/views/preload/index')
}
]
},
Expand Down Expand Up @@ -261,6 +268,12 @@ export const asyncRoutes = [
name: ROUTER_NAME_PROJECT_SCAN_CONFIGURATIONS,
component: () => import('@/views/scan/ProjectScanConfiguration'),
meta: { title: '项目配置', icon: 'setting' }
},
{
path: 'executionClustersConfig',
name: ROUTER_NAME_EXECUTION_CLUSTERS_CONFIG,
meta: { title: '扫描执行集群配置', icon: 'service-config' },
component: () => import('@/views/execution-clusters/index')
}
]
},
Expand Down Expand Up @@ -327,18 +340,6 @@ export const asyncRoutes = [
}
]
},
{
path: '/preload-config',
component: Layout,
children: [
{
path: '/',
name: ROUTER_NAME_PRELOAD_CONFIG,
meta: { title: '制品预加载配置', icon: 'service-config' },
component: () => import('@/views/preload/index')
}
]
},
// 404 page must be placed at the end !!!
{ path: '*', redirect: '/404', hidden: true }
]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,276 @@
<template>
<el-dialog :title="showMode? '详情': (createMode?'创建扫描执行集群配置':'更新扫描执行集群配置')" :visible.sync="showDialog" :before-close="close">
<el-form ref="form" :rules="rules" :model="executionCluster" status-icon label-position="left" label-width="185px">
<el-form-item ref="project-form-item" label="执行集群名" prop="name" :rules="[{ required: true, message: '执行集群名不能为空'}]">
<el-input v-model="executionCluster.name" style="height: 40px ; width: 500px;" :disabled="!createMode" />
</el-form-item>
<el-form-item ref="project-form-item" label="描述" prop="description">
<el-input v-model="executionCluster.description" style="height: 40px ; width: 500px;" :disabled="showMode" />
</el-form-item>
<el-form-item label="集群类型" prop="type">
<el-select
v-model="executionCluster.type"
placeholder="请选择"
:disabled="showMode"
>
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item v-if="executionCluster.type !== 'docker'" label="命名空间" prop="kubernetesProperties.namespace" :rules="[{ required: true, message: '命名空间不能为空'}]">
<el-input v-model="executionCluster.kubernetesProperties.namespace" style="height: 40px ; width: 500px;" :disabled="showMode" />
</el-form-item>
<el-form-item v-if="executionCluster.type !== 'docker'" label="apiServer" prop="apiServer">
<el-input v-model="executionCluster.kubernetesProperties.apiServer" style="height: 40px ; width: 500px;" :disabled="showMode" />
</el-form-item>
<el-form-item v-if="executionCluster.type !== 'docker'" label="certificateAuthorityData" prop="certificateAuthorityData">
<el-input v-model="executionCluster.kubernetesProperties.certificateAuthorityData" style="height: 40px ; width: 500px;" :disabled="showMode" />
</el-form-item>
<el-form-item v-if="executionCluster.type !== 'docker'" label="token" prop="token">
<el-input v-model="executionCluster.kubernetesProperties.token" style="height: 40px ; width: 500px;" :disabled="showMode" />
</el-form-item>
<el-form-item v-if="executionCluster.type !== 'docker'" label="clientCertificateData" prop="clientCertificateData">
<el-input v-model="executionCluster.kubernetesProperties.clientCertificateData" style="height: 40px ; width: 500px;" :disabled="showMode" />
</el-form-item>
<el-form-item v-if="executionCluster.type !== 'docker'" label="clientKeyData" prop="clientCertificateData">
<el-input v-model="executionCluster.kubernetesProperties.clientKeyData" style="height: 40px ; width: 500px;" :disabled="showMode" />
</el-form-item>
<el-form-item v-if="executionCluster.type !== 'docker'" label="最大使用内存(B)" prop="kubernetesProperties.limitMem" :rules="[{ required: true, message: '最大使用内存不能为空'}]">
<el-input-number v-model="executionCluster.kubernetesProperties.limitMem" style="height: 40px ; width: 200px;" controls-position="right" :min="1" :disabled="showMode" />
</el-form-item>
<el-form-item v-if="executionCluster.type !== 'docker'" label="最大临时内存(B)" prop="kubernetesProperties.limitStorage" :rules="[{ required: true, message: '最大临时内存不能为空'}]">
<el-input-number v-model="executionCluster.kubernetesProperties.limitStorage" style="height: 40px ; width: 200px;" controls-position="right" :min="1" :disabled="showMode" />
</el-form-item>
<el-form-item v-if="executionCluster.type !== 'docker'" label="最大cpu" prop="kubernetesProperties.limitCpu" :rules="[{ required: true, message: '最大cpu不能为空'}]">
<el-input-number v-model="executionCluster.kubernetesProperties.limitCpu" style="height: 40px ; width: 200px;" controls-position="right" :min="1" :disabled="showMode" />
</el-form-item>
<el-form-item v-if="executionCluster.type === 'k8s_job'" label="最大保留时间(秒)" prop="jobTtlSecondsAfterFinished">
<el-input-number v-model="executionCluster.jobTtlSecondsAfterFinished" style="height: 40px ; width: 200px;" controls-position="right" :min="1" :disabled="showMode" />
</el-form-item>
<el-form-item v-if="executionCluster.type === 'k8s_job'" label="执行完是否删除" prop="cleanJobAfterSuccess">
<el-switch
v-model="executionCluster.cleanJobAfterSuccess"
active-color="#13ce66"
inactive-color="#ff4949"
:disabled="showMode"
/>
</el-form-item>
<el-form-item v-if="executionCluster.type === 'k8s_deployment'" label="扫描器" prop="scanner" :rules="[{ required: true, message: '扫描器不能为空'}]">
<el-select
v-model="executionCluster.scanner"
placeholder="请选择"
:disabled="showMode"
>
<el-option
v-for="item in scannerOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item v-if="executionCluster.type === 'k8s_deployment'" label="最大副本数" prop="maxReplicas" :rules="[{ required: true, message: '最大副本数不能为空'}]">
<el-input-number v-model="executionCluster.maxReplicas" style="height: 40px ; width: 200px;" controls-position="right" :min="1" :disabled="showMode" />
</el-form-item>
<el-form-item v-if="executionCluster.type === 'k8s_deployment'" label="最小副本数" prop="minReplicas" :rules="[{ required: true, message: '最小副本数不能为空'}]">
<el-input-number v-model="executionCluster.minReplicas" style="height: 40px ; width: 200px;" controls-position="right" :min="1" :disabled="showMode" />
</el-form-item>
<el-form-item v-if="executionCluster.type === 'k8s_deployment'" label="扩容阈值" prop="scaleThreshold" :rules="[{ required: true, message: '扩容阈值不能为空'}]">
<el-input-number v-model="executionCluster.scaleThreshold" style="height: 40px ; width: 200px;" controls-position="right" :min="1" :disabled="showMode" />
</el-form-item>
<el-form-item v-if="executionCluster.type === 'k8s_deployment'" label="扫描器重试次数" prop="pullRetry" :rules="[{ required: true, message: '扫描器重试次数不能为空'}]">
<el-input-number v-model="executionCluster.pullRetry" style="height: 40px ; width: 200px;" controls-position="right" :min="1" :disabled="showMode" />
</el-form-item>
<el-form-item v-if="executionCluster.type === 'docker'" label="host" prop="host" :rules="[{ required: true, message: 'host不能为空'}]">
<el-input v-model="executionCluster.host" style="height: 40px ; width: 500px;" :disabled="showMode" />
</el-form-item>
<el-form-item v-if="executionCluster.type === 'docker'" label="版本" prop="version" :rules="[{ required: true, message: '版本不能为空'}]">
<el-input v-model="executionCluster.version" style="height: 40px ; width: 500px;" :disabled="showMode" />
</el-form-item>
<el-form-item v-if="executionCluster.type === 'docker'" label="连接超时时长(毫秒)" prop="connectTimeout" :rules="[{ required: true, message: '连接超时时长不能为空'}]">
<el-input-number v-model="executionCluster.connectTimeout" style="height: 40px ; width: 200px;" controls-position="right" :min="0" :disabled="showMode" />
</el-form-item>
<el-form-item v-if="executionCluster.type === 'docker'" label="读取超时时长(毫秒)" prop="readTimeout" :rules="[{ required: true, message: '读取超时时长不能为空'}]">
<el-input-number v-model="executionCluster.readTimeout" style="height: 40px ; width: 200px;" controls-position="right" :min="0" :disabled="showMode" />
</el-form-item>
<el-form-item v-if="executionCluster.type === 'docker'" label="最大任务数" prop="maxTaskCount" :rules="[{ required: true, message: '最大任务数不能为空'}]">
<el-input-number v-model="executionCluster.maxTaskCount" style="height: 40px ; width: 200px;" controls-position="right" :min="0" :disabled="showMode" />
</el-form-item>
</el-form>
<div v-if="!showMode" slot="footer">
<el-button @click="close">取 消</el-button>
<el-button type="primary" @click="handleUpdate()">确 定</el-button>
</div>
</el-dialog>
</template>
<script>
import _ from 'lodash'
import { scanners } from '@/api/scan'
import { create, update } from '@/api/executionClusters'
export default {
name: 'EditClusterConfigDialog',
props: {
visible: Boolean,
createMode: {
type: Boolean,
default: false
},
showMode: {
type: Boolean,
default: false
},
/**
* 仅在更新模式时有值
*/
updatingClusterConfig: {
type: Object,
default: undefined
}
},
data() {
return {
repoCache: {},
showDialog: this.visible,
executionCluster: this.newCluster(),
data: '',
rules: {},
options: [
{ value: 'k8s_job',
label: 'k8s_job' },
{ value: 'k8s_deployment',
label: 'k8s_deployment'
},
{ value: 'docker',
label: 'docker' }
],
scannerOptions: []
}
},
watch: {
visible: function(newVal) {
if (newVal) {
this.resetStrategy()
this.showDialog = true
} else {
this.close()
}
}
},
created() {
scanners().then(res => {
res.data.forEach(item => {
const scanner = {
label: item.name,
value: item.name
}
this.scannerOptions.push(scanner)
})
})
},
methods: {
resetStrategy() {
if (this.createMode) {
this.executionCluster = this.newCluster()
} else {
this.executionCluster = _.cloneDeep(this.updatingClusterConfig)
if (!this.executionCluster.kubernetesProperties) {
this.executionCluster.kubernetesProperties = {
namespace: '',
apiServer: '',
certificateAuthorityData: '',
token: '',
clientCertificateData: '',
clientKeyData: '',
limitMem: 1,
limitStorage: 1,
limitCpu: 1
}
}
}
this.$nextTick(() => {
this.$refs['form'].clearValidate()
})
},
newCluster() {
const Cluster = {
name: '',
type: 'k8s_job',
description: '',
kubernetesProperties: {
namespace: '',
apiServer: '',
certificateAuthorityData: '',
token: '',
clientCertificateData: '',
clientKeyData: '',
limitMem: 1,
limitStorage: 1,
limitCpu: 1
},
jobTtlSecondsAfterFinished: 1,
cleanJobAfterSuccess: true,
scanner: '',
maxReplicas: 1,
minReplicas: 1,
scaleThreshold: 1,
pullRetry: 1,
host: 'unix://var/run/docker.sock',
version: '1.23',
connectTimeout: 5000,
readTimeout: 0,
maxTaskCount: 1
}
return Cluster
},
close(changed) {
this.showDialog = false
this.$refs['form'].resetFields()
if (changed === true) {
this.$emit('updated')
}
this.$emit('update:visible', false)
},
handleUpdate() {
this.$refs['form'].validate((valid) => {
if (valid) {
if (this.executionCluster.kubernetesProperties.apiServer === '') {
this.executionCluster.kubernetesProperties.apiServer === null
}
if (this.executionCluster.kubernetesProperties.certificateAuthorityData === '') {
this.executionCluster.kubernetesProperties.certificateAuthorityData === null
}
if (this.executionCluster.kubernetesProperties.token === '') {
this.executionCluster.kubernetesProperties.token === null
}
if (this.executionCluster.kubernetesProperties.clientCertificateData === '') {
this.executionCluster.kubernetesProperties.clientCertificateData === null
}
if (this.executionCluster.kubernetesProperties.clientKeyData === '') {
this.executionCluster.kubernetesProperties.clientKeyData === null
}
if (this.createMode) {
create(this.executionCluster).then(() => {
this.$message.success('新建配置成功')
this.close(true)
})
} else {
update(this.executionCluster).then(() => {
this.$message.success('更新配置成功')
this.close(true)
})
}
}
})
}
}
}
</script>

<style scoped>
</style>
Loading

0 comments on commit cf0f44b

Please sign in to comment.