mirror of
https://github.com/jumpserver/lina.git
synced 2025-09-26 15:07:04 +00:00
perf: update cloud sync
This commit is contained in:
@@ -27,7 +27,9 @@ export default {
|
|||||||
},
|
},
|
||||||
beforeSubmit: {
|
beforeSubmit: {
|
||||||
type: Function,
|
type: Function,
|
||||||
default: (val) => { return true }
|
default: (val) => {
|
||||||
|
return true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
@@ -50,14 +52,16 @@ export default {
|
|||||||
::v-deep .el-select {
|
::v-deep .el-select {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
::v-deep .el-form-item__content {
|
::v-deep .el-form-item__content {
|
||||||
width: 100% !important;
|
width: 100% !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
::v-deep .form-buttons {
|
::v-deep .form-buttons {
|
||||||
margin: 0 !important;
|
margin: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.attr-input {
|
.attr-input {
|
||||||
margin-top: -10px;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
@@ -9,7 +9,6 @@ const clouds = {
|
|||||||
},
|
},
|
||||||
hidden: true,
|
hidden: true,
|
||||||
meta: {
|
meta: {
|
||||||
title: i18n.t('BaseCloudSync'),
|
|
||||||
app: 'xpack',
|
app: 'xpack',
|
||||||
resource: 'account'
|
resource: 'account'
|
||||||
},
|
},
|
||||||
@@ -41,32 +40,10 @@ const clouds = {
|
|||||||
hidden: true,
|
hidden: true,
|
||||||
redirect: '/console/assets/cloud',
|
redirect: '/console/assets/cloud',
|
||||||
meta: {
|
meta: {
|
||||||
title: i18n.t('CloudAccountList'),
|
title: i18n.t('CloudSync'),
|
||||||
permissions: ['xpack.view_account']
|
permissions: ['xpack.view_account']
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: 'create',
|
|
||||||
component: () => import('@/views/assets/Cloud/Account/AccountCreateUpdate'),
|
|
||||||
name: 'AccountCreate',
|
|
||||||
hidden: true,
|
|
||||||
meta: {
|
|
||||||
title: i18n.t('CloudAccountCreate'),
|
|
||||||
action: 'create',
|
|
||||||
permissions: ['xpack.add_account']
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: ':id/update',
|
|
||||||
component: () => import('@/views/assets/Cloud/Account/AccountCreateUpdate'),
|
|
||||||
name: 'AccountUpdate',
|
|
||||||
hidden: true,
|
|
||||||
meta: {
|
|
||||||
title: i18n.t('CloudAccountUpdate'),
|
|
||||||
action: 'update',
|
|
||||||
permissions: ['xpack.change_account']
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: ':id/',
|
path: ':id/',
|
||||||
component: () => import('@/views/assets/Cloud/Account/AccountDetail/index'),
|
component: () => import('@/views/assets/Cloud/Account/AccountDetail/index'),
|
||||||
|
@@ -1,292 +0,0 @@
|
|||||||
<template>
|
|
||||||
<Page>
|
|
||||||
<el-row :gutter="20">
|
|
||||||
<el-col :md="20" :sm="24">
|
|
||||||
<IBox>
|
|
||||||
<GenericCreateUpdateForm
|
|
||||||
v-show="activeStep===0"
|
|
||||||
ref="baseForm"
|
|
||||||
v-bind="configSettings"
|
|
||||||
/>
|
|
||||||
<GenericCreateUpdateForm
|
|
||||||
v-if="activeStep===1"
|
|
||||||
ref="strategyForm"
|
|
||||||
v-bind="strategySettings"
|
|
||||||
/>
|
|
||||||
</IBox>
|
|
||||||
</el-col>
|
|
||||||
<el-col :md="4" :sm="24">
|
|
||||||
<IBox style="height: 490px;">
|
|
||||||
<el-steps
|
|
||||||
:active="activeStep"
|
|
||||||
direction="vertical"
|
|
||||||
space="400px"
|
|
||||||
>
|
|
||||||
<el-step :description="description" :title="$tc('Config')" />
|
|
||||||
<el-step :title="$tc('Strategy')" />
|
|
||||||
</el-steps>
|
|
||||||
</IBox>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
</Page>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { RequiredChange, specialEmojiCheck } from '@/components/Form/DataForm/rules'
|
|
||||||
import { ACCOUNT_PROVIDER_ATTRS_MAP, aliyun } from '../const'
|
|
||||||
import { Checkbox, IBox, UploadKey } from '@/components'
|
|
||||||
import { encryptPassword } from '@/utils/crypto'
|
|
||||||
import { GenericCreateUpdateForm, Page } from '@/layout/components'
|
|
||||||
import SyncInstanceTaskStrategy from './components/SyncInstanceTaskStrategy'
|
|
||||||
import { setUrlParam } from '@/utils/common'
|
|
||||||
import { crontab, interval, is_periodic } from '@/components/const'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
components: {
|
|
||||||
IBox,
|
|
||||||
Page,
|
|
||||||
GenericCreateUpdateForm
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
const vm = this
|
|
||||||
const accountProvider = this.$route.query.provider || aliyun
|
|
||||||
const accountProviderAttrs = ACCOUNT_PROVIDER_ATTRS_MAP[accountProvider]
|
|
||||||
|
|
||||||
function setFieldAttrs() {
|
|
||||||
const fieldsObject = {}
|
|
||||||
const updateNotRequiredFields = [
|
|
||||||
'access_key_secret', 'client_secret', 'password', 'sc_password',
|
|
||||||
'oc_password', 'cert_file', 'key_file', 'public_key', 'private_key'
|
|
||||||
]
|
|
||||||
for (const item of accountProviderAttrs?.attrs) {
|
|
||||||
fieldsObject[item] = {
|
|
||||||
rules: updateNotRequiredFields.includes(item) && vm.$route.params.id ? [] : [RequiredChange]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return fieldsObject
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
accountId: '',
|
|
||||||
taskId: '',
|
|
||||||
activeStep: 0,
|
|
||||||
description: accountProviderAttrs.title,
|
|
||||||
configSettings: {
|
|
||||||
initial: {
|
|
||||||
attrs: {
|
|
||||||
ip_group: []
|
|
||||||
},
|
|
||||||
provider: this.$route.query.provider,
|
|
||||||
port: 443
|
|
||||||
},
|
|
||||||
url: '/api/v1/xpack/cloud/accounts/',
|
|
||||||
fields: [
|
|
||||||
[this.$t('Basic'), ['name', 'provider']],
|
|
||||||
[this.$t(accountProviderAttrs.title), ['attrs']],
|
|
||||||
[this.$t('Other'), ['comment']]
|
|
||||||
],
|
|
||||||
fieldsMeta: {
|
|
||||||
name: {
|
|
||||||
rules: [RequiredChange, specialEmojiCheck]
|
|
||||||
},
|
|
||||||
attrs: {
|
|
||||||
encryptedFields: ['access_key_secret'],
|
|
||||||
fields: accountProviderAttrs.attrs,
|
|
||||||
fieldsMeta: {
|
|
||||||
// 必须放在最上面,下面特殊制定的字段才会覆盖默认
|
|
||||||
...setFieldAttrs(),
|
|
||||||
service_account_key: {
|
|
||||||
label: this.$t('ServerAccountKey'),
|
|
||||||
component: UploadKey,
|
|
||||||
el: {
|
|
||||||
toFormat: 'object'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
cert_file: {
|
|
||||||
label: this.$t('Certificate'),
|
|
||||||
component: UploadKey,
|
|
||||||
el: {
|
|
||||||
toFormat: 'object'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
key_file: {
|
|
||||||
label: this.$t('SecretKey'),
|
|
||||||
component: UploadKey,
|
|
||||||
el: {
|
|
||||||
toFormat: 'object'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
password: {
|
|
||||||
rules: this.$route.params.id ? [] : [RequiredChange]
|
|
||||||
},
|
|
||||||
public_key: {
|
|
||||||
label: this.$t('PublicKey'),
|
|
||||||
rules: this.$route.params.id ? [] : [RequiredChange]
|
|
||||||
},
|
|
||||||
private_key: {
|
|
||||||
label: this.$t('PrivateKey'),
|
|
||||||
rules: this.$route.params.id ? [] : [RequiredChange]
|
|
||||||
},
|
|
||||||
project: {
|
|
||||||
label: this.$t('Project')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
provider: {
|
|
||||||
rules: [RequiredChange],
|
|
||||||
el: {
|
|
||||||
disabled: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onPerformSuccess: (resp) => {
|
|
||||||
let url = vm.strategySettings.fieldsMeta.regions.el.url
|
|
||||||
if (!vm.accountId) {
|
|
||||||
vm.accountId = resp?.id
|
|
||||||
url = setUrlParam(url, 'account_id', vm.accountId)
|
|
||||||
vm.strategySettings.fieldsMeta.regions.el.url = url
|
|
||||||
}
|
|
||||||
if (!vm.taskId) {
|
|
||||||
vm.taskId = resp?.task?.id
|
|
||||||
vm.strategySettings.url += `${vm.taskId}/`
|
|
||||||
}
|
|
||||||
this.activeStep = this.activeStep === 0 ? 1 : 0
|
|
||||||
},
|
|
||||||
submitBtnText: this.$t('Next'),
|
|
||||||
hasSaveContinue: false,
|
|
||||||
hasReset: false,
|
|
||||||
getUrl: () => {
|
|
||||||
let url = vm.configSettings.url
|
|
||||||
const params = vm.$route.params
|
|
||||||
const instanceId = params?.id || vm.accountId
|
|
||||||
if (instanceId) {
|
|
||||||
url = `${url}${instanceId}/`
|
|
||||||
}
|
|
||||||
return `${url}?provider=${accountProvider}`
|
|
||||||
},
|
|
||||||
submitMethod: () => {
|
|
||||||
return vm.$route.params?.id || vm.accountId ? 'put' : 'post'
|
|
||||||
},
|
|
||||||
cleanFormValue(values) {
|
|
||||||
const encryptedFields = [
|
|
||||||
'access_key_secret', 'password', 'client_secret',
|
|
||||||
'oc_password', 'sc_password'
|
|
||||||
]
|
|
||||||
const attrs = values.attrs
|
|
||||||
for (const item of encryptedFields) {
|
|
||||||
const value = attrs[item]
|
|
||||||
if (!value) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
attrs[item] = encryptPassword(value)
|
|
||||||
}
|
|
||||||
if (Array.isArray(attrs.ip_group)) {
|
|
||||||
values.attrs.ip_group = attrs.ip_group.filter(Boolean)
|
|
||||||
}
|
|
||||||
return values
|
|
||||||
},
|
|
||||||
afterGetFormValue(formValue) {
|
|
||||||
if (!formValue.attrs) {
|
|
||||||
return formValue
|
|
||||||
}
|
|
||||||
return formValue
|
|
||||||
}
|
|
||||||
},
|
|
||||||
strategySettings: {
|
|
||||||
initial: {
|
|
||||||
is_periodic: false,
|
|
||||||
interval: 24,
|
|
||||||
hostname_strategy: 'instance_name_partial_ip',
|
|
||||||
ip_network_segment_group: ['*']
|
|
||||||
},
|
|
||||||
fields: [
|
|
||||||
[this.$t('CloudSource'), ['regions']],
|
|
||||||
[this.$t('SaveSetting'), [
|
|
||||||
'hostname_strategy', 'ip_network_segment_group', 'sync_ip_type',
|
|
||||||
'is_always_update', 'fully_synchronous'
|
|
||||||
]],
|
|
||||||
[this.$t('SyncStrategy'), ['strategy']],
|
|
||||||
[this.$t('Periodic'), ['is_periodic', 'interval', 'crontab']]
|
|
||||||
],
|
|
||||||
url: '/api/v1/xpack/cloud/sync-instance-tasks/',
|
|
||||||
fieldsMeta: {
|
|
||||||
hostname_strategy: {
|
|
||||||
rules: [RequiredChange],
|
|
||||||
helpTip: this.$t('HostnameStrategy')
|
|
||||||
},
|
|
||||||
is_always_update: {
|
|
||||||
type: 'checkbox',
|
|
||||||
label: this.$t('IsAlwaysUpdate'),
|
|
||||||
helpTip: this.$t('IsAlwaysUpdateHelpTip')
|
|
||||||
},
|
|
||||||
fully_synchronous: {
|
|
||||||
type: 'checkbox',
|
|
||||||
label: this.$t('FullySynchronous'),
|
|
||||||
helpTip: this.$t('FullySynchronousHelpTip')
|
|
||||||
},
|
|
||||||
regions: {
|
|
||||||
component: Checkbox,
|
|
||||||
el: {
|
|
||||||
url: '/api/v1/xpack/cloud/regions/',
|
|
||||||
options: [],
|
|
||||||
value: [],
|
|
||||||
noOptionTip: this.$t('CloudRegionTip'),
|
|
||||||
processResults(data) {
|
|
||||||
return data.regions?.map((item) => {
|
|
||||||
return { label: item.name, value: item.id }
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
is_periodic,
|
|
||||||
crontab,
|
|
||||||
interval,
|
|
||||||
strategy: {
|
|
||||||
label: this.$t('Strategy'),
|
|
||||||
component: SyncInstanceTaskStrategy,
|
|
||||||
helpTip: this.$t('StrategyHelpTip')
|
|
||||||
}
|
|
||||||
},
|
|
||||||
hasSaveContinue: false,
|
|
||||||
hasReset: false,
|
|
||||||
getUrl: () => {
|
|
||||||
return this.strategySettings.url
|
|
||||||
},
|
|
||||||
submitMethod: () => {
|
|
||||||
return this.$refs.baseForm.form.task?.id ? 'put' : 'post'
|
|
||||||
},
|
|
||||||
moreButtons: [
|
|
||||||
{
|
|
||||||
title: this.$t('Previous'),
|
|
||||||
callback: () => {
|
|
||||||
this.activeStep = this.activeStep === 1 ? 0 : 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
updateSuccessNextRoute: { name: 'CloudAccountList' },
|
|
||||||
createSuccessNextRoute: { name: 'CloudAccountList' },
|
|
||||||
cleanFormValue(value) {
|
|
||||||
const ipNetworkSegments = value.ip_network_segment_group
|
|
||||||
const strategy = value?.strategy || []
|
|
||||||
if (!Array.isArray(ipNetworkSegments)) {
|
|
||||||
value.ip_network_segment_group = ipNetworkSegments ? ipNetworkSegments.split(',') : []
|
|
||||||
}
|
|
||||||
value.strategy = strategy.map(item => {
|
|
||||||
return item.id
|
|
||||||
})
|
|
||||||
const accountId = this.$route.params?.id || this.accountId
|
|
||||||
if (accountId) {
|
|
||||||
value.account = { pk: accountId }
|
|
||||||
}
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {}
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="less" scoped>
|
|
||||||
</style>
|
|
@@ -11,7 +11,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<template #right>
|
<template #right>
|
||||||
<QuickActions :actions="quickEditActions" type="primary" />
|
<QuickActions :actions="quickEditActions" type="primary" />
|
||||||
<QuickActions :actions="quickExecuteActions" type="primary" />
|
<QuickActions :actions="quickExecuteActions" :title="$t('Sync')" type="primary" />
|
||||||
<RelationCard
|
<RelationCard
|
||||||
ref="StrategyRelation"
|
ref="StrategyRelation"
|
||||||
v-perms="'xpack.change_strategy'"
|
v-perms="'xpack.change_strategy'"
|
||||||
|
@@ -1,64 +1,37 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<SmallCard ref="table" class="account-table" v-bind="table" />
|
<SmallCard ref="table" class="account-table" v-bind="table" />
|
||||||
<CreateDialog v-if="visible" :visible.sync="visible" v-bind="providerConfig" />
|
<CreateDialog
|
||||||
<UpdateDialog v-if="updateVisible" :object="object" :update-visible="updateVisible" />
|
v-if="visible"
|
||||||
<Dialog
|
:visible.sync="visible"
|
||||||
:close-on-click-modal="false"
|
v-bind="providerConfig"
|
||||||
:close-on-press-escape="false"
|
/>
|
||||||
:destroy-on-close="true"
|
<UpdateDialog
|
||||||
:show-buttons="false"
|
v-if="updateVisible"
|
||||||
:show-close="false"
|
:object="object"
|
||||||
:title="$tc('SyncOnline')"
|
:visible.sync="updateVisible"
|
||||||
|
@submitSuccess="onSubmitSuccess"
|
||||||
|
/>
|
||||||
|
<SyncDialog
|
||||||
|
v-if="onlineSyncVisible"
|
||||||
:visible.sync="onlineSyncVisible"
|
:visible.sync="onlineSyncVisible"
|
||||||
v-on="$listeners"
|
/>
|
||||||
>
|
|
||||||
<AssetPanel :object="object" :visible.sync="onlineSyncVisible" />
|
|
||||||
</Dialog>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script type="text/jsx">
|
<script type="text/jsx">
|
||||||
import {
|
import { lan, privateCloudProviders, publicCloudProviders } from '../const'
|
||||||
aliyun,
|
|
||||||
apsara_stack,
|
|
||||||
aws_china,
|
|
||||||
aws_international,
|
|
||||||
azure,
|
|
||||||
azure_international,
|
|
||||||
baiducloud,
|
|
||||||
fc,
|
|
||||||
gcp,
|
|
||||||
huaweicloud,
|
|
||||||
huaweicloud_private,
|
|
||||||
jdcloud,
|
|
||||||
kingsoftcloud,
|
|
||||||
lan,
|
|
||||||
nutanix,
|
|
||||||
openstack,
|
|
||||||
qcloud,
|
|
||||||
qcloud_lighthouse,
|
|
||||||
qingcloud_private,
|
|
||||||
scp,
|
|
||||||
state_private,
|
|
||||||
ucloud,
|
|
||||||
vmware,
|
|
||||||
volcengine,
|
|
||||||
zstack
|
|
||||||
} from '../const'
|
|
||||||
import CreateDialog from './components/CreateDialog.vue'
|
import CreateDialog from './components/CreateDialog.vue'
|
||||||
import UpdateDialog from './components/UpdateDialog.vue'
|
import UpdateDialog from './components/UpdateDialog.vue'
|
||||||
|
import SyncDialog from './components/SyncDialog.vue'
|
||||||
import SmallCard from '@/components/Table/CardTable/DataCardTable/index.vue'
|
import SmallCard from '@/components/Table/CardTable/DataCardTable/index.vue'
|
||||||
import { ACCOUNT_PROVIDER_ATTRS_MAP } from '@/views/assets/Cloud/const'
|
import { ACCOUNT_PROVIDER_ATTRS_MAP } from '@/views/assets/Cloud/const'
|
||||||
import Dialog from '@/components/Dialog/index.vue'
|
|
||||||
import AssetPanel from './components/AssetPanel.vue'
|
|
||||||
import { toSafeLocalDateStr } from '@/utils/time'
|
import { toSafeLocalDateStr } from '@/utils/time'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'CloudAccountList',
|
name: 'CloudAccountList',
|
||||||
components: {
|
components: {
|
||||||
AssetPanel,
|
SyncDialog,
|
||||||
Dialog,
|
|
||||||
SmallCard,
|
SmallCard,
|
||||||
CreateDialog,
|
CreateDialog,
|
||||||
UpdateDialog
|
UpdateDialog
|
||||||
@@ -128,13 +101,7 @@ export default {
|
|||||||
title: this.$t('PublicCloud'),
|
title: this.$t('PublicCloud'),
|
||||||
icon: 'public-cloud',
|
icon: 'public-cloud',
|
||||||
callback: () => {
|
callback: () => {
|
||||||
const providers = [
|
this.providerConfig.providers = publicCloudProviders.map(
|
||||||
aliyun, qcloud, qcloud_lighthouse, huaweicloud,
|
|
||||||
baiducloud, jdcloud, kingsoftcloud, aws_china,
|
|
||||||
aws_international, azure, azure_international,
|
|
||||||
gcp, ucloud, volcengine
|
|
||||||
]
|
|
||||||
this.providerConfig.providers = providers.map(
|
|
||||||
(item) => ACCOUNT_PROVIDER_ATTRS_MAP[item]
|
(item) => ACCOUNT_PROVIDER_ATTRS_MAP[item]
|
||||||
)
|
)
|
||||||
this.visible = true
|
this.visible = true
|
||||||
@@ -145,11 +112,7 @@ export default {
|
|||||||
icon: 'private-cloud',
|
icon: 'private-cloud',
|
||||||
title: this.$t('PrivateCloud'),
|
title: this.$t('PrivateCloud'),
|
||||||
callback: () => {
|
callback: () => {
|
||||||
const providers = [
|
this.providerConfig.providers = privateCloudProviders.map(
|
||||||
vmware, qingcloud_private, huaweicloud_private, state_private,
|
|
||||||
openstack, zstack, nutanix, fc, scp, apsara_stack
|
|
||||||
]
|
|
||||||
this.providerConfig.providers = providers.map(
|
|
||||||
(item) => ACCOUNT_PROVIDER_ATTRS_MAP[item]
|
(item) => ACCOUNT_PROVIDER_ATTRS_MAP[item]
|
||||||
)
|
)
|
||||||
this.visible = true
|
this.visible = true
|
||||||
|
@@ -124,7 +124,12 @@ export default {
|
|||||||
|
|
||||||
.right-content {
|
.right-content {
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
padding: 20px 10px;
|
|
||||||
|
::v-deep {
|
||||||
|
.el-form {
|
||||||
|
padding: 20px 20px 20px 10px
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
::v-deep .el-step {
|
::v-deep .el-step {
|
||||||
|
48
src/views/assets/Cloud/Account/components/SyncDialog.vue
Normal file
48
src/views/assets/Cloud/Account/components/SyncDialog.vue
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
<template>
|
||||||
|
<Dialog
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
:close-on-press-escape="false"
|
||||||
|
:destroy-on-close="true"
|
||||||
|
:show-buttons="false"
|
||||||
|
:show-close="false"
|
||||||
|
:title="$tc('SyncOnline')"
|
||||||
|
:visible.sync="iVisible"
|
||||||
|
v-on="$listeners"
|
||||||
|
>
|
||||||
|
<AssetPanel :object="object" :visible.sync="iVisible" />
|
||||||
|
</Dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import AssetPanel from '@/views/assets/Cloud/Account/components/AssetPanel.vue'
|
||||||
|
import Dialog from '@/components/Dialog/index.vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'SyncDialog',
|
||||||
|
components: { Dialog, AssetPanel },
|
||||||
|
props: {
|
||||||
|
object: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({})
|
||||||
|
},
|
||||||
|
visible: {
|
||||||
|
type: Boolean,
|
||||||
|
default: () => false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
iVisible: {
|
||||||
|
set(val) {
|
||||||
|
this.$emit('update:visible', val)
|
||||||
|
},
|
||||||
|
get() {
|
||||||
|
return this.visible
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
|
||||||
|
</style>
|
@@ -1,44 +1,69 @@
|
|||||||
<template>
|
<template>
|
||||||
<Drawer
|
<Drawer
|
||||||
v-if="updateVisible"
|
|
||||||
:destroy-on-close="true"
|
:destroy-on-close="true"
|
||||||
:show-buttons="false"
|
:show-buttons="false"
|
||||||
:title="$tc('CloudAccountUpdate')"
|
:title="$tc('CloudAccountUpdate')"
|
||||||
:visible.sync="updateVisible"
|
:visible.sync="iVisible"
|
||||||
|
class="drawer"
|
||||||
v-on="$listeners"
|
v-on="$listeners"
|
||||||
>
|
>
|
||||||
<div style="background: white">
|
<IBox>
|
||||||
<AuthPanel
|
<AuthPanel
|
||||||
:object="object"
|
:object="object"
|
||||||
:provider="object.provider.value"
|
:provider="object.provider.value"
|
||||||
:visible.sync="updateVisible"
|
:visible.sync="iVisible"
|
||||||
origin="update"
|
origin="update"
|
||||||
@submitSuccess="onSubmitSuccess"
|
@submitSuccess="onSubmitSuccess"
|
||||||
/>
|
/>
|
||||||
</div>
|
</IBox>
|
||||||
</Drawer>
|
</Drawer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import AuthPanel from '@/views/assets/Cloud/Account/components/AuthPanel.vue'
|
import AuthPanel from '@/views/assets/Cloud/Account/components/AuthPanel.vue'
|
||||||
import Drawer from '@/components/Drawer/index.vue'
|
import Drawer from '@/components/Drawer/index.vue'
|
||||||
|
import IBox from '@/components/Common/IBox/index.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'UpdateDialog',
|
name: 'UpdateDialog',
|
||||||
components: { Drawer, AuthPanel },
|
components: { Drawer, AuthPanel, IBox },
|
||||||
props: {
|
props: {
|
||||||
object: {
|
object: {
|
||||||
type: Object,
|
type: Object,
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
updateVisible: {
|
visible: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
iVisible: {
|
||||||
|
set(val) {
|
||||||
|
this.$emit('update:visible', val)
|
||||||
|
},
|
||||||
|
get() {
|
||||||
|
return this.visible
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onSubmitSuccess() {
|
||||||
|
this.$emit('submitSuccess')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
.ibox {
|
||||||
|
margin: 15px
|
||||||
|
}
|
||||||
|
|
||||||
|
.drawer ::v-deep {
|
||||||
|
.el-drawer__body {
|
||||||
|
background: #f3f3f3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
@@ -1,18 +1,25 @@
|
|||||||
<template>
|
<template>
|
||||||
<GenericListTable :header-actions="headerActions" :table-config="tableConfig" />
|
<DrawerListTable
|
||||||
|
:create-drawer="createDrawer"
|
||||||
|
:detail-drawer="detailDrawer"
|
||||||
|
:header-actions="headerActions"
|
||||||
|
:table-config="tableConfig"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script type="text/jsx">
|
<script type="text/jsx">
|
||||||
import GenericListTable from '@/layout/components/GenericListTable'
|
import { DrawerListTable } from '@/components'
|
||||||
import { DetailFormatter } from '@/components/Table/TableFormatters'
|
import { DetailFormatter } from '@/components/Table/TableFormatters'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'StrategyList',
|
name: 'StrategyList',
|
||||||
components: {
|
components: {
|
||||||
GenericListTable
|
DrawerListTable
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
createDrawer: () => import('@/views/assets/Cloud/Strategy/StrategyCreateUpdate.vue'),
|
||||||
|
detailDrawer: () => import('@/views/assets/Cloud/Strategy/StrategyDetail/index.vue'),
|
||||||
tableConfig: {
|
tableConfig: {
|
||||||
url: '/api/v1/xpack/cloud/strategies/',
|
url: '/api/v1/xpack/cloud/strategies/',
|
||||||
permissions: {
|
permissions: {
|
||||||
@@ -31,17 +38,25 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
strategy_rules: {
|
strategy_rules: {
|
||||||
formatter: (row) => { return row.strategy_rules.length }
|
formatter: (row) => {
|
||||||
|
return row.strategy_rules.length
|
||||||
|
}
|
||||||
},
|
},
|
||||||
strategy_actions: {
|
strategy_actions: {
|
||||||
formatter: (row) => { return row.strategy_actions.length }
|
formatter: (row) => {
|
||||||
|
return row.strategy_actions.length
|
||||||
|
}
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
formatterArgs: {
|
formatterArgs: {
|
||||||
updateRoute: 'CloudStrategyUpdate',
|
updateRoute: 'CloudStrategyUpdate',
|
||||||
hasClone: false,
|
hasClone: false,
|
||||||
canDelete: ({ row }) => { return row.name !== 'default' },
|
canDelete: ({ row }) => {
|
||||||
canUpdate: ({ row }) => { return row.name !== 'default' }
|
return row.name !== 'default'
|
||||||
|
},
|
||||||
|
canUpdate: ({ row }) => {
|
||||||
|
return row.name !== 'default'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -54,8 +69,7 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@@ -39,7 +39,8 @@ export default {
|
|||||||
submitBtnSize: 'mini',
|
submitBtnSize: 'mini',
|
||||||
submitBtnText: this.$t('Add'),
|
submitBtnText: this.$t('Add'),
|
||||||
hasReset: false,
|
hasReset: false,
|
||||||
onSubmit: () => {},
|
onSubmit: () => {
|
||||||
|
},
|
||||||
submitMethod: () => 'post',
|
submitMethod: () => 'post',
|
||||||
getUrl: () => '',
|
getUrl: () => '',
|
||||||
cleanFormValue(data) {
|
cleanFormValue(data) {
|
||||||
@@ -247,7 +248,6 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.action-input {
|
.action-input {
|
||||||
margin-top: -10px;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
@@ -15,10 +15,10 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import GenericCreateUpdateForm from '@/layout/components/GenericCreateUpdateForm'
|
import GenericCreateUpdateForm from '@/layout/components/GenericCreateUpdateForm/index.vue'
|
||||||
import Dialog from '@/components/Dialog/index.vue'
|
import Dialog from '@/components/Dialog/index.vue'
|
||||||
import RuleInput from '@/views/assets/Cloud/Strategy/components/RuleInput'
|
import RuleInput from '@/views/assets/Cloud/Strategy/components/RuleInput.vue'
|
||||||
import ActionInput from '@/views/assets/Cloud/Strategy/components/ActionInput'
|
import ActionInput from '@/views/assets/Cloud/Strategy/components/ActionInput.vue'
|
||||||
import IBox from '@/components/Common/IBox/index.vue'
|
import IBox from '@/components/Common/IBox/index.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
@@ -1,150 +0,0 @@
|
|||||||
<template>
|
|
||||||
<GenericCreateUpdatePage ref="createUpdatePage" v-bind="$data" />
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { GenericCreateUpdatePage } from '@/layout/components'
|
|
||||||
import { Select2 } from '@/components'
|
|
||||||
import rules from '@/components/Form/DataForm/rules'
|
|
||||||
import SyncInstanceTaskStrategy from './components/SyncInstanceTaskStrategy/index'
|
|
||||||
import { periodicMeta } from '@/components/const'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
components: {
|
|
||||||
GenericCreateUpdatePage
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
const vm = this
|
|
||||||
return {
|
|
||||||
initial: {
|
|
||||||
is_periodic: true,
|
|
||||||
interval: 24,
|
|
||||||
hostname_strategy: 'instance_name_partial_ip',
|
|
||||||
ip_network_segment_group: ['*']
|
|
||||||
},
|
|
||||||
fields: [
|
|
||||||
[this.$t('common.Basic'), ['name']],
|
|
||||||
[this.$t('xpack.Cloud.CloudSource'), ['account', 'regions']],
|
|
||||||
[this.$t('xpack.Cloud.SaveSetting'), [
|
|
||||||
'hostname_strategy', 'ip_network_segment_group',
|
|
||||||
'sync_ip_type', 'is_always_update', 'fully_synchronous'
|
|
||||||
]],
|
|
||||||
[this.$t('xpack.Cloud.SyncStrategy'), ['strategy']],
|
|
||||||
[this.$t('xpack.Timer'), ['is_periodic', 'crontab', 'interval']],
|
|
||||||
[this.$t('common.Other'), ['comment']]
|
|
||||||
],
|
|
||||||
url: '/api/v1/xpack/cloud/sync-instance-tasks/',
|
|
||||||
fieldsMeta: {
|
|
||||||
...periodicMeta,
|
|
||||||
account: {
|
|
||||||
label: this.$t('xpack.Cloud.Account'),
|
|
||||||
on: {
|
|
||||||
change: ([event], updateForm) => {
|
|
||||||
vm.fieldsMeta.regions.el.ajax.url = `/api/v1/xpack/cloud/regions/?account_id=${event?.pk}`
|
|
||||||
updateForm({ regions: '' })
|
|
||||||
}
|
|
||||||
},
|
|
||||||
el: {
|
|
||||||
multiple: false,
|
|
||||||
value: [],
|
|
||||||
ajax: {
|
|
||||||
url: '/api/v1/xpack/cloud/accounts/',
|
|
||||||
transformOption: (item) => {
|
|
||||||
const label = `${item.name}(${item.provider.label})`
|
|
||||||
return { label: label, value: item.id }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
hostname_strategy: {
|
|
||||||
rules: [rules.RequiredChange],
|
|
||||||
helpTips: this.$t('xpack.Cloud.HostnameStrategy')
|
|
||||||
},
|
|
||||||
is_always_update: {
|
|
||||||
type: 'checkbox',
|
|
||||||
label: this.$t('xpack.Cloud.IsAlwaysUpdate'),
|
|
||||||
helpTips: this.$t('xpack.Cloud.IsAlwaysUpdateHelpTips')
|
|
||||||
},
|
|
||||||
fully_synchronous: {
|
|
||||||
type: 'checkbox',
|
|
||||||
label: this.$t('xpack.Cloud.FullySynchronous'),
|
|
||||||
helpTips: this.$t('xpack.Cloud.FullySynchronousHelpTips')
|
|
||||||
},
|
|
||||||
regions: {
|
|
||||||
component: Select2,
|
|
||||||
el: {
|
|
||||||
multiple: true,
|
|
||||||
allowCreate: true,
|
|
||||||
value: [],
|
|
||||||
ajax: {
|
|
||||||
url: '/api/v1/xpack/cloud/regions/',
|
|
||||||
processResults(data) {
|
|
||||||
const results = data.regions?.map((item) => {
|
|
||||||
return { label: item.name, value: item.id }
|
|
||||||
})
|
|
||||||
const more = !!data.next
|
|
||||||
return { results: results, pagination: more, total: data.count }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
strategy: {
|
|
||||||
label: this.$t('common.Strategy'),
|
|
||||||
component: SyncInstanceTaskStrategy,
|
|
||||||
helpTips: this.$t('xpack.Cloud.StrategyHelpTips')
|
|
||||||
}
|
|
||||||
},
|
|
||||||
updateSuccessNextRoute: { name: 'CloudCenter' },
|
|
||||||
createSuccessNextRoute: { name: 'CloudCenter' },
|
|
||||||
afterGetFormValue(formValue) {
|
|
||||||
formValue.protocols = formValue.protocols?.split(' ').map(i => {
|
|
||||||
const [name, port] = i.split('/')
|
|
||||||
return { name, port }
|
|
||||||
})
|
|
||||||
return formValue
|
|
||||||
},
|
|
||||||
cleanFormValue(value) {
|
|
||||||
const ipNetworkSegments = value.ip_network_segment_group
|
|
||||||
const strategy = value?.strategy || []
|
|
||||||
if (!Array.isArray(ipNetworkSegments)) {
|
|
||||||
value.ip_network_segment_group = ipNetworkSegments ? ipNetworkSegments.split(',') : []
|
|
||||||
}
|
|
||||||
value.strategy = strategy.map(item => {
|
|
||||||
return item.id
|
|
||||||
})
|
|
||||||
return value
|
|
||||||
},
|
|
||||||
onPerformError(error, method, vm) {
|
|
||||||
this.$emit('submitError', error)
|
|
||||||
const response = error.response
|
|
||||||
const data = response.data
|
|
||||||
if (response.status === 400) {
|
|
||||||
for (const key of Object.keys(data)) {
|
|
||||||
let value = data[key]
|
|
||||||
if (key === 'protocols') {
|
|
||||||
value = Object.values(data[key])
|
|
||||||
}
|
|
||||||
if (value instanceof Array) {
|
|
||||||
value = value.join(';')
|
|
||||||
}
|
|
||||||
this.$refs.form.setFieldError(key, value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
async mounted() {
|
|
||||||
const params = this.$route.params
|
|
||||||
// 更新获取链接
|
|
||||||
if (params.id) {
|
|
||||||
const form = await this.$refs.createUpdatePage.$refs.createUpdateForm.getFormValue()
|
|
||||||
this.fieldsMeta.regions.el.ajax.url = form.account?.id ? `/api/v1/xpack/cloud/regions/?account_id=${form.account.id}` : `/api/v1/xpack/cloud/regions/`
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {}
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="less" scoped>
|
|
||||||
</style>
|
|
@@ -29,6 +29,18 @@ export const scp = 'scp'
|
|||||||
export const apsara_stack = 'apsara_stack'
|
export const apsara_stack = 'apsara_stack'
|
||||||
export const lan = 'lan'
|
export const lan = 'lan'
|
||||||
|
|
||||||
|
export const publicCloudProviders = [
|
||||||
|
aliyun, qcloud, qcloud_lighthouse, huaweicloud,
|
||||||
|
baiducloud, jdcloud, kingsoftcloud, aws_china,
|
||||||
|
aws_international, azure, azure_international,
|
||||||
|
gcp, ucloud, volcengine
|
||||||
|
]
|
||||||
|
|
||||||
|
export const privateCloudProviders = [
|
||||||
|
vmware, qingcloud_private, huaweicloud_private, state_private,
|
||||||
|
openstack, zstack, nutanix, fc, scp, apsara_stack
|
||||||
|
]
|
||||||
|
|
||||||
export const ACCOUNT_PROVIDER_ATTRS_MAP = {
|
export const ACCOUNT_PROVIDER_ATTRS_MAP = {
|
||||||
[aliyun]: {
|
[aliyun]: {
|
||||||
name: aliyun,
|
name: aliyun,
|
||||||
|
Reference in New Issue
Block a user