mirror of https://github.com/rancher/dashboard.git
Merge pull request #1243 from mantis-toboggan-md/backup-restore-op-deployment
Backup restore op deployment
This commit is contained in:
commit
d99ec480d0
|
|
@ -69,7 +69,7 @@ $selected: rgba($primary, .5);
|
||||||
--header-btn-bg : #317DB0;
|
--header-btn-bg : #317DB0;
|
||||||
--header-btn-text : white;
|
--header-btn-text : white;
|
||||||
--header-height : 50px;
|
--header-height : 50px;
|
||||||
--nav-width : 230px;
|
--nav-width : 250px;
|
||||||
--nav-bg : #{$lighter};
|
--nav-bg : #{$lighter};
|
||||||
--nav-active : #{rgba($primary, 0.3)};
|
--nav-active : #{rgba($primary, 0.3)};
|
||||||
--footer-bg : transparent;
|
--footer-bg : transparent;
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ nav:
|
||||||
|
|
||||||
product:
|
product:
|
||||||
apps: Apps & Marketplace
|
apps: Apps & Marketplace
|
||||||
backup: Backup Restore Operator
|
backup: Backup & Restore Operator
|
||||||
cis: CIS Benchmark
|
cis: CIS Benchmark
|
||||||
ecm: Cluster Manager
|
ecm: Cluster Manager
|
||||||
explorer: Cluster Explorer
|
explorer: Cluster Explorer
|
||||||
|
|
@ -137,6 +137,19 @@ asyncButton:
|
||||||
|
|
||||||
backupRestoreOperator:
|
backupRestoreOperator:
|
||||||
backupFilename: Backup Filename
|
backupFilename: Backup Filename
|
||||||
|
deployment:
|
||||||
|
rancherNamespace: Rancher ResourceSet Namespace
|
||||||
|
storage:
|
||||||
|
tip: Configure a storage location where all backups are saved by default. You will have the option to override this with each backup, but will be limited to using an S3-compatible object store.
|
||||||
|
storageClass: Storage Class
|
||||||
|
persistentVolume: Persistent Volume
|
||||||
|
label: Default Storage Location
|
||||||
|
options:
|
||||||
|
s3: Use an S3-compatible object store
|
||||||
|
defaultStorageClass: 'Use the default storage class ({name})'
|
||||||
|
pickSC: Use an existing storage class
|
||||||
|
pickPV: Use an existing persistent volume
|
||||||
|
size: Size
|
||||||
prune:
|
prune:
|
||||||
label: Prune
|
label: Prune
|
||||||
tip: Delete all resources that match the ResourceSet used, but are not present in the backup. (Recommended)
|
tip: Delete all resources that match the ResourceSet used, but are not present in the backup. (Recommended)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,88 @@
|
||||||
|
<script>
|
||||||
|
import LabeledInput from '@/components/form/LabeledInput';
|
||||||
|
import Checkbox from '@/components/form/Checkbox';
|
||||||
|
import FileSelector from '@/components/form/FileSelector';
|
||||||
|
import LabeledSelect from '@/components/form/LabeledSelect';
|
||||||
|
import { mapGetters } from 'vuex';
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
LabeledInput,
|
||||||
|
Checkbox,
|
||||||
|
FileSelector,
|
||||||
|
LabeledSelect,
|
||||||
|
},
|
||||||
|
|
||||||
|
props: {
|
||||||
|
value: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mode: {
|
||||||
|
type: String,
|
||||||
|
default: 'create'
|
||||||
|
},
|
||||||
|
|
||||||
|
secrets: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
credentialSecret: {
|
||||||
|
get() {
|
||||||
|
const { credentialSecretName, credentialSecretNamespace } = this.value;
|
||||||
|
|
||||||
|
return { metadata: { name: credentialSecretName, namespace: credentialSecretNamespace } };
|
||||||
|
},
|
||||||
|
|
||||||
|
set(neu) {
|
||||||
|
const { name, namespace } = neu.metadata;
|
||||||
|
|
||||||
|
this.$set(this.value, 'credentialSecretName', name);
|
||||||
|
this.$set(this.value, 'credentialSecretNamespace', namespace);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
...mapGetters({ t: 'i18n/t' })
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div class="row mb-10">
|
||||||
|
<div class="col span-6">
|
||||||
|
<LabeledSelect
|
||||||
|
v-model="credentialSecret"
|
||||||
|
:get-option-label="opt=>opt.metadata.name || ''"
|
||||||
|
:mode="mode"
|
||||||
|
:options="secrets"
|
||||||
|
:label="t('backupRestoreOperator.s3.credentialSecretName')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="col span-6">
|
||||||
|
<LabeledInput v-model="value.bucketName" :mode="mode" :label="t('backupRestoreOperator.s3.bucketName')" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-10">
|
||||||
|
<div class="col span-6">
|
||||||
|
<LabeledInput v-model="value.region" :mode="mode" :label="t('backupRestoreOperator.s3.region')" />
|
||||||
|
</div>
|
||||||
|
<div class="col span-6">
|
||||||
|
<LabeledInput v-model="value.folder" :mode="mode" :label="t('backupRestoreOperator.s3.folder')" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-10">
|
||||||
|
<div class="col span-6">
|
||||||
|
<LabeledInput v-model="value.endpoint" :mode="mode" :label="t('backupRestoreOperator.s3.endpoint')" />
|
||||||
|
<Checkbox v-model="value.insecureTLSSkipVerify" class="mt-10" :mode="mode" :label="t('backupRestoreOperator.s3.insecureTLSSkipVerify')" />
|
||||||
|
</div>
|
||||||
|
<div class="col span-6">
|
||||||
|
<LabeledInput v-model="value.endpointCA" :mode="mode" type="multiline" :label="t('backupRestoreOperator.s3.endpointCA')" />
|
||||||
|
<FileSelector v-if="mode!=='view'" class="btn btn-sm role-primary mt-5" :mode="mode" :label="t('generic.readFromFile')" @selected="e=>$set(s3, 'endpointCA', e)" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
@ -0,0 +1,199 @@
|
||||||
|
<script>
|
||||||
|
import Tab from '@/components/Tabbed/Tab';
|
||||||
|
import S3 from '@/chart/backup-restore-operator/S3';
|
||||||
|
import RadioGroup from '@/components/form/RadioGroup';
|
||||||
|
import LabeledSelect from '@/components/form/LabeledSelect';
|
||||||
|
import LabeledInput from '@/components/form/LabeledInput';
|
||||||
|
import Banner from '@/components/Banner';
|
||||||
|
import { get } from '@/utils/object';
|
||||||
|
import { allHash } from '@/utils/promise';
|
||||||
|
import { STORAGE_CLASS, SECRET, PV } from '@/config/types';
|
||||||
|
import { mapGetters } from 'vuex';
|
||||||
|
import { STORAGE } from '@/config/labels-annotations';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
Tab,
|
||||||
|
RadioGroup,
|
||||||
|
S3,
|
||||||
|
LabeledInput,
|
||||||
|
LabeledSelect,
|
||||||
|
Banner
|
||||||
|
},
|
||||||
|
|
||||||
|
hasTabs: true,
|
||||||
|
|
||||||
|
props: {
|
||||||
|
value: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
mode: {
|
||||||
|
type: String,
|
||||||
|
default: 'create'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
async fetch() {
|
||||||
|
const hash = await allHash({
|
||||||
|
storageClasses: this.$store.dispatch('cluster/findAll', { type: STORAGE_CLASS }),
|
||||||
|
persistentVolumes: this.$store.dispatch('cluster/findAll', { type: PV }),
|
||||||
|
secrets: this.$store.dispatch('cluster/findAll', { type: SECRET }),
|
||||||
|
});
|
||||||
|
|
||||||
|
this.secrets = hash.secrets;
|
||||||
|
this.storageClasses = hash.storageClasses;
|
||||||
|
this.persistentVolumes = hash.persistentVolumes;
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
const storageSource = this.mode === 'create' ? 's3' : this.getStorageSource(this.value);
|
||||||
|
|
||||||
|
return {
|
||||||
|
storageSource, secrets: [], storageClasses: [], persistentVolumes: []
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
defaultStorageClass() {
|
||||||
|
return this.storageClasses.filter(sc => sc.metadata.annotations[STORAGE.DEFAULT_STORAGE_CLASS])[0];
|
||||||
|
},
|
||||||
|
|
||||||
|
storageClassNames() {
|
||||||
|
return this.storageClasses.reduce((total, each) => {
|
||||||
|
total.push(each.id);
|
||||||
|
|
||||||
|
return total;
|
||||||
|
}, []);
|
||||||
|
},
|
||||||
|
|
||||||
|
unboundPVs() {
|
||||||
|
return this.persistentVolumes.reduce((total, each) => {
|
||||||
|
if (each?.status?.phase !== 'bound') {
|
||||||
|
total.push(each.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return total;
|
||||||
|
}, []);
|
||||||
|
},
|
||||||
|
|
||||||
|
radioOptions() {
|
||||||
|
const options = ['s3', 'pickSC', 'pickPV'];
|
||||||
|
const labels = [
|
||||||
|
this.t('backupRestoreOperator.deployment.storage.options.s3'),
|
||||||
|
this.t('backupRestoreOperator.deployment.storage.options.pickSC'),
|
||||||
|
this.t('backupRestoreOperator.deployment.storage.options.pickPV'),
|
||||||
|
];
|
||||||
|
|
||||||
|
if (this.defaultStorageClass) {
|
||||||
|
options.splice(1, 0, 'defaultSC');
|
||||||
|
labels.splice(1, 0, this.t('backupRestoreOperator.deployment.storage.options.defaultStorageClass', { name: this.defaultStorageClass.name }));
|
||||||
|
}
|
||||||
|
|
||||||
|
return { options, labels };
|
||||||
|
},
|
||||||
|
|
||||||
|
...mapGetters({ t: 'i18n/t' })
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
storageSource(neu) {
|
||||||
|
switch (neu) {
|
||||||
|
case 'defaultSC':
|
||||||
|
this.value.persistence.enabled = true;
|
||||||
|
this.value.s3.enabled = false;
|
||||||
|
this.value.persistence.storageClass = this.defaultStorageClass.id;
|
||||||
|
break;
|
||||||
|
case 'pickSC':
|
||||||
|
this.value.persistence.enabled = true;
|
||||||
|
delete this.value.persistence.volumeName;
|
||||||
|
this.value.s3.enabled = false;
|
||||||
|
break;
|
||||||
|
case 'pickPV':
|
||||||
|
this.value.persistence.enabled = true;
|
||||||
|
this.value.persistence.storageClass = '-';
|
||||||
|
this.value.s3.enabled = false;
|
||||||
|
break;
|
||||||
|
case 's3':
|
||||||
|
this.value.persistence.enabled = false;
|
||||||
|
this.value.s3.enabled = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
getStorageSource() {
|
||||||
|
if (get(this.value, 's3.enabled')) {
|
||||||
|
return 's3';
|
||||||
|
} if (get(this.value, 'persistence.enabled')) {
|
||||||
|
if (this.value.persistence.storageClass) {
|
||||||
|
if (this.value.persistence.storageClass === this.defaultSC.metadata.name) {
|
||||||
|
return 'defaultSC';
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'pickSC';
|
||||||
|
}
|
||||||
|
if (this.value.persistence.volumeName) {
|
||||||
|
return 'pickPV';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<Tab label="Chart Options" name="chartOptions">
|
||||||
|
<Banner color="info" :label="t('backupRestoreOperator.deployment.storage.tip')" />
|
||||||
|
<RadioGroup
|
||||||
|
v-model="storageSource"
|
||||||
|
name="storageSource"
|
||||||
|
:label="t('backupRestoreOperator.deployment.storage.label')"
|
||||||
|
class="mb-10"
|
||||||
|
:options="radioOptions.options"
|
||||||
|
:labels="radioOptions.labels"
|
||||||
|
/>
|
||||||
|
<S3 v-if="storageSource==='s3'" :value="value.s3" :secrets="secrets" :mode="mode" />
|
||||||
|
<template v-else>
|
||||||
|
<div class="row">
|
||||||
|
<div v-if="storageSource === 'pickSC'" class="col span-6">
|
||||||
|
<LabeledSelect
|
||||||
|
:key="storageSource"
|
||||||
|
v-model="value.persistence.storageClass"
|
||||||
|
:label="t('backupRestoreOperator.deployment.storage.storageClass')"
|
||||||
|
:mode="mode"
|
||||||
|
:options="storageClassNames"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div v-else-if="storageSource === 'pickPV'" class="col span-6">
|
||||||
|
<LabeledSelect
|
||||||
|
:key="storageSource"
|
||||||
|
:value="value.persistence.volumeName"
|
||||||
|
:label="t('backupRestoreOperator.deployment.storage.persistentVolume')"
|
||||||
|
:mode="mode"
|
||||||
|
:options="unboundPVs"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="col span-6">
|
||||||
|
<LabeledInput v-model="value.persistence.size" :mode="mode" :label="t('backupRestoreOperator.deployment.size')" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</Tab>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang='scss' scoped>
|
||||||
|
::v-deep .radio-group.label>SPAN {
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -103,7 +103,7 @@ export default {
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div v-if="label" class="radio-group label" :class="{'view':isView}">
|
<div v-if="label" class="radio-group label">
|
||||||
<span class="text-label">
|
<span class="text-label">
|
||||||
{{ label }}
|
{{ label }}
|
||||||
</span>
|
</span>
|
||||||
|
|
@ -154,7 +154,7 @@ export default {
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.radio-group.label.view{
|
.radio-group.label{
|
||||||
color: var(--input-label);
|
font-size: 1.2em;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,8 @@ export const RIO = { STACK: 'rio.cattle.io/stack' };
|
||||||
|
|
||||||
export const CERTMANAGER = { ISSUER: 'cert-manager.io/issuer-name' };
|
export const CERTMANAGER = { ISSUER: 'cert-manager.io/issuer-name' };
|
||||||
|
|
||||||
|
export const STORAGE = { DEFAULT_STORAGE_CLASS: 'storageclass.kubernetes.io/is-default-class' };
|
||||||
|
|
||||||
export const NODE_ROLES = {
|
export const NODE_ROLES = {
|
||||||
CONTROL_PLANE: 'node-role.kubernetes.io/controlplane',
|
CONTROL_PLANE: 'node-role.kubernetes.io/controlplane',
|
||||||
WORKER: 'node-role.kubernetes.io/worker',
|
WORKER: 'node-role.kubernetes.io/worker',
|
||||||
|
|
|
||||||
|
|
@ -3,13 +3,13 @@ import CruResource from '@/components/CruResource';
|
||||||
import createEditView from '@/mixins/create-edit-view';
|
import createEditView from '@/mixins/create-edit-view';
|
||||||
import LabeledInput from '@/components/form/LabeledInput';
|
import LabeledInput from '@/components/form/LabeledInput';
|
||||||
import UnitInput from '@/components/form/UnitInput';
|
import UnitInput from '@/components/form/UnitInput';
|
||||||
import Checkbox from '@/components/form/Checkbox';
|
|
||||||
import FileSelector from '@/components/form/FileSelector';
|
|
||||||
import LabeledSelect from '@/components/form/LabeledSelect';
|
import LabeledSelect from '@/components/form/LabeledSelect';
|
||||||
import Banner from '@/components/Banner';
|
import Banner from '@/components/Banner';
|
||||||
import RadioGroup from '@/components/form/RadioGroup';
|
import RadioGroup from '@/components/form/RadioGroup';
|
||||||
import NameNsDescription from '@/components/form/NameNsDescription';
|
import NameNsDescription from '@/components/form/NameNsDescription';
|
||||||
import Loading from '@/components/Loading';
|
import Loading from '@/components/Loading';
|
||||||
|
import S3 from '@/chart/backup-restore-operator/S3';
|
||||||
|
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
import { SECRET, BACKUP_RESTORE, CATALOG } from '@/config/types';
|
import { SECRET, BACKUP_RESTORE, CATALOG } from '@/config/types';
|
||||||
import { allHash } from '@/utils/promise';
|
import { allHash } from '@/utils/promise';
|
||||||
|
|
@ -22,13 +22,12 @@ export default {
|
||||||
CruResource,
|
CruResource,
|
||||||
UnitInput,
|
UnitInput,
|
||||||
LabeledInput,
|
LabeledInput,
|
||||||
Checkbox,
|
|
||||||
FileSelector,
|
|
||||||
LabeledSelect,
|
LabeledSelect,
|
||||||
RadioGroup,
|
RadioGroup,
|
||||||
NameNsDescription,
|
NameNsDescription,
|
||||||
Banner,
|
Banner,
|
||||||
Loading
|
Loading,
|
||||||
|
S3
|
||||||
},
|
},
|
||||||
mixins: [createEditView],
|
mixins: [createEditView],
|
||||||
|
|
||||||
|
|
@ -77,20 +76,6 @@ export default {
|
||||||
return BRORelease ? BRORelease.spec.namespace : '';
|
return BRORelease ? BRORelease.spec.namespace : '';
|
||||||
},
|
},
|
||||||
|
|
||||||
credentialSecret: {
|
|
||||||
get() {
|
|
||||||
const { credentialSecretName, credentialSecretNamespace } = this.s3;
|
|
||||||
|
|
||||||
return { metadata: { name: credentialSecretName, namespace: credentialSecretNamespace } };
|
|
||||||
},
|
|
||||||
set(neu) {
|
|
||||||
const { name, namespace } = neu.metadata;
|
|
||||||
|
|
||||||
this.$set(this.s3, 'credentialSecretName', name);
|
|
||||||
this.$set(this.s3, 'credentialSecretNamespace', namespace);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
encryptionSecretNames() {
|
encryptionSecretNames() {
|
||||||
return this.allSecrets.filter(secret => !!secret.data['encryption-provider-config.yaml'] && secret.metadata.namespace === this.chartNamespace).map(secret => secret.metadata.name);
|
return this.allSecrets.filter(secret => !!secret.data['encryption-provider-config.yaml'] && secret.metadata.namespace === this.chartNamespace).map(secret => secret.metadata.name);
|
||||||
},
|
},
|
||||||
|
|
@ -137,7 +122,7 @@ export default {
|
||||||
if (neu === 'useDefault') {
|
if (neu === 'useDefault') {
|
||||||
delete this.value.spec.storageLocation;
|
delete this.value.spec.storageLocation;
|
||||||
} else {
|
} else {
|
||||||
this.$set(this.value.spec, 'storageLocation', this.s3);
|
this.$set(this.value.spec, 'storageLocation', { s3: this.s3 });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -224,32 +209,7 @@ export default {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<template v-if="storageSource !== 'useDefault'">
|
<template v-if="storageSource !== 'useDefault'">
|
||||||
<div class="row mb-10">
|
<S3 :value="s3" :secrets="allSecrets" :mode="mode" />
|
||||||
<div class="col span-6">
|
|
||||||
<LabeledSelect v-model="credentialSecret" :get-option-label="opt=>opt.metadata.name || ''" :mode="mode" :options="allSecrets" :label="t('backupRestoreOperator.s3.credentialSecretName')" />
|
|
||||||
</div>
|
|
||||||
<div class="col span-6">
|
|
||||||
<LabeledInput v-model="s3.bucketName" :mode="mode" :label="t('backupRestoreOperator.s3.bucketName')" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-10">
|
|
||||||
<div class="col span-6">
|
|
||||||
<LabeledInput v-model="s3.region" :mode="mode" :label="t('backupRestoreOperator.s3.region')" />
|
|
||||||
</div>
|
|
||||||
<div class="col span-6">
|
|
||||||
<LabeledInput v-model="s3.folder" :mode="mode" :label="t('backupRestoreOperator.s3.folder')" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-10">
|
|
||||||
<div class="col span-6">
|
|
||||||
<LabeledInput v-model="s3.endpoint" :mode="mode" :label="t('backupRestoreOperator.s3.endpoint')" />
|
|
||||||
<Checkbox v-model="s3.insecureTLSSkipVerify" class="mt-10" :mode="mode" :label="t('backupRestoreOperator.s3.insecureTLSSkipVerify')" />
|
|
||||||
</div>
|
|
||||||
<div class="col span-6">
|
|
||||||
<LabeledInput v-model="s3.endpointCA" :mode="mode" type="multiline" :label="t('backupRestoreOperator.s3.endpointCA')" />
|
|
||||||
<FileSelector v-if="mode!=='view'" class="btn btn-sm role-primary mt-5" :mode="mode" :label="t('generic.readFromFile')" @selected="e=>$set(s3, 'endpointCA', e)" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
<Banner v-else color="error">
|
<Banner v-else color="error">
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,10 @@ import createEditView from '@/mixins/create-edit-view';
|
||||||
import LabeledInput from '@/components/form/LabeledInput';
|
import LabeledInput from '@/components/form/LabeledInput';
|
||||||
import UnitInput from '@/components/form/UnitInput';
|
import UnitInput from '@/components/form/UnitInput';
|
||||||
import Checkbox from '@/components/form/Checkbox';
|
import Checkbox from '@/components/form/Checkbox';
|
||||||
import FileSelector from '@/components/form/FileSelector';
|
|
||||||
import LabeledSelect from '@/components/form/LabeledSelect';
|
import LabeledSelect from '@/components/form/LabeledSelect';
|
||||||
import Loading from '@/components/Loading';
|
import Loading from '@/components/Loading';
|
||||||
import RadioGroup from '@/components/form/RadioGroup';
|
import RadioGroup from '@/components/form/RadioGroup';
|
||||||
|
import S3 from '@/chart/backup-restore-operator/S3';
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
import { SECRET, BACKUP_RESTORE, CATALOG } from '@/config/types';
|
import { SECRET, BACKUP_RESTORE, CATALOG } from '@/config/types';
|
||||||
import { allHash } from '@/utils/promise';
|
import { allHash } from '@/utils/promise';
|
||||||
|
|
@ -19,7 +19,7 @@ export default {
|
||||||
UnitInput,
|
UnitInput,
|
||||||
LabeledInput,
|
LabeledInput,
|
||||||
Checkbox,
|
Checkbox,
|
||||||
FileSelector,
|
S3,
|
||||||
LabeledSelect,
|
LabeledSelect,
|
||||||
Loading,
|
Loading,
|
||||||
RadioGroup
|
RadioGroup
|
||||||
|
|
@ -79,21 +79,6 @@ export default {
|
||||||
return BRORelease ? BRORelease.spec.namespace : '';
|
return BRORelease ? BRORelease.spec.namespace : '';
|
||||||
},
|
},
|
||||||
|
|
||||||
credentialSecret: {
|
|
||||||
get() {
|
|
||||||
const { credentialSecretName, credentialSecretNamespace } = this.s3;
|
|
||||||
|
|
||||||
return { metadata: { name: credentialSecretName, namespace: credentialSecretNamespace } };
|
|
||||||
},
|
|
||||||
|
|
||||||
set(neu) {
|
|
||||||
const { name, namespace } = neu.metadata;
|
|
||||||
|
|
||||||
this.$set(this.s3, 'credentialSecretName', name);
|
|
||||||
this.$set(this.s3, 'credentialSecretNamespace', namespace);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
encryptionSecretNames() {
|
encryptionSecretNames() {
|
||||||
return this.allSecrets.filter(secret => !!secret.data['encryption-provider-config.yaml'] && secret.metadata.namespace === this.chartNamespace).map(secret => secret.metadata.name);
|
return this.allSecrets.filter(secret => !!secret.data['encryption-provider-config.yaml'] && secret.metadata.namespace === this.chartNamespace).map(secret => secret.metadata.name);
|
||||||
},
|
},
|
||||||
|
|
@ -177,38 +162,7 @@ export default {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<template v-if="storageSource === 'configureS3'">
|
<template v-if="storageSource === 'configureS3'">
|
||||||
<div class="row mb-10">
|
<S3 v-model="s3" :mode="mode" :secrets="allSecrets" />
|
||||||
<div class="col span-6">
|
|
||||||
<LabeledSelect
|
|
||||||
v-model="credentialSecret"
|
|
||||||
:get-option-label="opt=>opt.metadata.name || ''"
|
|
||||||
:mode="mode"
|
|
||||||
:options="allSecrets"
|
|
||||||
:label="t('backupRestoreOperator.s3.credentialSecretName')"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="col span-6">
|
|
||||||
<LabeledInput v-model="s3.bucketName" :mode="mode" :label="t('backupRestoreOperator.s3.bucketName')" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-10">
|
|
||||||
<div class="col span-6">
|
|
||||||
<LabeledInput v-model="s3.region" :mode="mode" :label="t('backupRestoreOperator.s3.region')" />
|
|
||||||
</div>
|
|
||||||
<div class="col span-6">
|
|
||||||
<LabeledInput v-model="s3.folder" :mode="mode" :label="t('backupRestoreOperator.s3.folder')" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-10">
|
|
||||||
<div class="col span-6">
|
|
||||||
<LabeledInput v-model="s3.endpoint" :mode="mode" :label="t('backupRestoreOperator.s3.endpoint')" />
|
|
||||||
<Checkbox v-model="s3.insecureTLSSkipVerify" class="mt-10" :mode="mode" :label="t('backupRestoreOperator.s3.insecureTLSSkipVerify')" />
|
|
||||||
</div>
|
|
||||||
<div class="col span-6">
|
|
||||||
<LabeledInput v-model="s3.endpointCA" :mode="mode" type="multiline" :label="t('backupRestoreOperator.s3.endpointCA')" />
|
|
||||||
<FileSelector v-if="mode!=='view'" class="btn btn-sm role-primary mt-5" :mode="mode" :label="t('generic.readFromFile')" @selected="e=>$set(s3, 'endpointCA', e)" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
<div v-else-if="storageSource==='useBackup'" class="row mb-10">
|
<div v-else-if="storageSource==='useBackup'" class="row mb-10">
|
||||||
<div class="col span-6">
|
<div class="col span-6">
|
||||||
|
|
|
||||||
|
|
@ -507,7 +507,6 @@ export default {
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const res = await this.repo.doAction((isUpgrade ? 'upgrade' : 'install'), input);
|
const res = await this.repo.doAction((isUpgrade ? 'upgrade' : 'install'), input);
|
||||||
|
|
||||||
this.operation = await this.$store.dispatch('cluster/find', {
|
this.operation = await this.$store.dispatch('cluster/find', {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue