Skip to content

Commit 89a1613

Browse files
authored
Merge pull request #6322 from killianmuldoon/webhook/cluster-fieldpaths
🌱 Add field.Path aggregation for Cluster webhook
2 parents 582f51a + 91d130f commit 89a1613

File tree

1 file changed

+21
-18
lines changed

1 file changed

+21
-18
lines changed

internal/webhooks/cluster.go

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -148,11 +148,12 @@ func (webhook *Cluster) ValidateDelete(_ context.Context, obj runtime.Object) er
148148

149149
func (webhook *Cluster) validate(ctx context.Context, oldCluster, newCluster *clusterv1.Cluster) error {
150150
var allErrs field.ErrorList
151+
specPath := field.NewPath("spec")
151152
if newCluster.Spec.InfrastructureRef != nil && newCluster.Spec.InfrastructureRef.Namespace != newCluster.Namespace {
152153
allErrs = append(
153154
allErrs,
154155
field.Invalid(
155-
field.NewPath("spec", "infrastructureRef", "namespace"),
156+
specPath.Child("infrastructureRef", "namespace"),
156157
newCluster.Spec.InfrastructureRef.Namespace,
157158
"must match metadata.namespace",
158159
),
@@ -163,24 +164,25 @@ func (webhook *Cluster) validate(ctx context.Context, oldCluster, newCluster *cl
163164
allErrs = append(
164165
allErrs,
165166
field.Invalid(
166-
field.NewPath("spec", "controlPlaneRef", "namespace"),
167+
specPath.Child("controlPlaneRef", "namespace"),
167168
newCluster.Spec.ControlPlaneRef.Namespace,
168169
"must match metadata.namespace",
169170
),
170171
)
171172
}
173+
topologyPath := specPath.Child("topology")
172174

173175
// Validate the managed topology, if defined.
174176
if newCluster.Spec.Topology != nil {
175-
allErrs = append(allErrs, webhook.validateTopology(ctx, oldCluster, newCluster)...)
177+
allErrs = append(allErrs, webhook.validateTopology(ctx, oldCluster, newCluster, topologyPath)...)
176178
}
177179

178180
// On update.
179181
if oldCluster != nil {
180182
// Error if the update moves the cluster from Managed to Unmanaged i.e. the managed topology is removed on update.
181183
if oldCluster.Spec.Topology != nil && newCluster.Spec.Topology == nil {
182184
allErrs = append(allErrs, field.Forbidden(
183-
field.NewPath("spec", "topology"),
185+
topologyPath,
184186
"cannot be removed from an existing Cluster",
185187
))
186188
}
@@ -192,13 +194,13 @@ func (webhook *Cluster) validate(ctx context.Context, oldCluster, newCluster *cl
192194
return nil
193195
}
194196

195-
func (webhook *Cluster) validateTopology(ctx context.Context, oldCluster, newCluster *clusterv1.Cluster) field.ErrorList {
197+
func (webhook *Cluster) validateTopology(ctx context.Context, oldCluster, newCluster *clusterv1.Cluster, fldPath *field.Path) field.ErrorList {
196198
// NOTE: ClusterClass and managed topologies are behind ClusterTopology feature gate flag; the web hook
197199
// must prevent the usage of Cluster.Topology in case the feature flag is disabled.
198200
if !feature.Gates.Enabled(feature.ClusterTopology) {
199201
return field.ErrorList{
200202
field.Forbidden(
201-
field.NewPath("spec", "topology"),
203+
fldPath,
202204
"can be set only if the ClusterTopology feature flag is enabled",
203205
),
204206
}
@@ -211,7 +213,7 @@ func (webhook *Cluster) validateTopology(ctx context.Context, oldCluster, newClu
211213
allErrs = append(
212214
allErrs,
213215
field.Required(
214-
field.NewPath("spec", "topology", "class"),
216+
fldPath.Child("class"),
215217
"class cannot be empty",
216218
),
217219
)
@@ -222,7 +224,7 @@ func (webhook *Cluster) validateTopology(ctx context.Context, oldCluster, newClu
222224
allErrs = append(
223225
allErrs,
224226
field.Invalid(
225-
field.NewPath("spec", "topology", "version"),
227+
fldPath.Child("version"),
226228
newCluster.Spec.Topology.Version,
227229
"version must be a valid semantic version",
228230
),
@@ -235,7 +237,7 @@ func (webhook *Cluster) validateTopology(ctx context.Context, oldCluster, newClu
235237
if err := webhook.Client.Get(ctx, client.ObjectKey{Namespace: newCluster.Namespace, Name: newCluster.Spec.Topology.Class}, clusterClass); err != nil {
236238
allErrs = append(
237239
allErrs, field.Invalid(
238-
field.NewPath("spec", "topology", "class"),
240+
fldPath.Child("class"),
239241
newCluster.Name,
240242
fmt.Sprintf("ClusterClass with name %q could not be found", newCluster.Spec.Topology.Class)))
241243
return allErrs
@@ -245,7 +247,7 @@ func (webhook *Cluster) validateTopology(ctx context.Context, oldCluster, newClu
245247

246248
// Check if the variables defined in the ClusterClass are valid.
247249
allErrs = append(allErrs, variables.ValidateClusterVariables(newCluster.Spec.Topology.Variables, clusterClass.Spec.Variables,
248-
field.NewPath("spec", "topology", "variables"))...)
250+
fldPath.Child("variables"))...)
249251

250252
if newCluster.Spec.Topology.Workers != nil {
251253
for i, md := range newCluster.Spec.Topology.Workers.MachineDeployments {
@@ -255,9 +257,10 @@ func (webhook *Cluster) validateTopology(ctx context.Context, oldCluster, newClu
255257
}
256258

257259
allErrs = append(allErrs, variables.ValidateTopLevelClusterVariablesExist(md.Variables.Overrides, newCluster.Spec.Topology.Variables,
258-
field.NewPath("spec", "topology", "workers", "machineDeployments").Index(i).Child("variables", "overrides"))...)
260+
fldPath.Child("workers", "machineDeployments").Index(i).Child("variables", "overrides"))...)
261+
259262
allErrs = append(allErrs, variables.ValidateMachineDeploymentVariables(md.Variables.Overrides, clusterClass.Spec.Variables,
260-
field.NewPath("spec", "topology", "workers", "machineDeployments").Index(i).Child("variables", "overrides"))...)
263+
fldPath.Child("workers", "machineDeployments").Index(i).Child("variables", "overrides"))...)
261264
}
262265
}
263266

@@ -267,7 +270,7 @@ func (webhook *Cluster) validateTopology(ctx context.Context, oldCluster, newClu
267270
allErrs = append(
268271
allErrs,
269272
field.Forbidden(
270-
field.NewPath("spec", "topology", "class"),
273+
fldPath.Child("class"),
271274
"class cannot be set on an existing Cluster",
272275
),
273276
)
@@ -281,7 +284,7 @@ func (webhook *Cluster) validateTopology(ctx context.Context, oldCluster, newClu
281284
allErrs = append(
282285
allErrs,
283286
field.Invalid(
284-
field.NewPath("spec", "topology", "version"),
287+
fldPath.Child("version"),
285288
newCluster.Spec.Topology.Version,
286289
"version must be a valid semantic version",
287290
),
@@ -293,7 +296,7 @@ func (webhook *Cluster) validateTopology(ctx context.Context, oldCluster, newClu
293296
allErrs = append(
294297
allErrs,
295298
field.Invalid(
296-
field.NewPath("spec", "topology", "version"),
299+
fldPath.Child("version"),
297300
oldCluster.Spec.Topology.Version,
298301
fmt.Sprintf("old version %q cannot be compared with %q", oldVersion, inVersion),
299302
),
@@ -303,7 +306,7 @@ func (webhook *Cluster) validateTopology(ctx context.Context, oldCluster, newClu
303306
allErrs = append(
304307
allErrs,
305308
field.Invalid(
306-
field.NewPath("spec", "topology", "version"),
309+
fldPath.Child("version"),
307310
newCluster.Spec.Topology.Version,
308311
fmt.Sprintf("version cannot be decreased from %q to %q", oldVersion, inVersion),
309312
),
@@ -319,7 +322,7 @@ func (webhook *Cluster) validateTopology(ctx context.Context, oldCluster, newClu
319322
allErrs = append(
320323
allErrs,
321324
field.Forbidden(
322-
field.NewPath("spec", "topology", "version"),
325+
fldPath.Child("version"),
323326
fmt.Sprintf("version cannot be increased from %q to %q", oldVersion, inVersion),
324327
),
325328
)
@@ -332,7 +335,7 @@ func (webhook *Cluster) validateTopology(ctx context.Context, oldCluster, newClu
332335
if err != nil {
333336
allErrs = append(
334337
allErrs, field.Forbidden(
335-
field.NewPath("spec", "topology", "class"),
338+
fldPath.Child("class"),
336339
fmt.Sprintf("ClusterClass with name %q could not be found, change from class %[1]q to class %q cannot be validated",
337340
oldCluster.Spec.Topology.Class, newCluster.Spec.Topology.Class)))
338341

0 commit comments

Comments
 (0)