mirror of
https://github.com/jumpserver/lina.git
synced 2025-09-24 20:47:17 +00:00
perf: update cloud sync
This commit is contained in:
@@ -27,7 +27,9 @@ export default {
|
||||
},
|
||||
beforeSubmit: {
|
||||
type: Function,
|
||||
default: (val) => { return true }
|
||||
default: (val) => {
|
||||
return true
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
@@ -50,14 +52,16 @@ export default {
|
||||
::v-deep .el-select {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
::v-deep .el-form-item__content {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
::v-deep .form-buttons {
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
.attr-input {
|
||||
margin-top: -10px;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
@@ -9,7 +9,6 @@ const clouds = {
|
||||
},
|
||||
hidden: true,
|
||||
meta: {
|
||||
title: i18n.t('BaseCloudSync'),
|
||||
app: 'xpack',
|
||||
resource: 'account'
|
||||
},
|
||||
@@ -41,32 +40,10 @@ const clouds = {
|
||||
hidden: true,
|
||||
redirect: '/console/assets/cloud',
|
||||
meta: {
|
||||
title: i18n.t('CloudAccountList'),
|
||||
title: i18n.t('CloudSync'),
|
||||
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/',
|
||||
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 #right>
|
||||
<QuickActions :actions="quickEditActions" type="primary" />
|
||||
<QuickActions :actions="quickExecuteActions" type="primary" />
|
||||
<QuickActions :actions="quickExecuteActions" :title="$t('Sync')" type="primary" />
|
||||
<RelationCard
|
||||
ref="StrategyRelation"
|
||||
v-perms="'xpack.change_strategy'"
|
||||
|
@@ -1,64 +1,37 @@
|
||||
<template>
|
||||
<div>
|
||||
<SmallCard ref="table" class="account-table" v-bind="table" />
|
||||
<CreateDialog v-if="visible" :visible.sync="visible" v-bind="providerConfig" />
|
||||
<UpdateDialog v-if="updateVisible" :object="object" :update-visible="updateVisible" />
|
||||
<Dialog
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
:destroy-on-close="true"
|
||||
:show-buttons="false"
|
||||
:show-close="false"
|
||||
:title="$tc('SyncOnline')"
|
||||
<CreateDialog
|
||||
v-if="visible"
|
||||
:visible.sync="visible"
|
||||
v-bind="providerConfig"
|
||||
/>
|
||||
<UpdateDialog
|
||||
v-if="updateVisible"
|
||||
:object="object"
|
||||
:visible.sync="updateVisible"
|
||||
@submitSuccess="onSubmitSuccess"
|
||||
/>
|
||||
<SyncDialog
|
||||
v-if="onlineSyncVisible"
|
||||
:visible.sync="onlineSyncVisible"
|
||||
v-on="$listeners"
|
||||
>
|
||||
<AssetPanel :object="object" :visible.sync="onlineSyncVisible" />
|
||||
</Dialog>
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script type="text/jsx">
|
||||
import {
|
||||
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 { lan, privateCloudProviders, publicCloudProviders } from '../const'
|
||||
import CreateDialog from './components/CreateDialog.vue'
|
||||
import UpdateDialog from './components/UpdateDialog.vue'
|
||||
import SyncDialog from './components/SyncDialog.vue'
|
||||
import SmallCard from '@/components/Table/CardTable/DataCardTable/index.vue'
|
||||
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'
|
||||
|
||||
export default {
|
||||
name: 'CloudAccountList',
|
||||
components: {
|
||||
AssetPanel,
|
||||
Dialog,
|
||||
SyncDialog,
|
||||
SmallCard,
|
||||
CreateDialog,
|
||||
UpdateDialog
|
||||
@@ -128,13 +101,7 @@ export default {
|
||||
title: this.$t('PublicCloud'),
|
||||
icon: 'public-cloud',
|
||||
callback: () => {
|
||||
const providers = [
|
||||
aliyun, qcloud, qcloud_lighthouse, huaweicloud,
|
||||
baiducloud, jdcloud, kingsoftcloud, aws_china,
|
||||
aws_international, azure, azure_international,
|
||||
gcp, ucloud, volcengine
|
||||
]
|
||||
this.providerConfig.providers = providers.map(
|
||||
this.providerConfig.providers = publicCloudProviders.map(
|
||||
(item) => ACCOUNT_PROVIDER_ATTRS_MAP[item]
|
||||
)
|
||||
this.visible = true
|
||||
@@ -145,11 +112,7 @@ export default {
|
||||
icon: 'private-cloud',
|
||||
title: this.$t('PrivateCloud'),
|
||||
callback: () => {
|
||||
const providers = [
|
||||
vmware, qingcloud_private, huaweicloud_private, state_private,
|
||||
openstack, zstack, nutanix, fc, scp, apsara_stack
|
||||
]
|
||||
this.providerConfig.providers = providers.map(
|
||||
this.providerConfig.providers = privateCloudProviders.map(
|
||||
(item) => ACCOUNT_PROVIDER_ATTRS_MAP[item]
|
||||
)
|
||||
this.visible = true
|
||||
|
@@ -124,7 +124,12 @@ export default {
|
||||
|
||||
.right-content {
|
||||
background-color: #fff;
|
||||
padding: 20px 10px;
|
||||
|
||||
::v-deep {
|
||||
.el-form {
|
||||
padding: 20px 20px 20px 10px
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
::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>
|
||||
<Drawer
|
||||
v-if="updateVisible"
|
||||
:destroy-on-close="true"
|
||||
:show-buttons="false"
|
||||
:title="$tc('CloudAccountUpdate')"
|
||||
:visible.sync="updateVisible"
|
||||
:visible.sync="iVisible"
|
||||
class="drawer"
|
||||
v-on="$listeners"
|
||||
>
|
||||
<div style="background: white">
|
||||
<IBox>
|
||||
<AuthPanel
|
||||
:object="object"
|
||||
:provider="object.provider.value"
|
||||
:visible.sync="updateVisible"
|
||||
:visible.sync="iVisible"
|
||||
origin="update"
|
||||
@submitSuccess="onSubmitSuccess"
|
||||
/>
|
||||
</div>
|
||||
</IBox>
|
||||
</Drawer>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import AuthPanel from '@/views/assets/Cloud/Account/components/AuthPanel.vue'
|
||||
import Drawer from '@/components/Drawer/index.vue'
|
||||
import IBox from '@/components/Common/IBox/index.vue'
|
||||
|
||||
export default {
|
||||
name: 'UpdateDialog',
|
||||
components: { Drawer, AuthPanel },
|
||||
components: { Drawer, AuthPanel, IBox },
|
||||
props: {
|
||||
object: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
updateVisible: {
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
iVisible: {
|
||||
set(val) {
|
||||
this.$emit('update:visible', val)
|
||||
},
|
||||
get() {
|
||||
return this.visible
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onSubmitSuccess() {
|
||||
this.$emit('submitSuccess')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.ibox {
|
||||
margin: 15px
|
||||
}
|
||||
|
||||
.drawer ::v-deep {
|
||||
.el-drawer__body {
|
||||
background: #f3f3f3;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
@@ -1,18 +1,25 @@
|
||||
<template>
|
||||
<GenericListTable :header-actions="headerActions" :table-config="tableConfig" />
|
||||
<DrawerListTable
|
||||
:create-drawer="createDrawer"
|
||||
:detail-drawer="detailDrawer"
|
||||
:header-actions="headerActions"
|
||||
:table-config="tableConfig"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script type="text/jsx">
|
||||
import GenericListTable from '@/layout/components/GenericListTable'
|
||||
import { DrawerListTable } from '@/components'
|
||||
import { DetailFormatter } from '@/components/Table/TableFormatters'
|
||||
|
||||
export default {
|
||||
name: 'StrategyList',
|
||||
components: {
|
||||
GenericListTable
|
||||
DrawerListTable
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
createDrawer: () => import('@/views/assets/Cloud/Strategy/StrategyCreateUpdate.vue'),
|
||||
detailDrawer: () => import('@/views/assets/Cloud/Strategy/StrategyDetail/index.vue'),
|
||||
tableConfig: {
|
||||
url: '/api/v1/xpack/cloud/strategies/',
|
||||
permissions: {
|
||||
@@ -31,17 +38,25 @@ export default {
|
||||
}
|
||||
},
|
||||
strategy_rules: {
|
||||
formatter: (row) => { return row.strategy_rules.length }
|
||||
formatter: (row) => {
|
||||
return row.strategy_rules.length
|
||||
}
|
||||
},
|
||||
strategy_actions: {
|
||||
formatter: (row) => { return row.strategy_actions.length }
|
||||
formatter: (row) => {
|
||||
return row.strategy_actions.length
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
formatterArgs: {
|
||||
updateRoute: 'CloudStrategyUpdate',
|
||||
hasClone: false,
|
||||
canDelete: ({ row }) => { return row.name !== 'default' },
|
||||
canUpdate: ({ row }) => { return row.name !== 'default' }
|
||||
canDelete: ({ row }) => {
|
||||
return row.name !== 'default'
|
||||
},
|
||||
canUpdate: ({ row }) => {
|
||||
return row.name !== 'default'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -54,8 +69,7 @@ export default {
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
}
|
||||
methods: {}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
@@ -39,7 +39,8 @@ export default {
|
||||
submitBtnSize: 'mini',
|
||||
submitBtnText: this.$t('Add'),
|
||||
hasReset: false,
|
||||
onSubmit: () => {},
|
||||
onSubmit: () => {
|
||||
},
|
||||
submitMethod: () => 'post',
|
||||
getUrl: () => '',
|
||||
cleanFormValue(data) {
|
||||
@@ -247,7 +248,6 @@ export default {
|
||||
}
|
||||
|
||||
.action-input {
|
||||
margin-top: -10px;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
@@ -15,10 +15,10 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import GenericCreateUpdateForm from '@/layout/components/GenericCreateUpdateForm'
|
||||
import GenericCreateUpdateForm from '@/layout/components/GenericCreateUpdateForm/index.vue'
|
||||
import Dialog from '@/components/Dialog/index.vue'
|
||||
import RuleInput from '@/views/assets/Cloud/Strategy/components/RuleInput'
|
||||
import ActionInput from '@/views/assets/Cloud/Strategy/components/ActionInput'
|
||||
import RuleInput from '@/views/assets/Cloud/Strategy/components/RuleInput.vue'
|
||||
import ActionInput from '@/views/assets/Cloud/Strategy/components/ActionInput.vue'
|
||||
import IBox from '@/components/Common/IBox/index.vue'
|
||||
|
||||
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 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 = {
|
||||
[aliyun]: {
|
||||
name: aliyun,
|
||||
|
Reference in New Issue
Block a user