@@ -97,6 +97,60 @@ func (a *nutanixValidator) validate(
9797 return admission .Allowed ("" )
9898}
9999
100+ // validateFailureDomainXORMachineDetails validates the XOR behavior between failure domains
101+ // and cluster/subnets configuration. Either failure domains are set OR cluster and subnets
102+ // are set with machineDetails, but not both.
103+ func validateFailureDomainXORMachineDetails (
104+ fldPath * field.Path ,
105+ hasFailureDomains bool ,
106+ machineDetails * v1alpha1.NutanixMachineDetails ,
107+ failureDomainTerm string , // "failureDomains" for control plane, "failureDomain" for workers
108+ ) field.ErrorList {
109+ fldErrs := field.ErrorList {}
110+
111+ // Determine the correct verb based on singular/plural
112+ verb := "is"
113+ if failureDomainTerm == "failureDomains" {
114+ verb = "are"
115+ }
116+
117+ hasCluster , hasSubnets := machineDetails .HasClusterAndSubnets ()
118+
119+ if ! hasFailureDomains {
120+ // No failure domains -> cluster/subnets MUST be set
121+ if ! hasCluster {
122+ fldErrs = append (fldErrs , field .Required (
123+ fldPath .Child ("cluster" ),
124+ fmt .Sprintf ("\" cluster\" must be set when %s %s not configured." , failureDomainTerm , verb ),
125+ ))
126+ }
127+
128+ if ! hasSubnets {
129+ fldErrs = append (fldErrs , field .Required (
130+ fldPath .Child ("subnets" ),
131+ fmt .Sprintf ("\" subnets\" must be set when %s %s not configured." , failureDomainTerm , verb ),
132+ ))
133+ }
134+ } else {
135+ // Failure domains present -> cluster/subnets MUST NOT be set
136+ if hasCluster {
137+ fldErrs = append (fldErrs , field .Forbidden (
138+ fldPath .Child ("cluster" ),
139+ fmt .Sprintf ("\" cluster\" must not be set when %s %s configured." , failureDomainTerm , verb ),
140+ ))
141+ }
142+
143+ if hasSubnets {
144+ fldErrs = append (fldErrs , field .Forbidden (
145+ fldPath .Child ("subnets" ),
146+ fmt .Sprintf ("\" subnets\" must not be set when %s %s configured." , failureDomainTerm , verb ),
147+ ))
148+ }
149+ }
150+
151+ return fldErrs
152+ }
153+
100154// validateTopologyFailureDomainConfig validates the failure domain related configuration in cluster topology.
101155func validateTopologyFailureDomainConfig (
102156 clusterConfig * variables.ClusterConfigSpec ,
@@ -135,41 +189,15 @@ func validateControlPlaneFailureDomainConfig(clusterConfig *variables.ClusterCon
135189 if clusterConfig .ControlPlane != nil && clusterConfig .ControlPlane .Nutanix != nil {
136190 machineDetails := clusterConfig .ControlPlane .Nutanix .MachineDetails
137191 hasFailureDomains := len (clusterConfig .ControlPlane .Nutanix .FailureDomains ) > 0
138- hasCluster := machineDetails .Cluster != nil &&
139- (machineDetails .Cluster .IsName () || machineDetails .Cluster .IsUUID ())
140- hasSubnets := len (machineDetails .Subnets ) > 0
141-
142- if ! hasFailureDomains {
143- // No failure domains -> cluster/subnets MUST be set
144- if ! hasCluster {
145- fldErrs = append (fldErrs , field .Required (
146- fldPath .Child ("cluster" ),
147- "\" cluster\" must be set when failureDomains are not configured." ,
148- ))
149- }
150-
151- if ! hasSubnets {
152- fldErrs = append (fldErrs , field .Required (
153- fldPath .Child ("subnets" ),
154- "\" subnets\" must be set when failureDomains are not configured." ,
155- ))
156- }
157- } else {
158- // Failure domains present -> cluster/subnets MUST NOT be set
159- if hasCluster {
160- fldErrs = append (fldErrs , field .Forbidden (
161- fldPath .Child ("cluster" ),
162- "\" cluster\" must not be set when failureDomains are configured." ,
163- ))
164- }
165192
166- if hasSubnets {
167- fldErrs = append (fldErrs , field .Forbidden (
168- fldPath .Child ("subnets" ),
169- "\" subnets\" must not be set when failureDomains are configured." ,
170- ))
171- }
172- }
193+ fldErrs = append (
194+ fldErrs ,
195+ validateFailureDomainXORMachineDetails (
196+ fldPath ,
197+ hasFailureDomains ,
198+ & machineDetails ,
199+ "failureDomains" ,
200+ )... )
173201 }
174202
175203 return fldErrs
@@ -231,39 +259,15 @@ func validateWorkerFailureDomainConfig(
231259 }
232260
233261 machineDetails := workerConfig .Nutanix .MachineDetails
234- hasCluster := machineDetails .Cluster != nil &&
235- (machineDetails .Cluster .IsName () || machineDetails .Cluster .IsUUID ())
236- hasSubnets := len (machineDetails .Subnets ) > 0
237-
238- if ! hasFailureDomain {
239- // No failure domain -> cluster/subnets MUST be set
240- if ! hasCluster {
241- fldErrs = append (fldErrs , field .Required (
242- wcfgPath .Child ("value" , "nutanix" , "machineDetails" , "cluster" ),
243- "\" cluster\" must be set when failureDomain is not configured." ,
244- ))
245- }
246- if ! hasSubnets {
247- fldErrs = append (fldErrs , field .Required (
248- wcfgPath .Child ("value" , "nutanix" , "machineDetails" , "subnets" ),
249- "\" subnets\" must be set when failureDomain is not configured." ,
250- ))
251- }
252- } else {
253- // Failure domain present -> cluster/subnets MUST NOT be set
254- if hasCluster {
255- fldErrs = append (fldErrs , field .Forbidden (
256- wcfgPath .Child ("value" , "nutanix" , "machineDetails" , "cluster" ),
257- "\" cluster\" must not be set when failureDomain is configured." ,
258- ))
259- }
260- if hasSubnets {
261- fldErrs = append (fldErrs , field .Forbidden (
262- wcfgPath .Child ("value" , "nutanix" , "machineDetails" , "subnets" ),
263- "\" subnets\" must not be set when failureDomain is configured." ,
264- ))
265- }
266- }
262+
263+ fldErrs = append (
264+ fldErrs ,
265+ validateFailureDomainXORMachineDetails (
266+ wcfgPath .Child ("value" , "nutanix" , "machineDetails" ),
267+ hasFailureDomain ,
268+ & machineDetails ,
269+ "failureDomain" ,
270+ )... )
267271 }
268272 }
269273
0 commit comments