1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-07-23 15:29:42 +02:00

fix(app): various persisted folder fixes [EE-6235] (#10963)

Co-authored-by: testa113 <testa113>
This commit is contained in:
Ali 2024-01-17 08:31:22 +13:00 committed by GitHub
parent 7a04d1d4ea
commit 95474b7dc5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 84 additions and 78 deletions

View file

@ -1,12 +1,12 @@
import { Boxes, Sliders } from 'lucide-react';
import { FormikErrors } from 'formik';
import { BoxSelector } from '@@/BoxSelector';
import { BoxSelector, BoxSelectorOption } from '@@/BoxSelector';
import { FormSection } from '@@/form-components/FormSection';
import { TextTip } from '@@/Tip/TextTip';
import { FormError } from '@@/form-components/FormError';
import { DeploymentType } from '../../types';
import { getDeploymentOptions } from '../../CreateView/deploymentOptions';
interface Props {
values: DeploymentType;
@ -21,7 +21,7 @@ export function AppDeploymentTypeFormSection({
errors,
supportGlobalDeployment,
}: Props) {
const options = getDeploymentOptions(supportGlobalDeployment);
const options = getOptions(supportGlobalDeployment);
return (
<FormSection title="Deployment">
@ -39,3 +39,32 @@ export function AppDeploymentTypeFormSection({
</FormSection>
);
}
function getOptions(
supportGlobalDeployment: boolean
): ReadonlyArray<BoxSelectorOption<DeploymentType>> {
return [
{
id: 'deployment_replicated',
label: 'Replicated',
value: 'Replicated',
icon: Sliders,
iconType: 'badge',
description: 'Run one or multiple instances of this container',
},
{
id: 'deployment_global',
disabled: () => !supportGlobalDeployment,
tooltip: () =>
!supportGlobalDeployment
? 'The storage or access policy used for persisted folders cannot be used with this option'
: '',
label: 'Global',
description:
'Application will be deployed as a DaemonSet with an instance on each node of the cluster',
value: 'Global',
icon: Boxes,
iconType: 'badge',
},
] as const;
}

View file

@ -91,7 +91,7 @@ export function ConfigurationItem({
<Button
color="dangerlight"
size="medium"
onClick={() => onRemoveItem()}
onClick={onRemoveItem}
className="!ml-0 vertical-center btn-only-icon"
icon={Trash2}
/>

View file

@ -16,7 +16,7 @@ import { ApplicationFormValues } from '../../types';
import { ExistingVolume, PersistedFolderFormValue } from './types';
type Props = {
initialValues: PersistedFolderFormValue[];
initialValues?: PersistedFolderFormValue[];
item: PersistedFolderFormValue;
onChange: (value: PersistedFolderFormValue) => void;
error: ItemError<PersistedFolderFormValue>;
@ -220,7 +220,6 @@ export function PersistedFolderItem({
function isToggleVolumeTypeVisible() {
return (
!(isEdit && isExistingPersistedFolder()) && // if it's not an edit of an existing persisted folder
applicationValues.ApplicationType !== 'StatefulSet' && // and if it's not a statefulset
applicationValues.Containers.length <= 1 // and if there is only one container);
);
}

View file

@ -57,7 +57,10 @@ export function PersistedFoldersFormSection({
value={values}
onChange={onChange}
errors={errors}
isDeleteButtonHidden={isDeleteButtonHidden()}
isDeleteButtonHidden={
isEdit && applicationValues.ApplicationType === 'StatefulSet'
}
canUndoDelete={isEdit}
deleteButtonDataCy="k8sAppCreate-persistentFolderRemoveButton"
addButtonDataCy="k8sAppCreate-persistentFolderAddButton"
disabled={storageClasses.length === 0}
@ -77,33 +80,20 @@ export function PersistedFoldersFormSection({
initialValues={initialValues}
/>
)}
itemBuilder={() => {
const newVolumeClaimName = `${applicationValues.Name}-${uuidv4()}`;
return {
persistentVolumeClaimName:
availableVolumes[0]?.PersistentVolumeClaim.Name ||
newVolumeClaimName,
containerPath: '',
size: '',
sizeUnit: 'GB',
storageClass: storageClasses[0],
useNewVolume: true,
existingVolume: undefined,
needsDeletion: false,
};
}}
itemBuilder={() => ({
persistentVolumeClaimName: getNewPVCName(applicationValues.Name),
containerPath: '',
size: '',
sizeUnit: 'GB',
storageClass: storageClasses[0],
useNewVolume: true,
existingVolume: undefined,
needsDeletion: false,
})}
addLabel="Add persisted folder"
canUndoDelete={isEdit}
/>
</FormSection>
);
function isDeleteButtonHidden() {
return (
(isEdit && applicationValues.ApplicationType === 'StatefulSet') ||
applicationValues.Containers.length >= 1
);
}
}
function usePVCOptions(existingPVCs: ExistingVolume[]): Option<string>[] {
@ -123,3 +113,10 @@ function getAddButtonError(storageClasses: StorageClass[]) {
}
return '';
}
function getNewPVCName(applicationName: string) {
const name = `${applicationName}-${uuidv4()}`;
// limit it to 63 characters to avoid exceeding the limit for the volume name
const nameLimited = name.length > 63 ? name.substring(0, 63) : name;
return nameLimited;
}

View file

@ -34,7 +34,12 @@ export function replicationValidation(
.test(
'scalable',
`The following storage option(s) do not support concurrent access from multiples instances: ${nonScalableStorage}. You will not be able to scale that application.`,
() => !!supportScalableReplicaDeployment // must have support scalable replica deployment
(value) => {
if (!value || value <= 1) {
return true;
}
return !!supportScalableReplicaDeployment;
} // must have support scalable replica deployment
)
.required('Instance count is required.'),
});