mirror of
https://github.com/portainer/portainer.git
synced 2025-08-05 05:45:22 +02:00
refactor(app): persisted folders form section [EE-6235] (#10693)
* refactor(app): persisted folder section [EE-6235]
This commit is contained in:
parent
7a2412b1be
commit
e07ee05ee7
39 changed files with 732 additions and 374 deletions
|
@ -410,250 +410,25 @@
|
|||
></secrets-form-section>
|
||||
<!-- #endregion -->
|
||||
|
||||
<!-- #region PERSISTED FOLDERS -->
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12 vertical-center mb-2 pt-2.5" style="margin-top: 5px">
|
||||
<label class="control-label !pt-0 text-left !text-sm">Persisted folders</label>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-12 small text-muted vertical-center mt-1" ng-if="!ctrl.storageClassAvailable()">
|
||||
<pr-icon icon="'info'" mode="'primary'"></pr-icon>
|
||||
No storage option is available to persist data, contact your administrator to enable a storage option.
|
||||
</div>
|
||||
|
||||
<div class="row" ng-if="ctrl.storageClassAvailable()">
|
||||
<div class="col-sm-12" style="margin-top: 5px" ng-if="ctrl.allQuotasExhaustedAndNoVolumesAvailable()">
|
||||
<span class="small text-muted vertical-center">
|
||||
<pr-icon icon="'alert-circle'" mode="'warning'"></pr-icon>
|
||||
This namespace has exhausted its storage capacity. Contact your administrator to expand the capacity of the namespace.
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-12 form-inline" style="margin-top: 10px" ng-repeat="persistedFolder in ctrl.formValues.PersistedFolders">
|
||||
<div style="margin-top: 2px">
|
||||
<div class="input-group col-sm-3 input-group-sm" ng-class="{ striked: persistedFolder.NeedsDeletion }">
|
||||
<span class="input-group-addon required">path in container</span>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
name="persisted_folder_path_{{ $index }}"
|
||||
ng-model="persistedFolder.ContainerPath"
|
||||
ng-change="ctrl.onChangePersistedFolderPath()"
|
||||
ng-disabled="ctrl.isEditAndExistingPersistedFolder($index) || ctrl.formValues.Containers.length > 1"
|
||||
placeholder="/data"
|
||||
required
|
||||
data-cy="k8sAppCreate-containerPathInput_{{ $index }}"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="input-group col-sm-2 input-group-sm"
|
||||
ng-if="
|
||||
!ctrl.isEditAndExistingPersistedFolder($index) &&
|
||||
ctrl.application.ApplicationType !== ctrl.ApplicationTypes.STATEFULSET &&
|
||||
ctrl.formValues.Containers.length <= 1
|
||||
"
|
||||
>
|
||||
<span class="btn-group btn-group-sm" ng-class="{ striked: persistedFolder.NeedsDeletion }">
|
||||
<label
|
||||
class="btn btn-light"
|
||||
ng-model="persistedFolder.UseNewVolume"
|
||||
uib-btn-radio="true"
|
||||
ng-change="ctrl.useNewVolume($index)"
|
||||
ng-disabled="ctrl.isNewVolumeButtonDisabled($index)"
|
||||
>New volume</label
|
||||
>
|
||||
<label
|
||||
class="btn btn-light"
|
||||
ng-model="persistedFolder.UseNewVolume"
|
||||
uib-btn-radio="false"
|
||||
ng-change="ctrl.useExistingVolume($index)"
|
||||
ng-disabled="ctrl.isExistingVolumeButtonDisabled()"
|
||||
>Existing volume</label
|
||||
>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="input-group col-sm-3 input-group-sm" ng-class="{ striked: persistedFolder.NeedsDeletion }" ng-if="persistedFolder.UseNewVolume">
|
||||
<span class="input-group-addon required">requested size</span>
|
||||
<input
|
||||
type="number"
|
||||
class="form-control !rounded-none"
|
||||
name="persisted_folder_size_{{ $index }}"
|
||||
ng-model="persistedFolder.Size"
|
||||
placeholder="20"
|
||||
min="0"
|
||||
required
|
||||
ng-disabled="ctrl.isEditAndExistingPersistedFolder($index) || ctrl.formValues.Containers.length > 1"
|
||||
ng-change="ctrl.onChangeVolumeRequestedSize()"
|
||||
/>
|
||||
<span class="input-group-addon !rounded-r-[5px] !p-0">
|
||||
<select
|
||||
class="form-control !h-[28px] w-12 !rounded-r-[5px] !border-none text-xs"
|
||||
ng-model="persistedFolder.SizeUnit"
|
||||
ng-style="{ height: '100%', cursor: ctrl.isEditAndExistingPersistedFolder($index) ? 'not-allowed' : 'auto' }"
|
||||
ng-options="unit for unit in ctrl.state.availableSizeUnits"
|
||||
ng-disabled="ctrl.isEditAndExistingPersistedFolder($index) || ctrl.formValues.Containers.length > 1"
|
||||
ng-change="ctrl.onChangeVolumeRequestedSize()"
|
||||
></select>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="input-group col-sm-2 input-group-sm" ng-class="{ striked: persistedFolder.NeedsDeletion }" ng-if="persistedFolder.UseNewVolume">
|
||||
<span class="input-group-addon">storage</span>
|
||||
<select
|
||||
ng-if="ctrl.hasMultipleStorageClassesAvailable()"
|
||||
class="form-control"
|
||||
ng-model="persistedFolder.StorageClass"
|
||||
ng-options="storageClass as storageClass.Name for storageClass in ctrl.storageClasses"
|
||||
ng-disabled="ctrl.state.isEdit || ctrl.formValues.Containers.length > 1"
|
||||
data-cy="k8sAppCreate-storageSelect_{{ $index }}"
|
||||
></select>
|
||||
<input
|
||||
ng-if="!ctrl.hasMultipleStorageClassesAvailable()"
|
||||
type="text"
|
||||
class="form-control"
|
||||
disabled
|
||||
ng-model="persistedFolder.StorageClass.Name"
|
||||
data-cy="k8sAppCreate-storageClassNameInput_{{ $index }}"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="input-group col-sm-5 input-group-sm" ng-if="!persistedFolder.UseNewVolume" ng-class="{ striked: persistedFolder.NeedsDeletion }">
|
||||
<span class="input-group-addon">volume</span>
|
||||
<select
|
||||
class="form-control"
|
||||
name="existing_volumes_{{ $index }}"
|
||||
ng-model="ctrl.formValues.PersistedFolders[$index].ExistingVolume"
|
||||
ng-options="vol as vol.PersistentVolumeClaim.Name for vol in ctrl.availableVolumes"
|
||||
ng-change="ctrl.onChangeExistingVolumeSelection()"
|
||||
ng-disabled="ctrl.isEditAndExistingPersistedFolder($index) || ctrl.formValues.Containers.length > 1"
|
||||
required
|
||||
>
|
||||
<option selected disabled hidden value="">Select a volume</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="input-group col-sm-1 input-group-sm">
|
||||
<div ng-if="!ctrl.isEditAndStatefulSet() && !ctrl.state.useExistingVolume[$index] && ctrl.formValues.Containers.length <= 1">
|
||||
<button
|
||||
ng-if="!persistedFolder.NeedsDeletion"
|
||||
class="btn btn-sm btn-dangerlight !ml-0 h-[30px]"
|
||||
type="button"
|
||||
ng-click="ctrl.removePersistedFolder($index)"
|
||||
data-cy="k8sAppCreate-rmPersistentFolderButton"
|
||||
>
|
||||
<pr-icon icon="'trash-2'" size="'md'"></pr-icon>
|
||||
</button>
|
||||
<button
|
||||
ng-if="persistedFolder.NeedsDeletion"
|
||||
class="btn btn-sm btn-primary"
|
||||
type="button"
|
||||
ng-click="ctrl.restorePersistedFolder($index)"
|
||||
data-cy="k8sAppCreate-restorePersistentButton"
|
||||
>
|
||||
<pr-icon icon="'rotate-cw'"></pr-icon>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="flex flex-row gap-x-1"
|
||||
ng-show="
|
||||
kubernetesApplicationCreationForm['persisted_folder_path_' + $index].$invalid ||
|
||||
ctrl.state.duplicates.persistedFolders.refs[$index] !== undefined ||
|
||||
kubernetesApplicationCreationForm['persisted_folder_size_' + $index].$invalid ||
|
||||
ctrl.state.exceeded.persistedFolders.refs[$index] !== undefined ||
|
||||
kubernetesApplicationCreationForm['existing_volumes_' + $index].$invalid ||
|
||||
ctrl.state.duplicates.existingVolumes.refs[$index] !== undefined
|
||||
"
|
||||
>
|
||||
<div class="input-group col-sm-3 input-group-sm">
|
||||
<div
|
||||
class="small text-warning"
|
||||
style="margin-top: 5px"
|
||||
ng-show="
|
||||
kubernetesApplicationCreationForm['persisted_folder_path_' + $index].$invalid || ctrl.state.duplicates.persistedFolders.refs[$index] !== undefined
|
||||
"
|
||||
>
|
||||
<ng-messages for="kubernetesApplicationCreationForm['persisted_folder_path_' + $index].$error">
|
||||
<p class="vertical-center" ng-message="required"><pr-icon icon="'alert-triangle'" mode="'warning'"></pr-icon> Path is required.</p>
|
||||
</ng-messages>
|
||||
<p class="vertical-center" ng-if="ctrl.state.duplicates.persistedFolders.refs[$index] !== undefined"
|
||||
><pr-icon icon="'alert-triangle'" mode="'warning'"></pr-icon> This path is already defined.</p
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="input-group col-sm-offset-3 col-sm-3 input-group-sm">
|
||||
<div
|
||||
class="small text-warning"
|
||||
style="margin-top: 5px"
|
||||
ng-show="
|
||||
kubernetesApplicationCreationForm['persisted_folder_size_' + $index].$invalid || ctrl.state.exceeded.persistedFolders.refs[$index] !== undefined
|
||||
"
|
||||
>
|
||||
<ng-messages for="kubernetesApplicationCreationForm['persisted_folder_size_' + $index].$error">
|
||||
<p class="vertical-center" ng-message="required"><pr-icon icon="'alert-triangle'" mode="'warning'"></pr-icon> Size is required.</p>
|
||||
<p class="vertical-center" ng-message="min"><pr-icon icon="'alert-triangle'" mode="'warning'"></pr-icon> This value must be greater than zero.</p>
|
||||
</ng-messages>
|
||||
<p class="vertical-center" ng-if="ctrl.state.exceeded.persistedFolders.refs[$index] !== undefined">
|
||||
<pr-icon icon="'alert-triangle'" mode="'warning'"></pr-icon>
|
||||
You can only request up to
|
||||
{{ ctrl.state.storages.availabilities[persistedFolder.StorageClass.Name] | kubernetesAppStorageRequestSizeHumanReadable }} for
|
||||
{{ persistedFolder.StorageClass.Name }}
|
||||
</p>
|
||||
</div>
|
||||
<div
|
||||
class="small text-warning"
|
||||
ng-show="kubernetesApplicationCreationForm['existing_volumes_' + $index].$invalid || ctrl.state.duplicates.existingVolumes.refs[$index] !== undefined"
|
||||
>
|
||||
<ng-messages for="kubernetesApplicationCreationForm['existing_volumes_' + $index].$error">
|
||||
<p ng-message="required"><pr-icon icon="'alert-triangle'" mode="'warning'"></pr-icon> Volume is required.</p>
|
||||
</ng-messages>
|
||||
<p ng-if="ctrl.state.duplicates.existingVolumes.refs[$index] !== undefined"
|
||||
><pr-icon icon="'alert-triangle'" mode="'warning'"></pr-icon> This volume is already used.</p
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="input-group col-sm-1 input-group-sm"> </div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-12 mt-2">
|
||||
<span
|
||||
class="btn btn-primary btn-sm btn btn-sm btn-light mb-2 !ml-0"
|
||||
ng-click="ctrl.addPersistedFolder()"
|
||||
ng-if="ctrl.isAddPersistentFolderButtonShowed()"
|
||||
data-cy="k8sAppCreate-addPersistentFolderButton"
|
||||
>
|
||||
<pr-icon icon="'plus'" size="'sm'"></pr-icon> Add persisted folder
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- #endregion -->
|
||||
<persisted-folders-form-section
|
||||
values="ctrl.formValues.PersistedFolders"
|
||||
initial-values="ctrl.formValues.OriginalPersistedFolders"
|
||||
on-change="(ctrl.onChangePersistedFolder)"
|
||||
is-edit="ctrl.state.isEdit"
|
||||
application-values="ctrl.formValues"
|
||||
is-add-persistent-folder-button-shown="ctrl.isAddPersistentFolderButtonShown()"
|
||||
available-volumes="ctrl.availableVolumes"
|
||||
validation-data="{ namespaceQuotas: ctrl.formValues.ResourcePool.Quota, persistedFolders: ctrl.formValues.PersistedFolders, storageAvailabilities: ctrl.state.storages.availabilities }"
|
||||
></persisted-folders-form-section>
|
||||
|
||||
<!-- #region DATA ACCESS POLICY -->
|
||||
<div ng-if="ctrl.showDataAccessPolicySection()">
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<label class="control-label text-left">Data access policy</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12 small text-muted"> Specify how the data will be used across instances. </div>
|
||||
</div>
|
||||
|
||||
<kube-application-access-policy-selector
|
||||
<data-access-policy-form-section
|
||||
value="ctrl.formValues.DataAccessPolicy"
|
||||
on-change="(ctrl.onDataAccessPolicyChange)"
|
||||
is-edit="ctrl.state.isEdit"
|
||||
persisted-folders-use-existing-volumes="ctrl.state.persistedFoldersUseExistingVolumes"
|
||||
></kube-application-access-policy-selector>
|
||||
></data-access-policy-form-section>
|
||||
</div>
|
||||
<!-- #endregion -->
|
||||
|
||||
|
|
|
@ -153,6 +153,7 @@ class KubernetesCreateApplicationController {
|
|||
this.onEnvironmentVariableChange = this.onEnvironmentVariableChange.bind(this);
|
||||
this.onConfigMapsChange = this.onConfigMapsChange.bind(this);
|
||||
this.onSecretsChange = this.onSecretsChange.bind(this);
|
||||
this.onChangePersistedFolder = this.onChangePersistedFolder.bind(this);
|
||||
}
|
||||
/* #endregion */
|
||||
|
||||
|
@ -312,21 +313,21 @@ class KubernetesCreateApplicationController {
|
|||
}
|
||||
|
||||
restorePersistedFolder(index) {
|
||||
this.formValues.PersistedFolders[index].NeedsDeletion = false;
|
||||
this.formValues.PersistedFolders[index].needsDeletion = false;
|
||||
this.validatePersistedFolders();
|
||||
}
|
||||
|
||||
resetPersistedFolders() {
|
||||
this.formValues.PersistedFolders = _.forEach(this.formValues.PersistedFolders, (persistedFolder) => {
|
||||
persistedFolder.ExistingVolume = null;
|
||||
persistedFolder.UseNewVolume = true;
|
||||
persistedFolder.existingVolume = null;
|
||||
persistedFolder.useNewVolume = true;
|
||||
});
|
||||
this.validatePersistedFolders();
|
||||
}
|
||||
|
||||
removePersistedFolder(index) {
|
||||
if (this.state.isEdit && this.formValues.PersistedFolders[index].PersistentVolumeClaimName) {
|
||||
this.formValues.PersistedFolders[index].NeedsDeletion = true;
|
||||
if (this.state.isEdit && this.formValues.PersistedFolders[index].persistentVolumeClaimName) {
|
||||
this.formValues.PersistedFolders[index].needsDeletion = true;
|
||||
} else {
|
||||
this.formValues.PersistedFolders.splice(index, 1);
|
||||
}
|
||||
|
@ -334,15 +335,15 @@ class KubernetesCreateApplicationController {
|
|||
}
|
||||
|
||||
useNewVolume(index) {
|
||||
this.formValues.PersistedFolders[index].UseNewVolume = true;
|
||||
this.formValues.PersistedFolders[index].ExistingVolume = null;
|
||||
this.state.persistedFoldersUseExistingVolumes = !_.reduce(this.formValues.PersistedFolders, (acc, pf) => acc && pf.UseNewVolume, true);
|
||||
this.formValues.PersistedFolders[index].useNewVolume = true;
|
||||
this.formValues.PersistedFolders[index].existingVolume = null;
|
||||
this.state.persistedFoldersUseExistingVolumes = _.some(this.formValues.PersistedFolders, { useNewVolume: false });
|
||||
this.validatePersistedFolders();
|
||||
}
|
||||
|
||||
useExistingVolume(index) {
|
||||
this.formValues.PersistedFolders[index].UseNewVolume = false;
|
||||
this.state.persistedFoldersUseExistingVolumes = _.find(this.formValues.PersistedFolders, { UseNewVolume: false }) ? true : false;
|
||||
this.formValues.PersistedFolders[index].useNewVolume = false;
|
||||
this.state.persistedFoldersUseExistingVolumes = _.some(this.formValues.PersistedFolders, { useNewVolume: false });
|
||||
if (this.formValues.DataAccessPolicy === this.ApplicationDataAccessPolicies.ISOLATED) {
|
||||
this.formValues.DataAccessPolicy = this.ApplicationDataAccessPolicies.SHARED;
|
||||
this.resetDeploymentType();
|
||||
|
@ -360,22 +361,26 @@ class KubernetesCreateApplicationController {
|
|||
onChangePersistedFolderPath() {
|
||||
this.state.duplicates.persistedFolders.refs = KubernetesFormValidationHelper.getDuplicates(
|
||||
_.map(this.formValues.PersistedFolders, (persistedFolder) => {
|
||||
if (persistedFolder.NeedsDeletion) {
|
||||
if (persistedFolder.needsDeletion) {
|
||||
return undefined;
|
||||
}
|
||||
return persistedFolder.ContainerPath;
|
||||
return persistedFolder.containerPath;
|
||||
})
|
||||
);
|
||||
this.state.duplicates.persistedFolders.hasRefs = Object.keys(this.state.duplicates.persistedFolders.refs).length > 0;
|
||||
}
|
||||
|
||||
onChangePersistedFolder(values) {
|
||||
this.formValues.PersistedFolders = values;
|
||||
}
|
||||
|
||||
onChangeExistingVolumeSelection() {
|
||||
this.state.duplicates.existingVolumes.refs = KubernetesFormValidationHelper.getDuplicates(
|
||||
_.map(this.formValues.PersistedFolders, (persistedFolder) => {
|
||||
if (persistedFolder.NeedsDeletion) {
|
||||
if (persistedFolder.needsDeletion) {
|
||||
return undefined;
|
||||
}
|
||||
return persistedFolder.ExistingVolume ? persistedFolder.ExistingVolume.PersistentVolumeClaim.Name : '';
|
||||
return persistedFolder.existingVolume ? persistedFolder.existingVolume.PersistentVolumeClaim.Name : '';
|
||||
})
|
||||
);
|
||||
this.state.duplicates.existingVolumes.hasRefs = Object.keys(this.state.duplicates.existingVolumes.refs).length > 0;
|
||||
|
@ -518,8 +523,8 @@ class KubernetesCreateApplicationController {
|
|||
for (let i = 0; i < this.formValues.PersistedFolders.length; i++) {
|
||||
const folder = this.formValues.PersistedFolders[i];
|
||||
|
||||
if (folder.StorageClass && _.isEqual(folder.StorageClass.AccessModes, ['RWO'])) {
|
||||
storageOptions.push(folder.StorageClass.Name);
|
||||
if (folder.storageClass && _.isEqual(folder.storageClass.AccessModes, ['RWO'])) {
|
||||
storageOptions.push(folder.storageClass.Name);
|
||||
} else {
|
||||
storageOptions.push('<no storage option available>');
|
||||
}
|
||||
|
@ -612,7 +617,7 @@ class KubernetesCreateApplicationController {
|
|||
|
||||
/* #region PERSISTED FOLDERS */
|
||||
/* #region BUTTONS STATES */
|
||||
isAddPersistentFolderButtonShowed() {
|
||||
isAddPersistentFolderButtonShown() {
|
||||
return !this.isEditAndStatefulSet() && this.formValues.Containers.length <= 1;
|
||||
}
|
||||
|
||||
|
@ -630,7 +635,7 @@ class KubernetesCreateApplicationController {
|
|||
}
|
||||
|
||||
isEditAndExistingPersistedFolder(index) {
|
||||
return this.state.isEdit && this.formValues.PersistedFolders[index].PersistentVolumeClaimName;
|
||||
return this.state.isEdit && this.formValues.PersistedFolders[index].persistentVolumeClaimName;
|
||||
}
|
||||
/* #endregion */
|
||||
|
||||
|
@ -781,7 +786,7 @@ class KubernetesCreateApplicationController {
|
|||
this.volumes = volumes;
|
||||
const filteredVolumes = _.filter(this.volumes, (volume) => {
|
||||
const isUnused = !KubernetesVolumeHelper.isUsed(volume);
|
||||
const isRWX = volume.PersistentVolumeClaim.StorageClass && _.includes(volume.PersistentVolumeClaim.StorageClass.AccessModes, 'RWX');
|
||||
const isRWX = volume.PersistentVolumeClaim.storageClass && _.includes(volume.PersistentVolumeClaim.storageClass.AccessModes, 'RWX');
|
||||
return isUnused || isRWX;
|
||||
});
|
||||
this.availableVolumes = filteredVolumes;
|
||||
|
@ -873,7 +878,11 @@ class KubernetesCreateApplicationController {
|
|||
this.state.actionInProgress = true;
|
||||
await this.KubernetesApplicationService.patch(this.savedFormValues, this.formValues, false, this.originalServicePorts);
|
||||
this.Notifications.success('Success', 'Request to update application successfully submitted');
|
||||
this.$state.go('kubernetes.applications.application', { name: this.application.Name, namespace: this.application.ResourcePool });
|
||||
this.$state.go(
|
||||
'kubernetes.applications.application',
|
||||
{ name: this.application.Name, namespace: this.application.ResourcePool, endpointId: this.endpoint.Id },
|
||||
{ inherit: false }
|
||||
);
|
||||
} catch (err) {
|
||||
this.Notifications.error('Failure', err, 'Unable to update application');
|
||||
} finally {
|
||||
|
@ -1087,13 +1096,14 @@ class KubernetesCreateApplicationController {
|
|||
|
||||
if (this.application.ApplicationType !== KubernetesApplicationTypes.STATEFULSET) {
|
||||
_.forEach(this.formValues.PersistedFolders, (persistedFolder) => {
|
||||
const volume = _.find(this.availableVolumes, ['PersistentVolumeClaim.Name', persistedFolder.PersistentVolumeClaimName]);
|
||||
const volume = _.find(this.availableVolumes, ['PersistentVolumeClaim.Name', persistedFolder.persistentVolumeClaimName]);
|
||||
if (volume) {
|
||||
persistedFolder.UseNewVolume = false;
|
||||
persistedFolder.ExistingVolume = volume;
|
||||
persistedFolder.useNewVolume = false;
|
||||
persistedFolder.existingVolume = volume;
|
||||
}
|
||||
});
|
||||
}
|
||||
this.formValues.OriginalPersistedFolders = this.formValues.PersistedFolders;
|
||||
await this.refreshNamespaceData(namespace);
|
||||
} else {
|
||||
this.formValues.AutoScaler = KubernetesApplicationHelper.generateAutoScalerFormValueFromHorizontalPodAutoScaler(null, this.formValues.ReplicaCount);
|
||||
|
|
|
@ -91,7 +91,7 @@
|
|||
</div>
|
||||
</td>
|
||||
<td>{{ item.Name }}</td>
|
||||
<td>{{ item.Size }}</td>
|
||||
<td>{{ item.size }}</td>
|
||||
</tr>
|
||||
<tr
|
||||
dir-paginate-end
|
||||
|
|
|
@ -81,9 +81,9 @@
|
|||
<table-column-header
|
||||
col-title="'Usage'"
|
||||
can-sort="true"
|
||||
is-sorted="$ctrl.state.orderBy === 'Size'"
|
||||
is-sorted-desc="$ctrl.state.orderBy === 'Size' && $ctrl.state.reverseOrder"
|
||||
ng-click="$ctrl.changeOrderBy('Size')"
|
||||
is-sorted="$ctrl.state.orderBy === 'size'"
|
||||
is-sorted-desc="$ctrl.state.orderBy === 'size' && $ctrl.state.reverseOrder"
|
||||
ng-click="$ctrl.changeOrderBy('size')"
|
||||
></table-column-header>
|
||||
</th>
|
||||
</tr>
|
||||
|
@ -102,7 +102,7 @@
|
|||
</div>
|
||||
</td>
|
||||
<td>{{ item.Name }}</td>
|
||||
<td>{{ item.Size }}</td>
|
||||
<td>{{ item.size }}</td>
|
||||
</tr>
|
||||
<tr
|
||||
dir-paginate-end
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
</tr>
|
||||
<tr>
|
||||
<td>Storage Class</td>
|
||||
<td data-cy="k8sVolDetail-volStorageClassname">{{ ctrl.volume.PersistentVolumeClaim.StorageClass.Name }}</td>
|
||||
<td data-cy="k8sVolDetail-volStorageClassname">{{ ctrl.volume.PersistentVolumeClaim.storageClass.Name }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Access Modes</td>
|
||||
|
@ -69,7 +69,7 @@
|
|||
<tr>
|
||||
<td>Provisioner</td>
|
||||
<td data-cy="k8sVolDetail-volProvisioner">{{
|
||||
ctrl.volume.PersistentVolumeClaim.StorageClass.Provisioner ? ctrl.volume.PersistentVolumeClaim.StorageClass.Provisioner : '-'
|
||||
ctrl.volume.PersistentVolumeClaim.storageClass.Provisioner ? ctrl.volume.PersistentVolumeClaim.storageClass.Provisioner : '-'
|
||||
}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
@ -77,14 +77,14 @@
|
|||
<td data-cy="k8sVolDetail-volCreatedAt">{{ ctrl.volume.PersistentVolumeClaim.CreationDate | getisodate }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Size</td>
|
||||
<td>size</td>
|
||||
<td ng-if="!ctrl.state.increaseSize">
|
||||
{{ ctrl.volume.PersistentVolumeClaim.Storage }}
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm btn-primary"
|
||||
ng-click="ctrl.state.increaseSize = true"
|
||||
ng-if="ctrl.volume.PersistentVolumeClaim.StorageClass.AllowVolumeExpansion"
|
||||
ng-if="ctrl.volume.PersistentVolumeClaim.storageClass.AllowVolumeExpansion"
|
||||
data-cy="k8sVolDetail-increaseSizeButton"
|
||||
>Increase size</button
|
||||
>
|
||||
|
|
|
@ -186,12 +186,14 @@ class KubernetesVolumeController {
|
|||
try {
|
||||
await this.getVolume();
|
||||
await this.getEvents();
|
||||
this.state.volumeSharedAccessPolicies = this.volume.PersistentVolumeClaim.AccessModes;
|
||||
let policies = KubernetesStorageClassAccessPolicies();
|
||||
this.state.volumeSharedAccessPolicyTooltips = this.state.volumeSharedAccessPolicies.map((policy) => {
|
||||
const matchingPolicy = policies.find((p) => p.Name === policy);
|
||||
return matchingPolicy ? matchingPolicy.Description : undefined;
|
||||
});
|
||||
if (this.volume.PersistentVolumeClaim.storageClass !== undefined) {
|
||||
this.state.volumeSharedAccessPolicies = this.volume.PersistentVolumeClaim.AccessModes;
|
||||
let policies = KubernetesStorageClassAccessPolicies();
|
||||
this.state.volumeSharedAccessPolicyTooltips = this.state.volumeSharedAccessPolicies.map((policy) => {
|
||||
const matchingPolicy = policies.find((p) => p.Name === policy);
|
||||
return matchingPolicy ? matchingPolicy.Description : undefined;
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
this.Notifications.error('Failure', err, 'Unable to load view data');
|
||||
} finally {
|
||||
|
|
|
@ -7,9 +7,9 @@ import { confirmDelete } from '@@/modals/confirm';
|
|||
|
||||
function buildStorages(storages, volumes) {
|
||||
_.forEach(storages, (s) => {
|
||||
const filteredVolumes = _.filter(volumes, ['PersistentVolumeClaim.StorageClass.Name', s.Name, 'PersistentVolumeClaim.StorageClass.Provisioner', s.Provisioner]);
|
||||
const filteredVolumes = _.filter(volumes, ['PersistentVolumeClaim.storageClass.Name', s.Name, 'PersistentVolumeClaim.storageClass.Provisioner', s.Provisioner]);
|
||||
s.Volumes = filteredVolumes;
|
||||
s.Size = computeSize(filteredVolumes);
|
||||
s.size = computeSize(filteredVolumes);
|
||||
});
|
||||
return storages;
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ function buildStorages(storages, volumes) {
|
|||
function computeSize(volumes) {
|
||||
const size = _.sumBy(volumes, (v) => filesizeParser(v.PersistentVolumeClaim.Storage, { base: 10 }));
|
||||
const format = KubernetesResourceQuotaHelper.formatBytes(size);
|
||||
return `${format.Size}${format.SizeUnit}`;
|
||||
return `${format.size}${format.sizeUnit}`;
|
||||
}
|
||||
|
||||
class KubernetesVolumesController {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue