dashboard/edit/persistentvolumeclaim.vue

235 lines
7.8 KiB
Vue

<script>
import Checkbox from '@/components/form/Checkbox';
import CreateEditView from '@/mixins/create-edit-view';
import CruResource from '@/components/CruResource';
import NameNsDescription from '@/components/form/NameNsDescription';
import Tab from '@/components/Tabbed/Tab';
import RadioGroup from '@/components/form/RadioGroup';
import LabeledSelect from '@/components/form/LabeledSelect';
import UnitInput from '@/components/form/UnitInput';
import uniq from 'lodash/uniq';
import { _CREATE } from '@/config/query-params';
import { STORAGE_CLASS, PV } from '@/config/types';
import StatusTable from '@/components/StatusTable';
import ResourceTabs from '@/components/form/ResourceTabs';
const DEFAULT_STORAGE = '10Gi';
export default {
name: 'PersistentVolumClaim',
components: {
Checkbox,
CruResource,
LabeledSelect,
NameNsDescription,
RadioGroup,
ResourceTabs,
StatusTable,
Tab,
UnitInput,
},
mixins: [CreateEditView],
async fetch() {
const storageClasses = await this.$store.dispatch('cluster/findAll', { type: STORAGE_CLASS });
this.persistentVolumes = await this.$store.dispatch('cluster/findAll', { type: PV });
this.storageClassOptions = storageClasses.map(s => s.name).sort();
this.persistentVolumeOptions = this.persistentVolumes
.map((s) => {
const status = s.status.phase === 'Available' ? '' : ` (${ s.status.phase })`;
return {
label: `${ s.name }${ status }`,
value: s.name
};
})
.sort((l, r) => l.label.localeCompare(r.label));
this.$set(this.value.spec, 'storageClassName', this.value.spec.storageClassName || this.storageClassOptions[0]);
},
data() {
const sourceOptions = [
{
label: this.t('persistentVolumeClaim.source.options.new'),
value: 'new'
},
{
label: this.t('persistentVolumeClaim.source.options.existing'),
value: 'existing'
}
];
const defaultAccessModes = ['ReadWriteOnce'];
this.$set(this.value, 'spec', this.value.spec || {});
this.$set(this.value.spec, 'resources', this.value.spec.resources || {});
this.$set(this.value.spec.resources, 'requests', this.value.spec.resources.requests || {});
this.$set(this.value.spec.resources.requests, 'storage', this.value.spec.resources.requests.storage || DEFAULT_STORAGE);
if (this.realMode === _CREATE) {
this.$set(this.value.spec, 'accessModes', defaultAccessModes);
}
return {
sourceOptions,
source: this.value.spec.volumeName ? sourceOptions[1].value : sourceOptions[0].value,
persistentVolumeOptions: [],
persistentVolumes: [],
storageClassOptions: [],
};
},
computed: {
readWriteOnce: {
get() {
return this.value.spec.accessModes.includes('ReadWriteOnce');
},
set(value) {
this.checkboxSetter('ReadWriteOnce', value);
}
},
readOnlyMany: {
get() {
return this.value.spec.accessModes.includes('ReadOnlyMany');
},
set(value) {
this.checkboxSetter('ReadOnlyMany', value);
}
},
readWriteMany: {
get() {
return this.value.spec.accessModes.includes('ReadWriteMany');
},
set(value) {
this.checkboxSetter('ReadWriteMany', value);
}
},
capacity: {
get() {
return this.value.spec.resources.requests.storage;
},
set(value) {
this.$set(this.value.spec.resources.requests, 'storage', `${ value }Gi`);
}
},
persistentVolume: {
get() {
return this.value.spec.volumeName;
},
set(value) {
const persistentVolume = this.persistentVolumes.find(pv => pv.name === value);
if (persistentVolume) {
this.$set(this.value.spec.resources.requests, 'storage', persistentVolume.spec.capacity?.storage);
}
this.$set(this.value.spec, 'volumeName', value);
this.$set(this.value.spec, 'storageClassName', '');
}
}
},
methods: {
checkboxSetter(key, value) {
if (value) {
this.value.spec.accessModes.push(key);
this.$set(this.value, 'accessModes', uniq(this.value.spec.accessModes));
} else {
const indexOf = this.value.spec.accessModes.indexOf(key);
if (indexOf >= 0) {
this.value.spec.accessModes.splice(indexOf, 1);
}
}
},
isPersistentVolumeSelectable(option) {
const persistentVolume = this.persistentVolumes.find(pv => pv.name === option.value);
return persistentVolume.status.phase === 'Available';
},
updateDefaults(source) {
if (source === 'new') {
this.$set(this.value.spec.resources.requests, 'storage', DEFAULT_STORAGE);
}
this.$set(this, 'persistentVolume', null);
},
}
};
</script>
<template>
<CruResource
:done-route="doneRoute"
:mode="mode"
:resource="value"
:subtypes="[]"
:validation-passed="true"
:errors="errors"
@error="e=>errors = e"
@finish="save"
@cancel="done"
>
<NameNsDescription
:value="value"
:mode="mode"
:register-before-hook="registerBeforeHook"
:namespaced="true"
/>
<ResourceTabs v-model="value" :mode="mode" :side-tabs="true">
<Tab name="volumeclaim" :label="t('persistentVolumeClaim.volumeClaim.label')" :weight="4">
<div class="row">
<div class="col span-6">
<RadioGroup
v-model="source"
name="source"
:mode="mode"
:label="t('persistentVolumeClaim.source.label')"
:options="sourceOptions"
@input="updateDefaults"
/>
</div>
<div v-if="source === 'new'" class="col span-6">
<div class="row">
<div class="col span-12">
<LabeledSelect v-model="value.spec.storageClassName" :options="storageClassOptions" :label="t('persistentVolumeClaim.volumeClaim.storageClass')" :mode="mode" />
</div>
</div>
<div class="row">
<div class="col span-12 mt-10">
<UnitInput
v-model="capacity"
:label="t('persistentVolumeClaim.volumeClaim.requestStorage')"
:suffix="'GiB'"
:mode="mode"
/>
</div>
</div>
</div>
<div v-else class="col span-6">
<div class="row">
<div class="col span-12">
<LabeledSelect
v-model="persistentVolume"
:options="persistentVolumeOptions"
:label="t('persistentVolumeClaim.volumeClaim.persistentVolume')"
:selectable="isPersistentVolumeSelectable"
:mode="mode"
/>
</div>
</div>
</div>
</div>
</Tab>
<Tab name="customize" :label="t('persistentVolumeClaim.customize.label')" :weight="3">
<h3>Access Modes</h3>
<div><Checkbox v-model="readWriteOnce" :label="t('persistentVolumeClaim.customize.accessModes.readWriteOnce')" :mode="mode" /></div>
<div><Checkbox v-model="readOnlyMany" :label="t('persistentVolumeClaim.customize.accessModes.readOnlyMany')" :mode="mode" /></div>
<div><Checkbox v-model="readWriteMany" :label="t('persistentVolumeClaim.customize.accessModes.readWriteMany')" :mode="mode" /></div>
</Tab>
<Tab v-if="isView" name="status" :label="t('persistentVolumeClaim.status.label')" :weight="2">
<StatusTable :resource="value" />
</Tab>
</ResourceTabs>
</CruResource>
</template>