1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-07-20 22:09:41 +02:00
portainer/app/react/kubernetes/applications/components/ResourceReservationFormSection/resourceReservationValidation.ts
Ali 51449490fa
Some checks are pending
ci / build_images (map[arch:amd64 platform:linux version:]) (push) Waiting to run
ci / build_images (map[arch:amd64 platform:windows version:1809]) (push) Waiting to run
ci / build_images (map[arch:amd64 platform:windows version:ltsc2022]) (push) Waiting to run
ci / build_images (map[arch:arm platform:linux version:]) (push) Waiting to run
ci / build_images (map[arch:arm64 platform:linux version:]) (push) Waiting to run
ci / build_images (map[arch:ppc64le platform:linux version:]) (push) Waiting to run
ci / build_images (map[arch:s390x platform:linux version:]) (push) Waiting to run
ci / build_manifests (push) Blocked by required conditions
/ triage (push) Waiting to run
Lint / Run linters (push) Waiting to run
Test / test-client (push) Waiting to run
Test / test-server (map[arch:amd64 platform:linux]) (push) Waiting to run
Test / test-server (map[arch:amd64 platform:windows version:1809]) (push) Waiting to run
Test / test-server (map[arch:amd64 platform:windows version:ltsc2022]) (push) Waiting to run
Test / test-server (map[arch:arm64 platform:linux]) (push) Waiting to run
fix(app): on create don't mention previous values [EE-6837] (#11350)
Co-authored-by: testa113 <testa113>
2024-03-11 16:43:41 +13:00

118 lines
4.1 KiB
TypeScript

import { SchemaOf, TestContext, number, object } from 'yup';
import KubernetesResourceReservationHelper from '@/kubernetes/helpers/resourceReservationHelper';
import { nanNumberSchema } from '@/react-tools/yup-schemas';
import { ResourceQuotaFormValues } from './types';
type NodeLimit = {
CPU: number;
Memory: number;
};
type NodesLimits = Record<string, NodeLimit>;
type ValidationData = {
maxMemoryLimit: number;
maxCpuLimit: number;
isEnvironmentAdmin: boolean;
nodeLimits: NodesLimits;
isEdit: boolean;
};
export function resourceReservationValidation(
validationData?: ValidationData
): SchemaOf<ResourceQuotaFormValues> {
return object().shape({
memoryLimit: nanNumberSchema('Memory limit is required.')
.min(0, 'Value must be greater than or equal to 0.')
.test(
'exhaused',
`The memory capacity for this namespace has been exhausted, so you cannot deploy the application.${
validationData?.isEnvironmentAdmin
? ''
: ' Contact your administrator to expand the memory capacity of the namespace.'
}`,
() => !!validationData && validationData.maxMemoryLimit > 0
)
.max(validationData?.maxMemoryLimit || 0, ({ value }) =>
validationData?.isEdit
? `Value must be between 0 and ${validationData?.maxMemoryLimit}MB now - the previous value of ${value} exceeds this.`
: `Value must be between 0 and ${validationData?.maxMemoryLimit}MB.`
)
.test(
'hasSuitableNode',
`These reservations would exceed the resources currently available in the cluster.`,
// eslint-disable-next-line prefer-arrow-callback, func-names
function (value: number | undefined, context: TestContext) {
if (!validationData || value === undefined) {
// explicitely check for undefined, since 0 is a valid value
return true;
}
const { memoryLimit, cpuLimit } = context.parent;
return hasSuitableNode(
memoryLimit,
cpuLimit,
validationData.nodeLimits
);
}
)
.required('Memory limit is required.'),
cpuLimit: number()
.min(0)
.test(
'exhaused',
`The CPU capacity for this namespace has been exhausted, so you cannot deploy the application.${
validationData?.isEnvironmentAdmin
? ''
: ' Contact your administrator to expand the CPU capacity of the namespace.'
}`,
() => !!validationData && validationData.maxCpuLimit > 0
)
.max(validationData?.maxCpuLimit || 0, ({ value }) =>
validationData?.isEdit
? `Value must be between 0 and ${validationData?.maxCpuLimit} now - the previous value of ${value} exceeds this.`
: `Value must be between 0 and ${validationData?.maxCpuLimit}.`
)
.test(
'hasSuitableNode',
`These reservations would exceed the resources currently available in the cluster.`,
// eslint-disable-next-line prefer-arrow-callback, func-names
function (value: number | undefined, context: TestContext) {
if (!validationData || value === undefined) {
// explicitely check for undefined, since 0 is a valid value
return true;
}
const { memoryLimit, cpuLimit } = context.parent;
return hasSuitableNode(
memoryLimit,
cpuLimit,
validationData.nodeLimits
);
}
)
.required(),
});
}
function hasSuitableNode(
memoryLimit: number,
cpuLimit: number,
nodeLimits: NodesLimits
) {
const nanParsedMemoryLimit = Number.isNaN(memoryLimit) ? 0 : memoryLimit;
const nanParsedCPULimit = Number.isNaN(cpuLimit) ? 0 : cpuLimit;
// transform the nodelimits from bytes to MB
const limits = Object.values(nodeLimits).map((nodeLimit) => ({
...nodeLimit,
Memory: KubernetesResourceReservationHelper.megaBytesValue(
nodeLimit.Memory
),
}));
// make sure there's a node available with enough memory and cpu
return limits.some(
(nodeLimit) =>
nodeLimit.Memory >= nanParsedMemoryLimit &&
nodeLimit.CPU >= nanParsedCPULimit
);
}