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 = () => { 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 2d7f6b0e91..30bb0466ef 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(), }), - }); - }); + }), + );