mirror of https://github.com/portainer/portainer
refactor(app): migrate resource reservations [EE-6236] (#10695)
* refactor(app): migrate resource reservations [EE-6236]pull/10705/head
parent
e07ee05ee7
commit
947ba4940b
@ -0,0 +1,99 @@
|
||||
import { FormikErrors } from 'formik';
|
||||
|
||||
import { FormSection } from '@@/form-components/FormSection';
|
||||
import { TextTip } from '@@/Tip/TextTip';
|
||||
import { SliderWithInput } from '@@/form-components/Slider/SliderWithInput';
|
||||
import { FormControl } from '@@/form-components/FormControl';
|
||||
import { FormError } from '@@/form-components/FormError';
|
||||
import { Slider } from '@@/form-components/Slider';
|
||||
|
||||
import { ResourceQuotaFormValues } from './types';
|
||||
|
||||
type Props = {
|
||||
values: ResourceQuotaFormValues;
|
||||
onChange: (values: ResourceQuotaFormValues) => void;
|
||||
errors: FormikErrors<ResourceQuotaFormValues>;
|
||||
namespaceHasQuota: boolean;
|
||||
resourceQuotaCapacityExceeded: boolean;
|
||||
maxMemoryLimit: number;
|
||||
maxCpuLimit: number;
|
||||
};
|
||||
|
||||
export function ResourceReservationFormSection({
|
||||
values,
|
||||
onChange,
|
||||
errors,
|
||||
namespaceHasQuota,
|
||||
resourceQuotaCapacityExceeded,
|
||||
maxMemoryLimit,
|
||||
maxCpuLimit,
|
||||
}: Props) {
|
||||
return (
|
||||
<FormSection title="Resource reservations" titleSize="md">
|
||||
{!namespaceHasQuota && (
|
||||
<TextTip color="blue">
|
||||
Resource reservations are applied per instance of the application.
|
||||
</TextTip>
|
||||
)}
|
||||
{namespaceHasQuota && !resourceQuotaCapacityExceeded && (
|
||||
<TextTip color="blue">
|
||||
A resource quota is set on this namespace, you must specify resource
|
||||
reservations. Resource reservations are applied per instance of the
|
||||
application. Maximums are inherited from the namespace quota.
|
||||
</TextTip>
|
||||
)}
|
||||
{namespaceHasQuota && resourceQuotaCapacityExceeded && (
|
||||
<TextTip color="red">
|
||||
This namespace has exhausted its resource capacity and you will not be
|
||||
able to deploy the application. Contact your administrator to expand
|
||||
the capacity of the namespace.
|
||||
</TextTip>
|
||||
)}
|
||||
<FormControl
|
||||
className="flex flex-row"
|
||||
label="Memory limit (MB)"
|
||||
tooltip="An instance of this application will reserve this amount of memory. If the instance memory usage exceeds the reservation, it might be subject to OOM."
|
||||
>
|
||||
<div className="col-xs-10">
|
||||
<SliderWithInput
|
||||
value={Number(values.memoryLimit) ?? 0}
|
||||
onChange={(value) => onChange({ ...values, memoryLimit: value })}
|
||||
max={maxMemoryLimit}
|
||||
step={128}
|
||||
dataCy="k8sAppCreate-memoryLimit"
|
||||
visibleTooltip
|
||||
/>
|
||||
{errors?.memoryLimit && (
|
||||
<FormError className="pt-1">{errors.memoryLimit}</FormError>
|
||||
)}
|
||||
</div>
|
||||
</FormControl>
|
||||
<FormControl
|
||||
className="flex flex-row"
|
||||
label="CPU limit"
|
||||
tooltip="An instance of this application will reserve this amount of CPU. If the instance CPU usage exceeds the reservation, it might be subject to CPU throttling."
|
||||
>
|
||||
<div className="col-xs-10">
|
||||
<Slider
|
||||
onChange={(value) =>
|
||||
onChange(
|
||||
typeof value === 'number'
|
||||
? { ...values, cpuLimit: value }
|
||||
: { ...values, cpuLimit: value[0] ?? 0 }
|
||||
)
|
||||
}
|
||||
value={values.cpuLimit}
|
||||
min={0}
|
||||
max={maxCpuLimit}
|
||||
step={0.01}
|
||||
dataCy="k8sAppCreate-cpuLimitSlider"
|
||||
visibleTooltip
|
||||
/>
|
||||
{errors?.cpuLimit && (
|
||||
<FormError className="pt-1">{errors.cpuLimit}</FormError>
|
||||
)}
|
||||
</div>
|
||||
</FormControl>
|
||||
</FormSection>
|
||||
);
|
||||
}
|
@ -0,0 +1,2 @@
|
||||
export { ResourceReservationFormSection } from './ResourceReservationFormSection';
|
||||
export { resourceReservationValidation } from './resourceReservationValidation';
|
@ -0,0 +1,29 @@
|
||||
import { SchemaOf, number, object } from 'yup';
|
||||
|
||||
import { ResourceQuotaFormValues } from './types';
|
||||
|
||||
type ValidationData = {
|
||||
maxMemoryLimit: number;
|
||||
maxCpuLimit: number;
|
||||
};
|
||||
|
||||
export function resourceReservationValidation(
|
||||
validationData?: ValidationData
|
||||
): SchemaOf<ResourceQuotaFormValues> {
|
||||
return object().shape({
|
||||
memoryLimit: number()
|
||||
.min(0)
|
||||
.max(
|
||||
validationData?.maxMemoryLimit || 0,
|
||||
`Value must be between 0 and ${validationData?.maxMemoryLimit}`
|
||||
)
|
||||
.required(),
|
||||
cpuLimit: number()
|
||||
.min(0)
|
||||
.max(
|
||||
validationData?.maxCpuLimit || 0,
|
||||
`Value must be between 0 and ${validationData?.maxCpuLimit}`
|
||||
)
|
||||
.required(),
|
||||
});
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
export type ResourceQuotaFormValues = {
|
||||
memoryLimit: number;
|
||||
cpuLimit: number;
|
||||
};
|
Loading…
Reference in new issue