fix(app): remove duplicate validation messages [EE-5933] (#10967)
parent
93593e1379
commit
a58b4f479b
|
@ -24,7 +24,7 @@ func (kcl *KubeClient) GetNodesLimits() (portainer.K8sNodesLimits, error) {
|
|||
|
||||
for _, item := range nodes.Items {
|
||||
cpu := item.Status.Allocatable.Cpu().MilliValue()
|
||||
memory := item.Status.Allocatable.Memory().Value()
|
||||
memory := item.Status.Allocatable.Memory().Value() // bytes
|
||||
|
||||
nodesLimits[item.ObjectMeta.Name] = &portainer.K8sNodeLimits{
|
||||
CPU: cpu,
|
||||
|
@ -57,7 +57,7 @@ func (client *KubeClient) GetMaxResourceLimits(skipNamespace string, overCommitE
|
|||
memory := int64(0)
|
||||
for _, node := range nodes.Items {
|
||||
limits.CPU += node.Status.Allocatable.Cpu().MilliValue()
|
||||
memory += node.Status.Allocatable.Memory().Value()
|
||||
memory += node.Status.Allocatable.Memory().Value() // bytes
|
||||
}
|
||||
limits.Memory = memory / 1000000 // B to MB
|
||||
|
||||
|
|
|
@ -285,7 +285,7 @@
|
|||
namespace-has-quota="ctrl.state.resourcePoolHasQuota"
|
||||
max-memory-limit="ctrl.state.sliders.memory.max"
|
||||
max-cpu-limit="ctrl.state.sliders.cpu.max"
|
||||
validation-data="{maxMemoryLimit: ctrl.state.sliders.memory.max, maxCpuLimit: ctrl.state.sliders.cpu.max, isEnvironmentAdmin: ctrl.isAdmin}"
|
||||
validation-data="{maxMemoryLimit: ctrl.state.sliders.memory.max, maxCpuLimit: ctrl.state.sliders.cpu.max, isEnvironmentAdmin: ctrl.isAdmin, nodeLimits: ctrl.nodesLimits.nodesLimits}"
|
||||
resource-quota-capacity-exceeded="ctrl.resourceQuotaCapacityExceeded()"
|
||||
></resource-reservation-form-section>
|
||||
|
||||
|
|
|
@ -14,6 +14,12 @@ export function deploymentTypeValidation(
|
|||
.test(
|
||||
'exhaused',
|
||||
`This application would exceed available resources. Please review resource reservations or the instance count.`,
|
||||
() => !validationData?.isQuotaExceeded
|
||||
(value) => {
|
||||
// ignore this validation if the user has selected Replicated, in this case, the isQuotaExceeded will below the instance count input
|
||||
if (value === 'Replicated') {
|
||||
return true;
|
||||
}
|
||||
return !validationData?.isQuotaExceeded;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -24,7 +24,13 @@ export function replicationValidation(
|
|||
.test(
|
||||
'overflow',
|
||||
'This application would exceed available resources. Please review resource reservations or the instance count.',
|
||||
() => !resourceReservationsOverflow // must not have resource reservations overflow
|
||||
(value) => {
|
||||
// the user can't fix the error here with 1 replica. There are validation errors in the resource reservations section that are helpful in a case of resourceReservationsOverflow.
|
||||
if (value === 1) {
|
||||
return true;
|
||||
}
|
||||
return !resourceReservationsOverflow;
|
||||
}
|
||||
)
|
||||
.test(
|
||||
'quota',
|
||||
|
|
|
@ -1,11 +1,21 @@
|
|||
import { SchemaOf, number, object } from 'yup';
|
||||
import { SchemaOf, TestContext, number, object } from 'yup';
|
||||
|
||||
import KubernetesResourceReservationHelper from '@/kubernetes/helpers/resourceReservationHelper';
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
export function resourceReservationValidation(
|
||||
|
@ -28,6 +38,23 @@ export function resourceReservationValidation(
|
|||
({ value }) =>
|
||||
`Value must be between 0 and ${validationData?.maxMemoryLimit}MB now - the previous value of ${value} exceeds this`
|
||||
)
|
||||
.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(),
|
||||
cpuLimit: number()
|
||||
.min(0)
|
||||
|
@ -45,6 +72,41 @@ export function resourceReservationValidation(
|
|||
({ value }) =>
|
||||
`Value must be between 0 and ${validationData?.maxCpuLimit} now - the previous value of ${value} exceeds this`
|
||||
)
|
||||
.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
|
||||
) {
|
||||
// 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 >= memoryLimit && nodeLimit.CPU >= cpuLimit
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue