From d51df592f0f7017d6290f81b097693fa2925ba97 Mon Sep 17 00:00:00 2001 From: Montse Ortega Date: Thu, 6 Nov 2025 14:40:06 +0100 Subject: [PATCH 1/2] Solving errors with SNO dual-stack --- .../networkConfigurationValidation.ts | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/libs/ui-lib/lib/ocm/components/clusterConfiguration/networkConfiguration/networkConfigurationValidation.ts b/libs/ui-lib/lib/ocm/components/clusterConfiguration/networkConfiguration/networkConfigurationValidation.ts index bd261659c2..565b261e2d 100644 --- a/libs/ui-lib/lib/ocm/components/clusterConfiguration/networkConfiguration/networkConfigurationValidation.ts +++ b/libs/ui-lib/lib/ocm/components/clusterConfiguration/networkConfiguration/networkConfigurationValidation.ts @@ -74,17 +74,9 @@ export const getNetworkConfigurationValidationSchema = ( hostSubnets: HostSubnets, openshiftVersion?: string, ) => - Yup.lazy((values: NetworkConfigurationValues) => { - const apiVipSchema = - values.stackType === DUAL_STACK - ? vipArrayValidationSchema(hostSubnets, values, initialValues.apiVips).min( - 2, - 'Provide both Primary and Secondary API IPs.', - ) - : vipArrayValidationSchema(hostSubnets, values, initialValues.apiVips); - - return Yup.object().shape({ - apiVips: apiVipSchema, + Yup.lazy((values: NetworkConfigurationValues) => + Yup.object().shape({ + apiVips: vipArrayValidationSchema(hostSubnets, values, initialValues.apiVips), ingressVips: vipArrayValidationSchema( hostSubnets, values, @@ -124,5 +116,5 @@ export const getNetworkConfigurationValidationSchema = ( ) : Yup.array(), }), - }); - }); + }), + ); From fe9fc1e59ff700b8a5d5da5d5644a5c534aaa554 Mon Sep 17 00:00:00 2001 From: Montse Ortega Date: Fri, 7 Nov 2025 13:54:27 +0100 Subject: [PATCH 2/2] Solving errors when change between dual-stack and single-stack --- .../networkConfiguration/StackTypeControl.tsx | 28 +++++++++++++++++-- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/libs/ui-lib/lib/ocm/components/clusterConfiguration/networkConfiguration/StackTypeControl.tsx b/libs/ui-lib/lib/ocm/components/clusterConfiguration/networkConfiguration/StackTypeControl.tsx index f5fa51dade..6d9f4cd085 100644 --- a/libs/ui-lib/lib/ocm/components/clusterConfiguration/networkConfiguration/StackTypeControl.tsx +++ b/libs/ui-lib/lib/ocm/components/clusterConfiguration/networkConfiguration/StackTypeControl.tsx @@ -68,11 +68,12 @@ export const StackTypeControlGroup = ({ const setSingleStack = React.useCallback(() => { setFieldValue('stackType', IPV4_STACK); + // Determine whether the first machine network is IPv4 + const firstNetwork = values.machineNetworks?.[0]; + const isFirstIPv4 = Boolean(firstNetwork?.cidr && Address4.isValid(firstNetwork.cidr)); + if (values.machineNetworks && values.machineNetworks?.length >= 2) { // For single-stack IPv4, prefer IPv4 machine network - const firstNetwork = values.machineNetworks[0]; - const isFirstIPv4 = firstNetwork?.cidr && Address4.isValid(firstNetwork.cidr); - if (isFirstIPv4) { // Keep the first network if it's IPv4 setFieldValue('machineNetworks', [firstNetwork]); @@ -123,6 +124,24 @@ export const StackTypeControlGroup = ({ setFieldValue('serviceNetworks', [ipv4Service]); } + // Keep only IPv4 VIPs when switching to single-stack (unless DHCP allocation is used) + if (!values.vipDhcpAllocation) { + const pruneVips = ( + vips?: { ip?: string; clusterId?: Cluster['id'] }[], + ): { ip: string; clusterId: Cluster['id'] }[] => { + if (!vips || vips.length === 0) return []; + // Choose which index to keep based on whether the first network is IPv4 + const keepIndex = isFirstIPv4 ? 0 : 1; + const chosen = vips[keepIndex]; + return chosen && chosen.ip + ? [{ ip: chosen.ip, clusterId: chosen.clusterId || clusterId }] + : []; + }; + + setFieldValue('apiVips', pruneVips(values.apiVips)); + setFieldValue('ingressVips', pruneVips(values.ingressVips)); + } + void validateForm(); }, [ setFieldValue, @@ -133,6 +152,9 @@ export const StackTypeControlGroup = ({ values.clusterNetworks, values.machineNetworks, values.serviceNetworks, + values.apiVips, + values.ingressVips, + values.vipDhcpAllocation, ]); const setDualStack = () => {