merge from private branch

This commit is contained in:
ann 2022-03-17 15:57:24 +08:00
parent 483d9fa56c
commit cdb24ade09
43 changed files with 826 additions and 360 deletions

13
package-lock.json generated
View File

@ -11759,10 +11759,9 @@
}
},
"nanoid": {
"version": "3.1.30",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.30.tgz",
"integrity": "sha512-zJpuPDwOv8D2zq2WRoMe1HsfZthVewpel9CAvTfc/2mBD1uUT/agc5f7GHGWXlYkFvi1mVxe4IjvP2HNrop7nQ==",
"dev": true
"version": "1.0.2",
"resolved": "https://registry.npmmirror.com/nanoid/download/nanoid-1.0.2.tgz",
"integrity": "sha512-sCTwJt690lduNHyqknXJp8pRwzm80neOLGaiTHU2KUJZFVSErl778NNCIivEQCX5gNT0xR1Jy3HEMe/TABT6lw=="
},
"nanomatch": {
"version": "1.2.13",
@ -13668,6 +13667,12 @@
"postcss": "^8.3.6"
},
"dependencies": {
"nanoid": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz",
"integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==",
"dev": true
},
"postcss": {
"version": "8.3.11",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.3.11.tgz",

View File

@ -1,13 +1,53 @@
import request from '@/utils/request'
// cpu 内存状态获取
export function getUsageStatus() {
// 概览统计
export function getDashboardCounts() {
return request({
url: '/virtual/v1/metrics.k8s.io.nodes',
url: '/virtual/v1/harvester/counts',
method: 'get'
})
}
// 概览事件
export function getDashboardEvents() {
return request({
url: '/virtual/v1/harvester/events',
method: 'get'
})
}
// 概览info
export function getDashboardInfo() {
return request({
url: '/virtual/v1/harvester/nodes',
method: 'get'
})
}
// 概览获取内存cpu使用量
export function getUsageStatus() {
return request({
url: '/virtual/v1/harvester/pods',
method: 'get'
})
}
// 概览获取存储数据
export function getStorageStatus() {
return request({
url: '/virtual/v1/harvester/longhorn.io.nodes',
method: 'get'
})
}
// cpu 内存状态获取
// export function getUsageStatus() {
// return request({
// url: '/virtual/v1/metrics.k8s.io.nodes',
// method: 'get'
// })
// }
// cpu 内存状态获取
export function getUsageStatusByName(name) {
return request({
@ -88,16 +128,24 @@ export function getDataVolume() {
})
}
// 虚拟机管理-卷列表 新
export function getDataVolumeNew() {
return request({
url: '/virtual/v1/harvester/persistentvolumeclaims',
method: 'get'
})
}
export function getDataVolumeYaml(name) {
return request({
url: '/virtual/apis/cdi.kubevirt.io/v1beta1/namespaces/default/datavolumes/' + name,
url: '/virtual/api/v1/namespaces/default/persistentvolumeclaims/' + name,
method: 'get'
})
}
export function putDataVolumeYaml(name, yaml) {
return request({
url: '/virtual/v1/cdi.kubevirt.io.datavolumes/default/' + name,
url: '/virtual/v1/harvester/persistentvolumeclaims/default/' + name,
method: 'put',
data: yaml
})
@ -105,14 +153,14 @@ export function putDataVolumeYaml(name, yaml) {
export function editDataVolume(name, data) {
return request({
url: '/virtual/v1/cdi.kubevirt.io.datavolumes/default/' + name,
url: '/virtual/v1/harvester/persistentvolumeclaims/default/' + name,
method: 'put',
data: data
})
}
export function createDataVolume(data) {
return request({
url: '/virtual/v1/cdi.kubevirt.io.datavolumes',
url: '/virtual/v1/harvester/persistentvolumeclaims',
method: 'post',
data: data
})
@ -120,7 +168,7 @@ export function createDataVolume(data) {
export function deleteDataVolume(name) {
return request({
url: '/virtual/v1/cdi.kubevirt.io.datavolumes/default/' + name,
url: '/virtual/v1/harvester/persistentvolumeclaims/default/' + name,
method: 'delete'
})
}
@ -169,6 +217,12 @@ export function createImages(data) {
data: data
})
}
export function deleteImage(name) {
return request({
url: '/virtual/v1/harvester/harvesterhci.io.virtualmachineimages/default/' + name,
method: 'delete'
})
}
export function getImagesYaml(name) {
return request({
url: '/virtual/apis/harvesterhci.io/v1beta1/namespaces/default/virtualmachineimages/' + name,

View File

@ -47,6 +47,19 @@ export default {
})
},
// 获取镜像列表
getImagesList() {
return request({
url: process.env.VUE_APP_BASE_API + '/dockerhub/api/content/v1/products/search?image_filter=official&page_size=50&type=image',
method: 'get'
})
},
getImagesInfo(namespace, imageName) {
return request({
url: process.env.VUE_APP_BASE_API + `/kapis/resources.kubesphere.io/v1alpha2/registry/blob?namespace=${namespace}&image=${imageName}`
})
},
getStorageInfo(clusterName, namespace, name) {
return request({
// 存储管理
@ -89,15 +102,15 @@ export default {
data: { metadata: { annotations: query.metadata.annotations }}
})
}
if (classification === 'deployments') {
return request({
// 无传namespace是项目编辑信息的接口 /api/clusters/bj-member2/v1/namespaces/kube-federation-system
// 工作负载里 部署,有状态副本集,守护进程集
url: process.env.VUE_APP_BASE_API + `${namespace ? '/apis' + clusterName + '/apps' + '' : '/api' + clusterName}/v1/namespaces/${namespace ? namespace + '/' + (classification || 'deployments') + '/' + podName : podName}`,
method: 'patch',
data: query
})
}
// if (classification === 'deployments') {
return request({
// 无传namespace是项目编辑信息的接口 /api/clusters/bj-member2/v1/namespaces/kube-federation-system
// 工作负载里 部署,有状态副本集,守护进程集
url: process.env.VUE_APP_BASE_API + `${namespace ? '/apis' + clusterName + '/apps' + '' : '/api' + clusterName}/v1/namespaces/${namespace ? namespace + '/' + (classification || 'deployments') + '/' + podName : podName}`,
method: 'patch',
data: query
})
// }
},
// 编辑配置文件
editSetting(clusterName, namespace, name, query, classification) {
@ -210,9 +223,55 @@ export default {
})
},
// 工作负载提交前check
getWorkloadCheck(clusterName, namespaces, type, name) {
// http://10.105.20.3:30880/apis/clusters/fedjcce-ten002/apps/v1/namespaces/test-zhangjie/deployments?labelSelector=app%3Dasd
return request({
url: process.env.VUE_APP_BASE_API + `/apis${clusterName}/apps/v1/namespaces/${namespaces}/${type}?labelSelector=app%3D${name}`,
method: 'get',
headers: {
'x-check-exist': true
}
})
},
// 工作负载新建
getWorkloadCreate(clusterName, namespaces, type, data) {
// http://10.105.20.3:30880/apis/clusters/fedjcce-ten002/apps/v1/namespaces/test-zhangjie/deployments?dryRun=All
return request({
url: process.env.VUE_APP_BASE_API + `/apis${clusterName}/apps/v1/namespaces/${namespaces}/${type}?dryRun=All`,
method: 'post',
data: data,
headers: {
'Content-Type': 'application/json'
}
})
},
// 工作负载提交
postWorkload(clusterName, namespaces, type, data) {
return request({
url: process.env.VUE_APP_BASE_API + `/apis${clusterName}/apps/v1/namespaces/${namespaces}/${type}`,
method: 'post',
data: data,
headers: {
'Content-Type': 'application/json'
}
})
},
// http://119.45.100.73:30880/apis/apps/v1/namespaces/kubesphere-system/deployments/tower
// 工作负载名称check
getWorkloadNameCheck(clusterName, type, name) {
return request({
url: process.env.VUE_APP_BASE_API + `/apis${clusterName}/apps/v1/${type}/${name}`,
method: 'get',
headers: {
'x-check-exist': true
}
})
},
// 工作负载名称重复check
getWorkloadNameCheck(clusterName, namespace, type, name) {
getWorkloadNameandNamespaceCheck(clusterName, namespace, type, name) {
return request({
url: process.env.VUE_APP_BASE_API + `/apis${clusterName}/v1/namespaces/${namespace}/${type}/${name}`,
method: 'get',

View File

@ -74,7 +74,7 @@ export function getRamAverage(start, end, step) {
// 计量计费接口总价格
export function getMeasure(start, end, step) {
return request({
url: process.env.VUE_APP_BASE_API + '/kapis/clusters/fedjcce-ten002/metering.kubesphere.io/v1alpha1/cluster' + '?start=' + start + '&end=' + end + '&step=' + step + 's&metrics_filter=meter_cluster_cpu_usage%7Cmeter_cluster_memory_usage%7Cmeter_cluster_net_bytes_transmitted%7Cmeter_cluster_net_bytes_received%7Cmeter_cluster_pvc_bytes_total&resources_filter=fedjcce-ten002',
url: process.env.VUE_APP_BASE_API + '/kapis/clusters/host/metering.kubesphere.io/v1alpha1/cluster' + '?start=' + start + '&end=' + end + '&step=' + step + 's&metrics_filter=meter_cluster_cpu_usage%7Cmeter_cluster_memory_usage%7Cmeter_cluster_net_bytes_transmitted%7Cmeter_cluster_net_bytes_received%7Cmeter_cluster_pvc_bytes_total&resources_filter=host',
method: 'get',
data: JSON,
headers: {
@ -98,7 +98,7 @@ export function getRamLoad(start, end, step) {
// 计量计费列表接口
export function getMeteringList(start, end, step) {
return request({
url: process.env.VUE_APP_BASE_API + '/kapis/clusters/fedjcce-ten002/metering.kubesphere.io/v1alpha1/cluster' + '?start=' + start + '&end=' + end + '&step=' + step + 's&metrics_filter=meter_cluster_cpu_usage%7Cmeter_cluster_memory_usage%7Cmeter_cluster_net_bytes_transmitted%7Cmeter_cluster_net_bytes_received%7Cmeter_cluster_pvc_bytes_total&resources_filter=fedjcce-ten002',
url: process.env.VUE_APP_BASE_API + '/kapis/clusters/host/metering.kubesphere.io/v1alpha1/cluster' + '?start=' + start + '&end=' + end + '&step=' + step + 's&metrics_filter=meter_cluster_cpu_usage%7Cmeter_cluster_memory_usage%7Cmeter_cluster_net_bytes_transmitted%7Cmeter_cluster_net_bytes_received%7Cmeter_cluster_pvc_bytes_total&resources_filter=host',
method: 'get',
data: JSON,
headers: {
@ -110,7 +110,7 @@ export function getMeteringList(start, end, step) {
// CPU整体负载接口
export function getCpuAllload(start, end) {
return request({
url: '/monitoringscreen/api/v1/query_range?query=node_load15%7Binstance%3D~%22jcc-txy-001%22%7D&start=' + start + '&end=' + end + '&step=900&_=1645409802467',
url: '/monitoringscreen/api/v1/query_range?query=node_load15%7Binstance%3D~%22k8s-master%22%7D&start=' + start + '&end=' + end + '&step=900&_=1645409802467',
method: 'get',
data: JSON,
headers: {

View File

@ -8,9 +8,9 @@ export function getServiceDetails(url1, url2) {
})
}
// 服务创建
export function createService(url, param) {
export function createService(name, url, param) {
return request({
url: process.env.VUE_APP_BASE_API + `/api/clusters/host/v1/namespaces/` + url + `/services`,
url: process.env.VUE_APP_BASE_API + `/api${name}/v1/namespaces/` + url + `/services`,
contentType: 'application/json',
method: 'post',
headers: {

BIN
src/assets/img/bg_logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
src/assets/img/cluster.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 KiB

BIN
src/assets/img/virtual.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -10,7 +10,7 @@
<span class="tips">对容器的名称及容器的计算资源进行设置</span>
</p>
<el-form-item label="镜像" required="">
<el-input v-model="createContainerForm.image" placeholder="点击右侧图标可选择镜像,或直接输入名称 例nginx:latest">
<el-input v-model="createContainerForm.image" placeholder="点击右侧图标可选择镜像,或直接输入名称 例nginx:latest" @blur="selectMirror">
<template slot="prepend">DockerHub</template>
<el-select slot="append" v-model="createContainerForm.image" filterable class="selectPro" placeholder="选择已有镜像" @change="selectMirror">
<el-option
@ -62,36 +62,45 @@
<span class="tips">设置容器的访问策略</span>
</p>
<div>
<el-form-item
v-for="(tag, index) in createContainerForm.ports"
:key="'tag'+index"
label=""
>
<span style="width:50%; display:block;float:left">{{ item.label }}{{ item.alias?'('+item.alias+')':'' }}存储类型{{ item.storageClassName }}</span>
<span style="width:10%;display:block;float:left; color: #8492a6; font-size: 13px">容量{{ item.storage }}</span>
<span style="width:40%; display:block;float:left; text-align:right">访问模式{{ item.accessModes }}</span>
<!-- </el-option>
</el-select> -->
</el-form-item>
<table>
<tr>
<td>容器</td>
<td>container-9lxa15</td>
<td>
<el-select v-model="createContainerForm.readOnly">
<el-option
v-for="item in mountOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</td>
<td><el-input v-model="createContainerForm.mountPath" :disabled="!createContainerForm.readOnly || createContainerForm.readOnly === 'null'" placeholder="容器挂载路径, 例如: /data" /></td>
</tr>
</table>
<div>
<el-form-item
v-for="(tag, index) in createContainerForm.ports"
:key="'tag'+index"
label=""
>
<el-row :gutter="10">
<el-col :span="7">
<el-tooltip
class="item"
effect="dark"
content="为了充分利用应用治理的能力,请选择服务实际使用的协议。例如,如果服务暴露的是 HTTP 服务,则选择 http 协议,会生成形如 http-[name] 的端口名称。"
placement="top-start"
>
<i class="el-icon-question" />
</el-tooltip>
协议
<el-select v-model="tag.protocol" @change="selectPolicy(tag)">
<el-option
v-for="item in protocolOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-col>
<el-col :span="7">
名称
<el-input v-model="tag.name" style="width:80%" />
</el-col>
<el-col :span="7">
容器端口
<el-input v-model="tag.containerPort" style="width:80%" />
</el-col>
<el-col :span="3"><el-button icon="el-icon-delete" circle @click.prevent="removeTag(tag,index)" /></el-col>
</el-row>
</el-form-item>
<el-button type="primary" plain round :disabled="addTagNumCheck" @click="addTag">添加端口</el-button>
</div>
</div></div></el-form>
<div slot="footer" class="dialog-footer">
<el-button icon="el-icon-close" circle @click="dialogVisible = false" />
@ -113,7 +122,18 @@ export default {
},
formData: {
type: Object,
default: () => {}
default: () => {
return {
ports: [],
securityContext: {
seLinuxOptions: {}
}
}
}
},
namespace: {
type: String,
default: ''
}
// isEdit: {
// type: Boolean,
@ -122,15 +142,8 @@ export default {
},
data() {
return {
createContainerForm: {
ports: [],
securityContext: {
seLinuxOptions: {}
}
},
imageList: [],
activeName: 'first',
namespace: '',
imageData: undefined,
noImage: false,
loading: false,
@ -157,6 +170,14 @@ export default {
this.$emit('input', value)
}
},
createContainerForm: {
get() {
return this.formData
},
set(value) {
// this.$emit('input', value)
}
},
addTagNumCheck() {
let flag = false
this.createContainerForm.ports.forEach(e => {
@ -169,11 +190,12 @@ export default {
},
watch: {
// 'createContainerForm.image'(newVal) {
// throttle(this.selectMirror(), 300)
// throttle(this.selectMirror(), 800)
// }
},
mounted() {
this.getVolumeList()
moment.locale('zh-cn')
this.getImageList()
},
methods: {
selectPolicy(tag) {
@ -188,12 +210,14 @@ export default {
},
selectMirror() {
//
if (!this.createContainerForm.image) {
return false
}
this.loading = true
this.$Api.getImagesInfo(this.namespace, this.createContainerForm.image).then(res => {
// if status === 'fail'
//
// if status === 'succeeded'
console.log(res.status)
if (res.status === 'succeeded') {
const layers = res.imageManifest.layers
const size = layers.reduce((prev, layer) => prev + layer.size, 0)
@ -241,7 +265,6 @@ export default {
servicePort: containerPort
}
})
console.log(ports)
if (!isEmpty(ports)) {
this.createContainerForm.ports = ports
}
@ -249,8 +272,10 @@ export default {
ok() {
// generate('0123456789abcdefghijklmnopqrstuvwxyz', length || 6)
const container = Object.assign(this.createContainerForm)
// TODO container
if (!this.createContainerForm.name) {
container.name = 'container-' + generate('0123456789abcdefghijklmnopqrstuvwxyz', 6)
container.imagePullPolicy = 'IfNotPresent'
this.$emit('addImage', container)
} else {
this.$emit('editImage', container)
@ -269,5 +294,18 @@ export default {
</script>
<style lang="scss" scoped>
.border{
border: 1px solid #DCDFE6;
padding: 10px;
margin-bottom: 10px;
}
.grayCard{
background: #eeeeee;
p{margin: 0;}
.tips{
margin-top: 0;
margin-bottom: 5px;
}
table td{padding: 0 5px; border: 0!important;}
}
</style>

View File

@ -50,17 +50,17 @@
</el-form-item>
</el-tab-pane>
</el-tabs>
<table>
<tr>
<table v-if="formData.spec.template.spec.containers">
<tr v-for="(item, index) in formData.spec.template.spec.containers" :key="index" class="dataList">
<td>容器</td>
<td>container-9lxa15</td>
<td>{{ item }}</td>
<td>
<el-select v-model="createVolumesForm.readOnly">
<el-option
v-for="item in mountOptions"
:key="item.value"
:label="item.label"
:value="item.value"
v-for="it in mountOptions"
:key="it.value"
:label="it.label"
:value="it.value"
/>
</el-select>
</td>

View File

@ -95,7 +95,7 @@ export default {
this.$Api.editInfo(this.clusterName, formData.metadata.namespace || null, this.editInfoForm.name, formData, this.classification).then(res => {
this.$message.success('操作成功')
this.dialogFormVisible = false
// this.$refs.multipleTable.getList()
this.$emit('getList')
})
}
}

View File

@ -174,6 +174,7 @@
<script>
import { createService, checkServiceName } from '@/api/second-class-page/serviceInfo'
import { getStorageProject } from '@/api/one-class-page/storageManagement'
import addKeyandValue from '@/components/addKeyandValue'
import { validStorageName } from '@/utils/validate'
@ -193,7 +194,6 @@ export default {
} else if (!validStorageName(value)) {
callback(new Error('名称格式不合法'))
} else {
console.log(111)
const res = await checkServiceName(this.clusterName, value, this.formData.namespace)
if (res.exist) {
callback(new Error('名称已存在。请使用其他名称。'))
@ -305,7 +305,6 @@ export default {
},
methods: {
changeInput(current, target, key) {
console.log(111)
this.formData[target][key] = this.formData[current]
},
prev() {
@ -316,9 +315,8 @@ export default {
},
//
setFilterMapNamespaceList() {
this.$Api.getNamespaceList().then(res => {
const arr = res.items.map(e => { return { label: e.metadata.name, value: e.metadata.name, disabled: e.metadata.isFedManaged, isFedManaged: e.metadata.isFedManaged } })
this.options1 = arr
getStorageProject(this.clusterName, { page: 1, limit: 9999 }).then(res => {
this.options1 = res.items.map(item => ({ label: item.metadata.name, value: item.metadata.name, disabled: item.metadata.isFedManaged, isFedManaged: item.metadata.isFedManaged }))
})
},
create() {
@ -363,9 +361,8 @@ export default {
...this.formData.annotations
}
}
console.log(volumeData)
const url = this.formData.namespace
createService(url, volumeData).then(res => {
createService(this.clusterName, url, volumeData).then(res => {
this.$message.success('创建成功')
this.dialogSettingVisible = false
this.$emit('getList')

View File

@ -61,11 +61,16 @@
<script>
import { set } from 'lodash'
import { getStorageProject } from '@/api/one-class-page/storageManagement'
export default {
props: {
value: {
type: Object,
default: () => {}
},
classification: {
type: String,
default: ''
}
},
data() {
@ -86,8 +91,7 @@ export default {
},
{ validator: this.nameValidator }
]
},
namespace: ''
}
}
},
computed: {
@ -111,7 +115,18 @@ export default {
editInfoForm: {
handler(newName, oldName) {
//
this.submitInfoEdit()
// console.log(newName)
const { name, alias, description, namespace } = this.editInfoForm
set(this.formData, 'metadata.labels.app', name)
set(this.formData, 'metadata.name', name)
set(this.formData, 'metadata.labels.app', name)
set(this.formData, 'spec.selector.matchLabels.app', name)
set(this.formData, 'spec.template.metadata.labels.app', name)
set(this.formData, "metadata.annotations['kubesphere.io/alias-name']", alias)
set(this.formData, "metadata.annotations['kubesphere.io/alias-description']", description)
set(this.formData, "metadata.annotations['kubesphere.io/creator']", 'admin')
set(this.formData, 'metadata.namespace', namespace)
// set(this.formData, 'spec.template.metadata.annotations[logging.kubesphere.io/logsidecar-config]', '{}')
},
deep: true
}
@ -121,24 +136,12 @@ export default {
},
methods: {
setFilterMapNamespaceList() {
this.$Api.getNamespaceList().then(res => {
const arr = res.items.map(e => { return { label: e.metadata.name, value: e.metadata.name, disabled: e.metadata.isFedManaged, isFedManaged: e.metadata.isFedManaged } })
this.namespaceOptions = arr
getStorageProject(this.clusterName, { page: 1, limit: 9999 }).then(res => {
this.namespaceOptions = res.items.map(item => ({ label: item.metadata.name, value: item.metadata.name, disabled: item.metadata.isFedManaged, isFedManaged: item.metadata.isFedManaged }))
})
},
submitInfoEdit() {
// when formData is empty do this
const { name, alias, description, namespace } = this.editInfoForm
set(this.formData, 'metadata.labels.app', name)
set(this.formData, 'metadata.name', name)
set(this.formData, 'metadata.labels.app', name)
set(this.formData, 'spec.selector.matchLabels.app', name)
set(this.formData, 'spec.template.metadata.lables.app', name)
set(this.formData, 'metadata.annotations[kubesphere.io/alias-name]', alias)
set(this.formData, 'metadata.annotations[kubesphere.io/alias-description]', description)
set(this.formData, 'metadata.annotations[kubesphere.io/creator]', 'admin')
set(this.formData, 'metadata.namespace', namespace)
set(this.formData, 'spec.template.metadata.annotations[logging.kubesphere.io/logsidecar-config]', '{}')
// this.formData = {
// apiVersion: 'v1',
@ -178,12 +181,20 @@ export default {
// }
// }
},
submitNameCheck() {
this.$Api.getWorkloadNameandNamespaceCheck(this.clusterName, this.editInfoForm.namespace, this.classification, this.editInfoForm.name).then(res => {
if (res.exist) {
this.$message.warning('名称已存在')
} else {
this.$emit('checkSuccess', true)
}
})
},
nameValidator(rule, value, callback) {
if (!value) {
return callback()
}
this.$Api.getWorkloadNameCheck(this.clusterName, this.namespace, this.type, value).then(res => {
this.$Api.getWorkloadNameCheck(this.clusterName, this.classification, value).then(res => {
if (res.exist) {
return callback({ message: '名称已存在', field: rule.field })
}

View File

@ -14,13 +14,14 @@
</el-button>
<div v-if="editInfoForm.spec.template.spec.containers">
<div v-for="(item, index) in editInfoForm.spec.template.spec.containers" :key="index" class="dataList">
<i class="el-icon-receiving" />
<div>{{ item.name }}</div>
<el-button icon="el-icon-delete" circle @click.prevent="removeContainer(index)" />
<el-button icon="el-icon-edit" circle @click.prevent="editContainer(item)" />
<div><i class="el-icon-receiving" />{{ item.name }}</div>
<div>镜像{{ item.image }}</div>
</div>
</div>
<addContainerForm v-model="containerFormVisiable" :form-data="formData" @addImage="addImage" @editImage="editImage" />
<addContainerForm v-if="containerFormVisiable" v-model="containerFormVisiable" :namespace="editInfoForm.metadata.namespace" :form-data="containerForm" @addImage="addImage" @editImage="editImage" />
<!-- <el-form-item
prop="mirror"
label="更新策略"
@ -220,6 +221,7 @@ export default {
},
data() {
return {
containerForm: undefined,
policysOptions,
policysTypeOptions,
namespaceOptions: [],
@ -263,11 +265,14 @@ export default {
},
methods: {
addImage(data) {
console.log(this.editInfoForm.spec.template.spec.containers)
this.editInfoForm.spec.template.spec.containers.push(data)
console.log(data)
console.log(this.editInfoForm.spec.template.spec.containers.length)
// console.log(data)
this.containerForm = undefined
},
editImage(data) {
console.log(data)
// console.log(data)
},
setFilterMapNamespaceList() {
this.$Api.getNamespaceList().then(res => {
@ -280,6 +285,13 @@ export default {
},
removeTag(tag, index) {
this.editTagForm.splice(index, 1)
},
removeContainer(index) {
this.editInfoForm.spec.template.spec.containers.splice(index, 1)
},
editContainer(item) {
this.containerForm = item
this.containerFormVisiable = true
}
}
}
@ -287,6 +299,14 @@ export default {
<style lang="scss">
.createForm {
.dataList{
border: 1px solid #DCDFE6;
margin-top: 10px;
padding:10px;
.el-button{
float:right;
}
}
.selectRadio{
width: 100%;
height: 50px!important;

View File

@ -1,20 +1,20 @@
<template>
<el-dialog v-if="createFormVisible" width="80%" title="创建项目" :visible.sync="createFormVisible">
<el-dialog v-if="createFormVisible" width="80%" :title="'创建'+typeMap[classification]" :visible.sync="createFormVisible">
<el-steps :active="stepNum" finish-status="success" simple>
<el-step title="基本信息" />
<el-step title="容器镜像" />
<el-step title="挂载存储" />
<el-step title="高级设置" />
</el-steps>
{{ metaData }}
<basicInfoForm v-show="stepNum===0" v-model="metaData" />
<basicInfoForm v-show="stepNum===0" ref="basicInfoForm" v-model="metaData" :classification="classification" @checkSuccess="handleCheckSuccess()" />
<containerImage v-if="stepNum===1" v-model="metaData" />
<mountVolumes v-if="stepNum===2" v-model="metaData" />
<advancedSettings v-if="stepNum===3" v-model="metaData" />
<div slot="footer" class="dialog-footer">
<el-button @click="createFormVisible = false"> </el-button>
<el-button v-if="stepNum!==0" type="primary" @click="prev">上一步</el-button>
<el-button type="primary" @click="next">下一步</el-button>
<el-button v-if="stepNum!==3" type="primary" @click="next">下一步</el-button>
<el-button v-else type="primary" @click="createWorkload">创建</el-button>
</div>
</el-dialog>
</template>
@ -46,6 +46,11 @@ export default {
},
data() {
return {
typeMap: {
deployments: '部署',
statefulsets: '有状态副本集',
daemonsets: '守护进程集'
},
stepNum: 0,
metaData: {},
baseYaml: `apiVersion: apps/v1
@ -57,11 +62,16 @@ spec:
selector:
matchLabels: {}
template:
metadata:
metadata: {
labels: {}
}
spec:
containers: []
serviceAccount: default
affinity: {}
initContainers: []
volumes: []
imagePullSecrets: null
strategy:
type: RollingUpdate
rollingUpdate:
@ -71,6 +81,13 @@ spec:
}
},
computed: {
clusterName() {
if (localStorage.getItem('clusterName') === 'default') {
return ''
} else {
return '/clusters/' + localStorage.getItem('clusterName')
}
},
createFormVisible: {
get() {
return this.value
@ -85,6 +102,21 @@ spec:
this.transformYaml()
},
methods: {
createWorkload() {
this.$Api.getWorkloadCheck(this.clusterName, this.metaData.metadata.namespace, this.classification, this.metaData.metadata.labels.app).then(res => {
if (res.exist) {
this.$message.warning('名称已存在')
} else {
this.$Api.getWorkloadCreate(this.clusterName, this.metaData.metadata.namespace, this.classification, this.metaData).then(() => {
this.$Api.postWorkload(this.clusterName, this.metaData.metadata.namespace, this.classification, this.metaData).then(() => {
this.$message.success('创建成功!')
this.createFormVisible = false
this.$emit('getList')
})
})
}
})
},
transformYaml() {
this.metaData = JSON.parse(JSON.stringify(yaml.load(this.baseYaml), null, 2))
},
@ -92,6 +124,13 @@ spec:
this.stepNum--
},
next() {
if (this.stepNum === 0) {
this.$refs.basicInfoForm.submitNameCheck()
} else {
this.stepNum++
}
},
handleCheckSuccess() {
this.stepNum++
}
}
@ -101,4 +140,5 @@ spec:
.el-steps{
margin-bottom: 15px;
}
</style>

View File

@ -2,7 +2,8 @@
<div>
<p>挂载存储</p>
dataList
<!-- dataList -->
<!-- <i class="el-icon-receiving" />
<i class="el-icon-setting" />
<i class="el-icon-key" /> -->
@ -16,7 +17,7 @@
<span class="tips">将配置文件或密钥挂载至指定目录</span>
</el-button>
</el-button-group>
<addVolumesForm v-model="createFormVisible" :form-data="formData" @addVolumes="addVolumes" />
<addVolumesForm v-model="createFormVisible" :form-data="editInfoForm" @addVolumes="addVolumes" />
</div>
</template>
@ -24,6 +25,12 @@
import addVolumesForm from '@/components/Actions/addVolumesForm.vue'
export default {
components: { addVolumesForm },
props: {
value: {
type: Object,
default: () => {}
}
},
data() {
return {
createFormVisible: false,
@ -31,6 +38,16 @@ export default {
formData: {}
}
},
computed: {
editInfoForm: {
get() {
return this.value
},
set(value) {
this.$emit('input', value)
}
}
},
methods: {
addVolumes() {}
}

View File

@ -6,7 +6,7 @@
<div class="right-menu">
<router-link v-if="routesType==='cluster'" class="selectBtn" to="/clusterSelect">多集群管理</router-link>
<a class="selectBtn" @click="toContainerCost">计量计费</a>
<!-- <a class="selectBtn" @click="toContainerCost">计量计费</a> -->
<router-link class="selectBtn" to="/monitorSelect">资源管理</router-link>
<template v-if="device!=='mobile'">
<!-- <search id="header-search" class="right-menu-item" /> -->
@ -87,18 +87,19 @@ export default {
},
methods: {
toMoniter() {
const clusterName = localStorage.getItem('clusterName')
switch (clusterName) {
case 'fedjcce-member2':
window.open('http://121.89.220.60:3000/d/9CWBz0bik/cluster-ali?orgId=1', '_blank')
break
case 'fedjcce-member1':
window.open('http://121.89.220.60:3000/d/9CWBz0bi34/cluster-huawei?orgId=1', '_blank')
break
default:
window.open('http://121.89.220.60:3000/d/9CWBz0bi/cluster-tencent?orgId=1', '_blank')
break
}
// const clusterName = localStorage.getItem('clusterName')
// switch (clusterName) {
// case 'fedjcce-member2':
// window.open('http://121.89.220.60:3000/d/9CWBz0bik/cluster-ali?orgId=1', '_blank')
// break
// case 'fedjcce-member1':
// window.open('http://121.89.220.60:3000/d/9CWBz0bi34/cluster-huawei?orgId=1', '_blank')
// break
// default:
// window.open('http://121.89.220.60:3000/d/9CWBz0bi/cluster-tencent?orgId=1', '_blank')
// break
// }
window.open('https://www.jointcloud.net/dashboard/dashboards', '_blank')
},
toContainerCost() {
this.$store.dispatch('user/setRouteType', 'containerCost')
@ -120,14 +121,14 @@ export default {
height: 60px;
overflow: hidden;
position: relative;
background: #fff;
box-shadow: 0 1px 4px rgba(0,21,41,.08);
// background: #fff;
// box-shadow: 0 1px 4px rgba(0,21,41,.08);
.selectBtn{
line-height: 67px;
height: 60px;
float: left;
border-right: 1px solid #eeeeee;
border-left: 1px solid #eeeeee;
// border-right: 1px solid #eeeeee;
// border-left: 1px solid #eeeeee;
padding: 0 20px;
}
.navbar .right-menu .right-menu-item.hover-effect{
@ -164,6 +165,7 @@ export default {
float: right;
height: 100%;
line-height: 50px;
font-size: 14px;
&:focus {
outline: none;
}
@ -172,7 +174,6 @@ export default {
display: inline-block;
padding: 0 8px;
height: 100%;
font-size: 18px;
color: #5a5e66;
vertical-align: text-bottom;

View File

@ -22,7 +22,18 @@ export default {
// 删除接口 成功后
this.$Api.deleteCurrent(this.clusterName, namespace, name, classification).then(res => {
this.$message.success('删除成功')
if (from === 'list') { this.$refs.multipleTable.getList() } else { this.goBack() }
if (from === 'list') {
if (text === '项目') {
this.getList()
setTimeout(() => {
this.getList()
}, 10000)
} else {
this.$refs.multipleTable.getList()
}
} else {
this.goBack()
}
})
}).catch(() => {
})

View File

@ -1,4 +1,4 @@
import { login, blockChainLogin } from '@/api/user'
import { login, harvesterLogin, blockChainLogin } from '@/api/user'
import { getToken, setToken, removeToken } from '@/utils/auth'
import { resetRouter } from '@/router'
@ -57,14 +57,14 @@ const actions = {
const { username, password } = userInfo
return Promise.all([
login({ 'username': username.trim(), 'encrypt': encrypt('kubesphere', password) }),
// harvesterLogin({ 'username': 'admin', 'password': 'Nudt@123', 'description': 'UI Session', 'responseType': 'cookie', 'ttl': 57600000 }),
harvesterLogin({ 'username': 'admin', 'password': 'xNudt@123456', 'description': 'UI Session', 'responseType': 'cookie', 'ttl': 57600000 }),
blockChainLogin({
'user': 'exploreradmin',
'password': 'exploreradminpw',
'network': 'agridepart-network'
})]).then(response => {
commit('SET_TOKEN', response[1].token)
setToken(response[1].token)
commit('SET_TOKEN', response[2].token)
setToken(response[2].token)
// Cookies.set('bToken', response[2].token)
})
},

View File

@ -2,7 +2,7 @@ import { getVolume } from '@/api/one-class-page/storageManagement'
import { getNodeMessage, getNodeStatus } from '@/api/one-class-page/nodeManagement'
import { getByValue } from '@/utils/data-process'
import { getDaemonSets, getDeployments, getPods, getServices, getStatefulSets } from '@/api/one-class-page/workloadManagement'
import { getUsageStatus, getVirtualHosts, getVirtualMachinesInstances, getDataVolume, getImages } from '@/api/one-class-page/virtualMachine'
import { getUsageStatus, getVirtualHosts, getVirtualMachinesInstances, getDataVolumeNew, getImages } from '@/api/one-class-page/virtualMachine'
// import { getImages } from '@/api/one-class-page/virtualMachine'
import {
getBriefSystemProject,
@ -11,7 +11,7 @@ import {
getDetailUserProject
} from '@/api/one-class-page/projectManagement'
import { getHostNum, getMemberNum } from '@/api/one-class-page/cluster'
import { strToNumber } from '@/utils/data-process'
// import { strToNumber } from '@/utils/data-process'
function getStatus(readyReplicas, replicas) {
if (readyReplicas === replicas) {
@ -242,7 +242,7 @@ const getUserProjectList = (clusterName, params) => {
const customUrl = baseUrl + items.map(function(v) { return v.metadata.name }).join('%7C') + '%24&metrics_filter=namespace_cpu_usage%7Cnamespace_memory_usage_wo_cache%7Cnamespace_pod_count%24'
getDetailUserProject(customUrl).then(re => {
const { results } = re
results.map((v) => { v.data.result.map((s) => { items[getByValue(namespace, s.metric.namespace)][v.metric_name] = s.value[1] }) })
results.map((v) => { v.data?.result?.map((s) => { items[getByValue(namespace, s.metric.namespace)][v.metric_name] = s.value[1] }) })
listResult = items
resolve({ total: res.totalItems, rows: listResult })
})
@ -260,7 +260,7 @@ const getSystemProjectList = (clusterName, params) => {
const customUrl = baseUrl + items.map(function(v) { return v.metadata.name }).join('%7C') + '%24&metrics_filter=namespace_cpu_usage%7Cnamespace_memory_usage_wo_cache%7Cnamespace_pod_count%24'
getDetailSystemProject(customUrl).then(re => {
const { results } = re
results.map((v) => { v.data.result.map((s) => { items[getByValue(namespace, s.metric.namespace)][v.metric_name] = s.value[1] }) })
results.map((v) => { v.data?.result?.map((s) => { items[getByValue(namespace, s.metric.namespace)][v.metric_name] = s.value[1] }) })
listResult = items
resolve({ total: res.totalItems, rows: listResult })
})
@ -293,7 +293,7 @@ const getVirtualMachineList = (clusterName, params) => {
obj.aliveTime = obj.aliveTime.replace('h', '小时')
obj.aliveTime = obj.aliveTime.replace('h', '小时')
obj.cpu = res.data[item].spec.domain.cpu.cores
obj.memory = res.data[item].spec.domain.resources.requests.memory
obj.memory = res.data[item].spec.domain.memory.guest
obj.ipAddress = res.data[item].metadata.fields[3]
obj.node = res.data[item].metadata.fields[4]
obj.label = res.data[item].metadata.labels['harvesterhci.io/creator']
@ -322,7 +322,7 @@ const getVirtualHostList = () => {
obj.aliveTime = res.data[item].metadata.fields[3]
obj.aliveTime = obj.aliveTime.replace('d', '天')
obj.aliveTime = obj.aliveTime.replace('h', '小时')
obj.cpuUsed = parseFloat((parseInt(usage.data[item].usage.cpu) / 1000000000).toFixed(2))
obj.cpuUsed = parseFloat((parseInt(usage?.data[item]?.usage?.cpu || 0) / 1000000000).toFixed(2))
obj.cpuAll = parseInt(res.data[item].status.capacity.cpu)
obj.cpuUsePercentage = parseFloat((obj.cpuUsed / obj.cpuAll).toFixed(2)) * 100
obj.memoryUsed = parseFloat((parseInt(usage.data[item].usage.memory) / 1024 / 1024).toFixed(2))
@ -347,37 +347,32 @@ const getVirtualHostList = () => {
const getDataVolumeList = () => {
return new Promise(function(resolve) {
const listResult = []
getDataVolume().then((res) => {
// console.log(res)
for (let item = 0; item < res.data.length; item++) {
var obj = {}
obj.index = item
obj.name = res.data[item].metadata.name
if (res.data[item].metadata.ownerReferences) { obj.state = 'In-Use' } else { obj.state = 'Ready' }
obj.phase = res.data[item].metadata.fields[1]
if (obj.phase !== null) { if (obj.phase === 'Pending') { obj.tagtype = 'warning' } else obj.tagtype = 'success' } else {
obj.tagtype = 'info'
obj.phase = '未运行'
let listResult = []
getDataVolumeNew().then((res) => {
const data = res.data
for (let i = 0; i < data.length; i++) {
listResult[i] = {
namespace: data[i].metadata.namespace,
index: i,
name: data[i].metadata.name,
tagtype: data[i].metadata.fields[1] === null ? 'info' : (data[i].metadata.fields[1] === 'Pending' ? 'warning' : 'success'),
phase: data[i].metadata.fields[1],
size: data[i].spec.resources.requests.storage,
aliveTime: data[i].metadata.fields[6].replace('h', '小时').replace('d', '天').replace('m', '分'),
creationTime: data[i].metadata.creationTimestamp,
vm: ''
}
obj.progress = res.data[item].metadata.fields[2]
if (obj.progress !== null) {
if (obj.progress === 'N/A') { obj.state = 'Not-Ready' } else { obj.progress = strToNumber(obj.progress.slice(0, -1)) }
} else obj.progress = 0
obj.aliveTime = res.data[item].metadata.fields[4]
obj.aliveTime = obj.aliveTime.replace('h', '小时')
obj.aliveTime = obj.aliveTime.replace('d', '天')
obj.aliveTime = obj.aliveTime.replace('m', '分')
obj.creationTime = res.data[item].metadata.creationTimestamp
if (res.data[item].metadata.ownerReferences) {
obj.vm = res.data[item].metadata.ownerReferences[0].name
} else { obj.vm = '' }
obj.size = res.data[item].spec.pvc.resources.requests.storage
listResult[item] = obj
if (data[i].metadata.annotations['harvesterhci.io/owned-by']) {
listResult[i].vm = JSON.parse(data[i].metadata.annotations['harvesterhci.io/owned-by'])[0].refs[0].replace('default/', '')
}
// 状态判断
const ownedBy = data[i].metadata?.annotations?.['harvesterhci.io/owned-by']
const status = data[i].status?.phase === 'Bound' ? 'Ready' : 'NotReady'
listResult[i].state = (ownedBy ? 'In-use' : status)
}
console.log(res)
resolve({ total: res.data.length, rows: listResult })
listResult = listResult.filter(n => n.namespace === 'default')
resolve({ total: listResult.length, rows: listResult })
})
})
}
@ -385,7 +380,6 @@ const getImagesList = () => {
return new Promise(function(resolve) {
const listResult = []
getImages().then((res) => {
console.log(res)
for (let item = 0; item < res.data.length; item++) {
var obj = {}
obj.index = item
@ -393,10 +387,11 @@ const getImagesList = () => {
obj.name = res.data[item].metadata.name
obj.state = res.data[item].metadata.state.name
obj.creationTime = res.data[item].metadata.creationTimestamp
obj.aliveTime = res.data[item].metadata.fields[5]
obj.aliveTime = res.data[item].metadata.fields[3]
obj.size = Number((res.data[item].status.size / 1024 / 1024).toString().match(/^\d+(?:\.\d{0,2})?/)) + 'MB'
obj.aliveTime = obj.aliveTime.replace('d', '天')
obj.aliveTime = obj.aliveTime.replace('h', '小时')
obj.aliveTime = obj.aliveTime.replace('m', '分钟')
listResult[item] = obj
}
resolve({ total: res.data.length, rows: listResult })

View File

@ -20,13 +20,16 @@ service.interceptors.request.use(
// do something before request is sent
// kubesphere
// Cookies.set('CSRF', '4d2f9a95f8')
if (store.getters.token && config.url.indexOf('/virtual/') === -1 && config.url.indexOf('blockChain') === -1) {
if (store.getters.token && config.url.indexOf('/virtual/') === -1 && config.url.indexOf('blockChain') === -1 && config.url.indexOf('dockerhub/api') === -1) {
config.headers['Authorization'] = 'Bearer ' + getToken()
// kubesphere删除
if (config.method === 'delete') {
config.headers['Content-Type'] = 'application/json'
}
}
if (config.url.indexOf('dockerhub/api') > -1) {
config.headers['Search-Version'] = 'v3'
}
// 区块链
if (config.url.indexOf('blockChain') !== -1) {
config.headers['Authorization'] = 'bearer ' + Cookies.get('bToken')

View File

@ -74,7 +74,7 @@
import { isString } from '@/utils/validate'
// import SocialSign from './components/SocialSignin'
import Cookies from 'js-cookie'
// import { harvesterFirstLogin } from '@/api/user'
import { harvesterFirstLogin } from '@/api/user'
export default {
name: 'Login',
@ -166,9 +166,9 @@ export default {
this.loading = true
const csrf = Cookies.get('CSRF')
if (!csrf) {
// harvesterFirstLogin().then(() => {
this.login()
// })
harvesterFirstLogin().then(() => {
this.login()
})
} else {
this.login()
}
@ -182,7 +182,7 @@ export default {
.then(() => {
this.$message.success('登录成功')
if (this.redirect) {
if (this.redirect.indexOf('cluster') && !localStorage.getItem('clusterName')) {
if (this.redirect.indexOf('cluster') > -1) {
this.$router.push({ path: '/clusterSelect' })
} else {
this.$router.push({ path: this.redirect, query: this.otherQuery })

View File

@ -1,28 +1,69 @@
<template>
<div class="monitor-select">
<Navbar />
<el-row :gutter="20">
<el-col :span="6">
<a class="monitorSelectBtn" @click="selectMonitor('/cluster/overview')">
<p>容器管理</p>
</a>
</el-col>
<el-col :span="6">
<a class="monitorSelectBtn" @click="selectMonitor('/virtual/overview')">
<p>虚拟机管理</p>
</a>
</el-col>
<el-col :span="6">
<a class="monitorSelectBtn" @click="selectMonitor('/functions/overview')">
<p>函数管理</p>
</a>
</el-col>
<el-col :span="6">
<a class="monitorSelectBtn" @click="selectMonitor('/blockChain/blockChainBrowser')">
<p>块链管理</p>
</a>
</el-col>
</el-row>
<div class="selectDiv">
<el-row>
<el-col :span="18">
<el-row>
<el-col :span="12">
<a @click="selectMonitor('/cluster/overview')">
<div class="monitorSelectDiv">
<div class="monitorSelectBtn">
<img src="@/assets/img/cluster.png">
<div>
<div class="selectTitle">容器管理</div>
<div>从容器维度中支持以跨云跨域多源异构方式提供高性能可伸缩的容器应用管理服务</div>
</div>
</div>
</div>
</a>
</el-col>
<el-col :span="12">
<a @click="selectMonitor('/virtual/overview')">
<div class="monitorSelectDiv">
<div class="monitorSelectBtn">
<img src="@/assets/img/virtual.png">
<div>
<div class="selectTitle">虚拟机管理</div>
<div>在虚拟机的控制台中管理属于主机或群集的单个虚拟机或一组虚拟机</div>
</div>
</div>
</div>
</a>
</el-col>
<el-col :span="12">
<a @click="selectMonitor('/functions/overview')">
<div class="monitorSelectDiv">
<div class="monitorSelectBtn">
<img src="@/assets/img/functions.png">
<div>
<div class="selectTitle">函数管理</div>
<div>支持一个服务下对多个函数进行创建编辑运行对函数运行全生命周期进行监控调度</div>
</div>
</div>
</div>
</a>
</el-col>
<el-col :span="12">
<a @click="selectMonitor('/blockChain/blockChainBrowser')">
<div class="monitorSelectDiv">
<div class="monitorSelectBtn">
<img src="@/assets/img/blockChain.png">
<div>
<div class="selectTitle">块链管理</div>
<div>构建于云际分布式框架之上拥有去中心化信任机制支持多组织资源分配模式</div>
</div>
</div>
</div>
</a>
</el-col>
</el-row>
</el-col>
<el-col :span="6">
<img class="logo" src="@/assets/img/bg_logo.png">
</el-col>
</el-row>
</div>
</div>
</template>
@ -41,7 +82,7 @@ export default {
methods: {
selectMonitor(monitor) {
this.$store.dispatch('user/setRouteType', monitor.split('/')[1])
this.$router.push({ path: monitor })
this.$router.push({ path: monitor.indexOf('cluster') > -1 ? 'clusterSelect' : monitor })
}
}
}
@ -49,15 +90,51 @@ export default {
<style lang="scss">
.monitor-select{
.el-col a{
display: block;
width: 80%;
margin: 30px auto;
height: 80vh;
padding: 30px;
border: 1px solid #419ef4;
border-radius: 30px;
font-size: 24px;
height: 100%;
background: url('../../assets/img/monitorSelect_bg.png') center no-repeat;
position: relative;
.selectDiv{
width: 100%;
padding: 0 8% 0 15%;
position: absolute;
top: 50%;
margin-top: -300px;
.el-col a{
display: block;
padding: 8%;
font-size: 24px;
margin: 4%;
color: white;
height: 280px;
background: linear-gradient(29deg, #454B53, #454B53, #879AB2);
border-radius: 36px;
position: relative;
}
.el-col a:hover{
background: linear-gradient(29deg, #0677E0, #127CDF, #5896EA);
}
.monitorSelectDiv{
position: relative;
top: 50%;
margin-top: -50px;
.monitorSelectBtn{
display: flex;
align-items: center;
font-size: 14px;
>img{
height: 30%;
margin-right: 20px;
}
.selectTitle{
margin-bottom: 20px;
font-size: 30px;
}
}
}
.logo{
width: 100%;
padding-top: 30%;
}
}
}
</style>

View File

@ -1,9 +1,9 @@
<template>
<div class="functionOverview">
<el-card slot="label" class="overviewTab" shadow="never">
<!-- <el-card slot="label" class="overviewTab" shadow="never">
<img src="@/assets/img/hanshu-.png">
<h4>函数概览</h4>
</el-card>
</el-card> -->
<el-card shadow="never">
<div slot="header" class="clearfix">
<span>函数调用概览</span>

View File

@ -1,9 +1,9 @@
<template>
<div>
<el-card slot="label" class="overviewTab" shadow="never">
<!-- <el-card slot="label" class="overviewTab" shadow="never">
<img src="@/assets/img/rq.png">
<h4>容器概览</h4>
</el-card>
</el-card> -->
<Pod />
</div>
</template>

View File

@ -1,25 +1,29 @@
<template>
<div>
<el-card slot="label" class="overviewTab" shadow="never">
<!-- <el-card slot="label" class="overviewTab" shadow="never">
<img src="@/assets/img/xnj-.png">
<h4>虚拟机概览</h4>
</el-card>
</el-card> -->
<el-card shadow="never" class="virtualMachineChart">
<h3>仪表盘</h3>
<span>版本: {{ info.version }} 创建时间: {{ info.createTime + '前' }}</span>
<el-divider />
<el-row :gutter="5">
<el-col :span="8">
<h4>cpu</h4>
<div id="cpuGauge" ref="cpuGauge" />
<p>cpu4中的0.39</p>
<p>已预留 {{ cpuUsage }}/{{ cpuTotal }}</p>
</el-col>
<el-col :span="8">
<h4>内存</h4>
<div id="memoryGauge" ref="memoryGauge" />
<p>内存7.75GiB中的4.27</p>
<p>已预留 {{ parseInt(memoryUsage/1024/1024/1024) }}/{{ parseInt(memoryTotal/1024/1024) + 'GiB' }}</p>
</el-col>
<el-col :span="8">
<h4>存储</h4>
<div id="storageGauge" ref="storageGauge" />
<p>存储197GiB中的9.84</p>
<p>已使用 {{ (storageUsage/1024/1024/1024/1024).toFixed(2) }} / {{ (storageTotal/1024/1024/1024/1024).toFixed(2) }} TiB</p>
</el-col>
</el-row>
@ -32,11 +36,11 @@
<th>存储卷</th>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>2</td>
<td>2</td>
<td>{{ counts.host }}</td>
<td>{{ counts.virtualMachine }}</td>
<td>{{ counts.networking }}</td>
<td>{{ counts.mirror }}</td>
<td>{{ counts.volume }}</td>
</tr>
</table>
<h4>事件</h4>
@ -51,51 +55,168 @@
</template>
<script>
const UNITS = ['', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y']
const FRACTIONAL = ['', 'm', 'u', 'n', 'p', 'f', 'a', 'z', 'y'] // milli micro nano pico femto
import List from '@/components/list'
import * as echarts from 'echarts'
import { getDashboardCounts, getDashboardEvents, getDashboardInfo, getUsageStatus, getStorageStatus } from '@/api/one-class-page/virtualMachine'
import moment from 'moment'
export default {
components: { List },
data() {
return {
moment,
info: {
version: '',
createTime: ''
},
counts: {
host: '',
virtualMachine: '',
networking: '',
mirror: '',
volume: ''
},
columns: [
{ prop: 'reason', label: '原因', width: '150' },
{ prop: 'info', label: '资源信息' },
{ prop: 'time', label: '发生时间', width: '150' }
{ prop: 'info', label: '事件详情', formatter: (row) => {
return <div>
<span>{row.involvedObject.kind + ' ' + row.involvedObject.name}</span> <br />
<span>{row.message}</span>
</div>
} },
{ prop: 'lastTimestamp', label: '更新时间', width: '150', formatter: (row) => {
return <div>{this.formatDate(row.lastTimestamp)}</div>
} }
],
listData: [
{
reason: 'Created',
info: 'VirtualMachineInstance educoder-main VirtualMachineInstance defined. ',
time: '2021/4/23 9:40'
},
{
reason: 'Started',
info: 'VirtualMachineInstance educoder-main VirtualMachineInstance defined. ',
time: '2021/4/23 9:40'
},
{
reason: 'Stopped',
info: 'VirtualMachineInstance educoder-main VirtualMachineInstance defined. ',
time: '2021/4/23 9:40'
}
]
],
cpuTotal: 0,
memoryTotal: 0,
storageTotal: 0,
cpuUsage: 0,
memoryUsage: 0,
storageUsage: 0
}
},
created() {
this.$nextTick(() => {
//
getDashboardCounts().then(res => {
this.counts.host = res.data[0].counts.node.summary.count
this.counts.virtualMachine = res.data[0].counts['kubevirt.io.virtualmachine'].summary.count
this.counts.networking = res.data[0].counts['k8s.cni.cncf.io.networkattachmentdefinition'].summary.count
this.counts.mirror = res.data[0].counts['harvesterhci.io.virtualmachineimage'].summary.count
this.counts.volume = res.data[0].counts['longhorn.io.volume'].summary.count
})
//
getDashboardEvents().then(res => {
this.listData = res.data
})
Promise.all([
getDashboardInfo(), // cpu
getUsageStatus(), // cpu 使
getStorageStatus()]).then(res => {
res[0].data.forEach(element => {
this.cpuTotal += Number(element.status.capacity.cpu)
this.memoryTotal += Number(element.status.capacity.memory.replace('Ki', ''))
if (element.metadata.fields[2].indexOf('master') > -1) {
this.info.version = element.metadata.fields[7].replace('Harvester ', '')
this.info.createTime = element.metadata.fields[3].replace('d', '天').replace('h', '小时')
}
})
this.memoryUsage = 0
this.cpuUsage = 0
res[1].data.forEach(element => {
const containers = element.spec.containers || []
let memoryCounts = 0
let cpuCounts = 0
containers.forEach(e => {
memoryCounts += this.parseSi(e?.resources?.requests?.memory || '0m', { increment: 1024 })
cpuCounts += this.parseSi(e?.resources?.requests?.cpu || '0m')
})
this.memoryUsage += memoryCounts
this.cpuUsage += cpuCounts
})
this.cpuUsage = parseInt(this.cpuUsage)
this.storageUsage = 0
this.storageTotal = 0
res[2].data.forEach(element => {
const diskStatus = element.status?.diskStatus || {}
Object.values(diskStatus).map((disk) => {
if (disk?.conditions?.Schedulable?.status === 'True' && disk?.storageAvailable && disk?.storageMaximum) {
this.storageUsage += (disk.storageMaximum - disk.storageAvailable)
}
if (disk?.storageMaximum) {
this.storageTotal += disk.storageMaximum
}
})
})
this.drawChart()
})
},
methods: {
parseSi(inValue, opt) {
opt = opt || {}
let increment = opt.increment
const allowFractional = opt.allowFractional !== false
if (!inValue || typeof inValue !== 'string' || !inValue.length) {
return NaN
}
inValue = inValue.replace(/,/g, '')
// eslint-disable-next-line prefer-const
let [, valStr, unit, incStr] = inValue.match(/^([0-9.-]+)\s*([^0-9.-]?)([^0-9.-]?)/)
const val = parseFloat(valStr)
if (!unit) {
return val
}
// micro "mu" symbol -> u
if (unit.charCodeAt(0) === 181) {
unit = 'u'
}
const divide = FRACTIONAL.includes(unit)
const multiply = UNITS.includes(unit.toUpperCase())
if (!increment) {
// Automatically handle 1 KB = 1000B, 1 KiB = 1024B if no increment set
if ((multiply || divide) && incStr === 'i') {
increment = 1024
} else {
increment = 1000
}
}
if (divide && allowFractional) {
const exp = FRACTIONAL.indexOf(unit)
return val / (increment ** exp)
}
if (multiply) {
const exp = UNITS.indexOf(unit.toUpperCase())
return val * (increment ** exp)
}
// Unrecognized unit character
return val
},
formatDate(t) {
return moment(t).local().format('YYYY-MM-DD hh:mm:ss')
},
drawChart() {
const cpuGauge = echarts.init(this.$refs.cpuGauge)
cpuGauge.setOption(this.returnGaugeOption(5))
cpuGauge.setOption(this.returnGaugeOption((this.cpuUsage / this.cpuTotal).toFixed(4) * 100))
const memoryGauge = echarts.init(this.$refs.memoryGauge)
memoryGauge.setOption(this.returnGaugeOption(16))
memoryGauge.setOption(this.returnGaugeOption((parseInt(this.memoryUsage / 1024 / 1024 / 1024) / parseInt(this.memoryTotal / 1024 / 1024)).toFixed(4) * 100))
const storageGauge = echarts.init(this.$refs.storageGauge)
storageGauge.setOption(this.returnGaugeOption(3))
storageGauge.setOption(this.returnGaugeOption(((this.storageUsage / 1024 / 1024 / 1024 / 1024).toFixed(2) / (this.storageTotal / 1024 / 1024 / 1024 / 1024).toFixed(2)).toFixed(4) * 100))
},
returnGaugeOption(data) {
return {

View File

@ -101,7 +101,7 @@ export default {
this.$Api.addInfo(this.clusterName, formData).then(res => {
this.$message.success('操作成功')
this.createFormVisible = false
this.doSearch()
this.$emit('getList')
})
},
nameValidator(rule, value, callback) {

View File

@ -7,12 +7,12 @@
将根据项目资源进行分组, 可以按项目对资源进行查看管理</span>
<el-button v-if="activeName ==='0'" class="create-btn" type="primary" @click="createFormVisible = true">创建</el-button>
</el-card>
<BaseInfoForm v-model="dialogFormVisible" :data="editInfoForm" />
<BaseInfoForm v-model="dialogFormVisible" :data="editInfoForm" @getList="getList" />
<el-card shadow="never">
<el-tabs v-model="activeName" @tab-click="switchTab">
<el-tab-pane key="userProject" label="用户项目">
<List
ref="multipleTable"
ref="multipleTable1"
class="multipleTable"
:columns="columns[0]"
func-name="getUserProjectList"
@ -24,7 +24,7 @@
</el-tab-pane>
<el-tab-pane key="systemProject" label="系统项目">
<List
ref="multipleTable"
ref="multipleTable2"
class="multipleTable"
:columns="columns[1]"
func-name="getSystemProjectList"
@ -36,7 +36,7 @@
</el-tab-pane>
</el-tabs>
</el-card>
<CreateProject v-model="createFormVisible" :do-search="doSearch" />
<CreateProject v-model="createFormVisible" @getList="getList" />
</div>
</template>
@ -69,7 +69,7 @@ export default {
[
{ prop: 'name', label: '名称', formatter: (row) => { return <a onClick={() => this.viewUserProjectDetail(row)}>{row.metadata.name}</a> } },
{ prop: 'status', label: '状态', formatter: (row, column) => { return row.status.phase === 'Active' ? '活跃' : '准备中' } },
{ prop: 'space', label: '企业空间', formatter: (row, column) => { return row.metadata.labels['kubesphere.io/workspace'] || '-' } },
// { prop: 'space', label: '', formatter: (row, column) => { return row.metadata.labels['kubesphere.io/workspace'] || '-' } },
{ prop: 'namespace_cpu_usage', label: 'CPU使用量' },
{ prop: 'namespace_memory_usage_wo_cache', label: '内存使用量' },
{ prop: 'namespace_pod_count', label: 'Pods数量' },
@ -80,7 +80,6 @@ export default {
</el-button>
<el-dropdown-menu slot='dropdown'>
<span onClick={() => this.editBaseInfo(row)}> <el-dropdown-item> 编辑</el-dropdown-item> </span>
<span onClick={() => this.setSpace(row)}> <el-dropdown-item> 分配企业空间 </el-dropdown-item> </span>
<span onClick={() => this.deleteCurrent('项目', row.metadata.name, row.metadata.name, 'userProject', 'list')}> <el-dropdown-item> 删除</el-dropdown-item> </span>
</el-dropdown-menu>
</el-dropdown>
@ -90,7 +89,7 @@ export default {
[
{ prop: 'name', label: '名称', formatter: (row) => { return <a onClick={() => this.viewSystemProjectDetail(row)}>{row.metadata.name}</a> } },
{ prop: 'status', label: '状态', formatter: (row, column) => { return row.status.phase === 'Active' ? '活跃' : '准备中' } },
{ prop: 'space', label: '企业空间', formatter: (row, column) => { return row.metadata.labels['kubesphere.io/workspace'] || '-' } },
// { prop: 'space', label: '', formatter: (row, column) => { return row.metadata.labels['kubesphere.io/workspace'] || '-' } },
{ prop: 'namespace_cpu_usage', label: 'CPU使用量' },
{ prop: 'namespace_memory_usage_wo_cache', label: '内存使用量' },
{ prop: 'namespace_pod_count', label: 'Pods数量' },
@ -133,8 +132,9 @@ export default {
}
},
methods: {
doSearch() {
this.$refs.multipleTable.getList()
getList() {
this.$refs.multipleTable1.getList()
this.$refs.multipleTable2.getList()
},
switchTab(e) {
const tab = this.tabList[e.index]

View File

@ -21,7 +21,7 @@
<!-- <el-dialog title="查看配置文件" :visible.sync="dialogSettingVisible">
<codemirror v-model="code" class="code-mirror" :options="cmOption" />
</el-dialog> -->
<BaseInfoForm v-model="dialogFormVisible" :data="editInfoForm" />
<BaseInfoForm v-model="dialogFormVisible" :data="editInfoForm" @getList="getList" />
<ServiceCreate v-model="dialogSettingVisible" @getList="getList" />
<!-- <el-dialog :visible.sync="dialogSettingVisible">
<Service class="demo1" />

View File

@ -111,7 +111,7 @@
>
<el-slider
v-model="editInfoForm2.storage"
style="margin-top: 30px;width:90%"
style="margin-top:30px;word-break:keep-all;"
:marks="marks"
show-input
:max="2050"

View File

@ -7,7 +7,7 @@
存储卷供用户创建的工作负载使用是将工作负载数据持久化的一种资源对象 </span>
<el-button type="primary" class="create-btn" @click="dialogCreateVisible = true">创建</el-button>
</el-card>
<BaseInfoForm v-model="dialogFormVisible" :data="editInfoForm" classification="storage" />
<BaseInfoForm v-model="dialogFormVisible" :data="editInfoForm" classification="storage" @getList="getList" />
<el-card shadow="never">
<List
ref="multipleTable"
@ -49,7 +49,16 @@ export default {
},
status: {
label: '状态',
type: 'select'
type: 'select',
dataSource: [
{
label: '准备就绪', value: 'bound'
}, {
label: '丢失', value: 'lost'
}, {
label: '等待中', value: 'pending'
}
]
}
},
columns: [

View File

@ -44,12 +44,12 @@
<el-form-item label="大小">
<el-input
v-model="formData.size"
:disabled="!clone"
:disabled="isDisabled"
><template slot="append">GIB</template></el-input>
</el-form-item>
</el-tab-pane>
<el-tab-pane label="标签">
<!-- <el-tab-pane label="标签">
<h4>标签</h4>
<div v-for="(item, index) in formData.tag" :key="item.id">
<el-form-item>
@ -62,7 +62,7 @@
</el-form-item>
</div>
<el-button type="primary" :disabled="isDisabled" @click="addTag">添加</el-button>
</el-tab-pane>
</el-tab-pane> -->
</el-tabs>
</el-form>
@ -78,7 +78,7 @@
</template>
<script>
import { getImages, getDataVolume, editDataVolume } from '@/api/one-class-page/virtualMachine'
import { getImages, getDataVolumeNew, editDataVolume } from '@/api/one-class-page/virtualMachine'
import { createDataVolume } from '@/api/one-class-page/virtualMachine'
export default {
data() {
@ -158,7 +158,7 @@ export default {
getFormData() {
this.formData.name = this.$route.query.name
this.formData.size = this.$route.query.size.slice(0, -2)
getDataVolume().then(res => {
getDataVolumeNew().then(res => {
this.Data = res.data[this.$route.query.index]
if (this.Data.metadata.annotations['field.cattle.io/description'] != null && typeof (this.Data.metadata.annotations['field.cattle.io/description']) !== 'undefined') {
this.formData.description = this.Data.metadata.annotations['field.cattle.io/description']
@ -213,10 +213,7 @@ export default {
},
editVolume() {
this.Data.metadata.annotations['field.cattle.io/description'] = this.formData.description
this.Data.metadata.labels = {}
for (let item = 0; item < this.formData.tag.length; item++) {
this.Data.metadata.labels[this.formData.tag[item].key] = this.formData.tag[item].value
}
this.Data.spec.resources.requests.storage = this.formData.size + 'Gi'
editDataVolume(this.$route.query.name, this.Data).then(res => {
console.log(res)
this.$message.success('修改成功')

View File

@ -50,7 +50,7 @@
</el-form-item>
</el-tab-pane>
<el-tab-pane label="标签">
<!-- <el-tab-pane label="标签">
<h4>标签</h4>
<div v-for="(item, index) in formData.tag" :key="item.id">
<el-form-item>
@ -63,7 +63,7 @@
</el-form-item>
</div>
<el-button type="primary" @click="addTag">添加</el-button>
</el-tab-pane>
</el-tab-pane> -->
</el-tabs>
</el-form>
@ -100,32 +100,7 @@ export default {
label: 'VM Image'
}],
options2: [],
volumeData: {
type: 'cdi.kubevirt.io.datavolume',
metadata: {
namespace: 'default',
annotations: {
'field.cattle.io/description': ''
// 'harvesterhci.io/imageId': null
},
labels: {},
name: ''
},
spec: {
pvc: {
resources: {
requests: {
storage: ''
}
},
volumeMode: 'Block',
accessModes: ['ReadWriteMany']
},
source: {
blank: {}
}
}
},
volumeData: {},
//
rules: {
name: [
@ -157,7 +132,6 @@ export default {
const obj = {}
obj.value = data[item].id
obj.label = data[item].metadata.fields[1]
console.log(data[item].metadata.fields[1])
this.options2.push(obj)
}
})
@ -179,16 +153,29 @@ export default {
this.formData.tag.splice(index, 1)
},
create() {
this.volumeData.metadata.annotations['field.cattle.io/description'] = this.formData.description
if (this.formData.resourceType === 'VM Image') this.volumeData.metadata.annotations['harvesterhci.io/imageId'] = this.formData.imageId
for (let item = 0; item < this.formData.tag.length; item++) {
this.volumeData.metadata.labels[this.formData.tag[item].key] = this.formData.tag[item].value
this.volumeData = {
metadata: {
annotations: {
'field.cattle.io/description': this.formData.description || '',
'harvesterhci.io/imageId': this.formData.resourceType === 'VM Image' ? this.formData.imageId : undefined
},
name: this.formData.name || '',
namespace: 'default'
},
spec: {
accessModes: ['ReadWriteMany'],
resources: {
requests: {
storage: this.formData.size + 'Gi'
}
},
storageClassName: this.formData.resourceType === 'VM Image' ? `longhorn-${this.formData.imageId.replace('default/', '')}` : 'longhorn',
volumeMode: 'Block',
volumeName: ''
},
type: 'persistentvolumeclaim'
}
this.volumeData.metadata.name = this.formData.name
this.volumeData.spec.pvc.resources.requests.storage = this.formData.size + 'Gi'
// console.log(this.volumeData)
createDataVolume(this.volumeData).then(res => {
console.log(res)
this.$message.success('创建成功')
this.goBack()
})

View File

@ -15,7 +15,7 @@
<script>
import { FormData } from '@/components/FormData'
import { getImages, getDataVolume } from '@/api/one-class-page/virtualMachine'
import { getImages, getDataVolumeNew } from '@/api/one-class-page/virtualMachine'
export default {
components: { FormData },
@ -79,7 +79,7 @@ export default {
var images = null
getImages().then(res => {
images = res.data
getDataVolume().then(res => {
getDataVolumeNew().then(res => {
var data = res.data[this.index]
if (data.metadata.annotations['harvesterhci.io/imageId'] != null && typeof (data.metadata.annotations['harvesterhci.io/imageId']) !== 'undefined' && data.metadata.annotations['harvesterhci.io/imageId'] !== '') {
var imageId = data.metadata.annotations['harvesterhci.io/imageId']

View File

@ -23,7 +23,7 @@
:columns="columns"
func-name="getDataVolumeList"
:cluster-name="clusterName"
:pagination="true"
:pagination="false"
tooltip-effect="dark"
/>
</el-card>
@ -69,7 +69,6 @@ export default {
{ prop: 'name', label: '名称', formatter: (row) => { return <a onClick={() => this.viewVolumeDetail(row)}>{row.name}</a> } },
{ prop: 'size', label: '大小' },
{ prop: 'vm', label: '挂载虚拟机', formatter: (row) => { return <a onClick={() => this.viewVMDetail(row)}>{row.vm}</a> } },
{ prop: 'progress', label: '进度', formatter: (row) => { return <el-progress percentage={row.progress}></el-progress> } },
{ prop: 'phase', label: '阶段', formatter: (row) => { return <el-tag type={row.tagtype}>{row.phase}</el-tag> } },
{ prop: 'aliveTime', label: '存活时间', formatter: (row) => { return <el-tooltip effect='light' content={row.creationTime} placement='right'><span>{row.aliveTime}</span></el-tooltip> } },
{
@ -105,11 +104,6 @@ export default {
},
created() {
},
mounted() {
this.timer = setInterval(() => {
this.$refs.multipleTable.getList()
}, this.timeInterval)
},
beforeDestroy() {
clearInterval(this.timer)
this.timer = null
@ -170,9 +164,8 @@ export default {
document.body.removeChild(link)
})
},
deleteDataVolumes(name) {
deleteDataVolume(name).then(res => {
console.log(res)
async deleteDataVolumes(name) {
await deleteDataVolume(name).then(res => {
this.deleteDialogVisible = false
this.$message.success('删除成功')
})

View File

@ -26,12 +26,24 @@
tooltip-effect="dark"
/>
</el-card>
<el-dialog
title="您确定要删除吗?"
:visible.sync="deleteDialogVisible"
width="30%"
>
<span>您试图删除 镜像 {{ clickrow.name }} </span>
<span slot="footer" class="dialog-footer">
<el-button @click="deleteDialogVisible = false"> </el-button>
<el-button type="primary" @click="deleteDataImage(clickrow.name)"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import List from '@/components/list'
import { getImagesYaml } from '@/api/one-class-page/virtualMachine'
import { getImagesYaml, deleteImage } from '@/api/one-class-page/virtualMachine'
export default {
name: 'PodForm',
@ -41,6 +53,8 @@ export default {
timer: null,
timeInterval: 10000,
disabled: false,
deleteDialogVisible: false,
clickrow: '',
filterMap: {
// name: {
// label: ''
@ -121,10 +135,19 @@ export default {
this.downloadHostYaml(row.name)
break
case 5:
this.deleteDialogVisible = true
this.clickrow = row
break
default:
}
},
async deleteDataImage(name) {
await deleteImage(name).then(() => {
this.deleteDialogVisible = false
this.$message.success('删除成功')
})
this.$refs.multipleTable.getList()
},
viewVMDetail(row) {
this.$router.push({ path: `virtual-machine/detail`, query: row })
},

View File

@ -71,21 +71,7 @@ export default {
url: '',
tag: []
},
imagesData: {
type: 'harvesterhci.io.virtualmachineimage',
metadata: {
annotations: {
'field.cattle.io/description': ''
},
generateName: 'image-',
labels: {},
namespace: 'default'
},
spec: {
displayName: '',
url: ''
}
},
imagesData: {},
//
rules: {
name: [
@ -98,7 +84,7 @@ export default {
url: [
{
required: true, //
message: '大小不能为空', //
message: '地址不能为空', //
trigger: 'blur' //
}
]
@ -124,18 +110,35 @@ export default {
this.formData.tag.splice(index, 1)
},
create() {
this.imagesData.metadata.annotations['field.cattle.io/description'] = this.formData.description
for (let item = 0; item < this.formData.tag.length; item++) {
this.imagesData.metadata.labels[this.formData.tag[item].key] = this.formData.tag[item].value
}
this.imagesData.spec.displayName = this.formData.name
this.imagesData.metadata.generateName = 'img'
this.imagesData.spec.url = this.formData.url
console.log(this.imagesData)
createImages(this.imagesData).then(res => {
console.log(res)
this.$message.success('创建成功')
this.goBack()
this.$refs['formData'].validate((valid) => {
if (valid) {
this.imagesData = {
'type': 'harvesterhci.io.virtualmachineimage',
'metadata': {
annotations: {
'field.cattle.io/description': this.formData.description
},
labels: {},
'namespace': 'default',
'generateName': 'image-'
},
'spec': {
'sourceType': 'download',
'displayName': this.formData.name,
'url': this.formData.url
}
}
for (let item = 0; item < this.formData.tag.length; item++) {
this.imagesData.metadata.labels[this.formData.tag[item].key] = this.formData.tag[item].value
}
createImages(this.imagesData).then(res => {
this.$message.success('创建成功')
this.goBack()
})
} else {
console.log('error submit!!')
return false
}
})
}
}

View File

@ -7,7 +7,7 @@
<span class="tips">
工作负载 (Workload) 通常是访问服务的实际载体, 也是对节点日志收集监控等系统应用的实际运行载体是对一组容器组 (Pod) 的抽象模型</span>
</el-card>
<BaseInfoForm v-model="dialogFormVisible" :data="editInfoForm" :classification="tabList[activeName]" />
<BaseInfoForm v-model="dialogFormVisible" :data="editInfoForm" :classification="tabList[activeName]" @getList="getList" />
<el-card shadow="never">
<el-tabs v-model="activeName" @tab-click="switchTab">
<el-tab-pane key="deployments" label="部署">
@ -52,7 +52,7 @@
</el-tabs>
</el-card>
<EditSetting v-model="dialogSettingVisible" :is-edit="true" :code="code" @submitSettingEdit="submitSettingEdit" />
<CreateWorkload v-model="createFormVisible" />
<CreateWorkload v-model="createFormVisible" :classification="tabList[activeName]" @getList="getList" />
</div>
</template>
@ -63,6 +63,7 @@ import deleteCurrent from '@/mixin/deleteCurrent'
import editSetting from '@/mixin/editSetting'
import { statusOptions } from '@/utils/map'
import CreateWorkload from '@/components/workloadsManagement/createWorkload'
import { getStorageProject } from '@/api/one-class-page/storageManagement'
export default {
name: 'WorkloadForm',
@ -152,7 +153,7 @@ export default {
},
methods: {
setFilterMapNamespaceList() {
this.$Api.getNamespaceList().then(res => {
getStorageProject(this.clusterName, { page: 1, limit: 9999 }).then(res => {
const arr = res.items.map(e => { return { label: e.metadata.name, value: e.metadata.name } })
this.filterMap.namespace.dataSource = arr
})
@ -166,6 +167,9 @@ export default {
viewDetail(row) {
this.$router.push({ path: `${row.project}/${this.tabList[this.activeName]}/${row.name}/resource-status` })
},
getList() {
this.$refs.multipleTable.getList()
},
//
reDeploy(row) {
const query = { 'spec': { 'template': { 'metadata': { 'annotations': { 'kubesphere.io/restartedAt': new Date().toISOString() }}}}}

View File

@ -39,7 +39,7 @@ module.exports = {
proxy: {
'^/login': {
ws: false,
target: 'http://10.105.20.3:30880/'/* Host */
target: 'https://jointcloud.net/prod-api/'/* Host */
},
// '^/v1': {
// ws: false,
@ -57,12 +57,13 @@ module.exports = {
// ws: true,
// target: 'http://124.71.196.205:30881/' /* EduCoder */
// target: 'http://119.3.157.144:30881/', /* KubeX */
target: 'http://10.105.20.3:30880/'/* Host */
// target: 'http://10.105.20.3:30880/'/* Host */
target: 'https://jointcloud.net/prod-api/'/* Host */
// target: 'http://39.103.233.49:30881/', /* BJ-Member2 */
// changeOrigin: true,
},
'^/dockerhub/api/': {
target: 'http://119.45.100.73:30880/'
target: 'http://10.105.20.3:30880/'
// pathRewrite: {
// '^/dockerhub': '/api'
// },