Skip to content

Commit ffc9943

Browse files
authored
Merge pull request #6129 from sbueringer/pr-improve-kcp-validation
🌱 KCP: improve validation webhooks
2 parents 338ed6b + 7a02662 commit ffc9943

File tree

5 files changed

+51
-28
lines changed

5 files changed

+51
-28
lines changed

bootstrap/kubeadm/api/v1beta1/kubeadmconfig_webhook.go

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ func (c *KubeadmConfig) ValidateDelete() error {
7979
}
8080

8181
func (c *KubeadmConfigSpec) validate(name string) error {
82-
allErrs := c.Validate()
82+
allErrs := c.Validate(field.NewPath("spec"))
8383

8484
if len(allErrs) == 0 {
8585
return nil
@@ -89,16 +89,16 @@ func (c *KubeadmConfigSpec) validate(name string) error {
8989
}
9090

9191
// Validate ensures the KubeadmConfigSpec is valid.
92-
func (c *KubeadmConfigSpec) Validate() field.ErrorList {
92+
func (c *KubeadmConfigSpec) Validate(pathPrefix *field.Path) field.ErrorList {
9393
var allErrs field.ErrorList
9494

95-
allErrs = append(allErrs, c.validateFiles()...)
96-
allErrs = append(allErrs, c.validateIgnition()...)
95+
allErrs = append(allErrs, c.validateFiles(pathPrefix)...)
96+
allErrs = append(allErrs, c.validateIgnition(pathPrefix)...)
9797

9898
return allErrs
9999
}
100100

101-
func (c *KubeadmConfigSpec) validateFiles() field.ErrorList {
101+
func (c *KubeadmConfigSpec) validateFiles(pathPrefix *field.Path) field.ErrorList {
102102
var allErrs field.ErrorList
103103

104104
knownPaths := map[string]struct{}{}
@@ -109,7 +109,7 @@ func (c *KubeadmConfigSpec) validateFiles() field.ErrorList {
109109
allErrs = append(
110110
allErrs,
111111
field.Invalid(
112-
field.NewPath("spec", "files").Index(i),
112+
pathPrefix.Child("files").Index(i),
113113
file,
114114
conflictingFileSourceMsg,
115115
),
@@ -122,19 +122,17 @@ func (c *KubeadmConfigSpec) validateFiles() field.ErrorList {
122122
if file.ContentFrom.Secret.Name == "" {
123123
allErrs = append(
124124
allErrs,
125-
field.Invalid(
126-
field.NewPath("spec", "files").Index(i).Child("contentFrom", "secret", "name"),
127-
file,
125+
field.Required(
126+
pathPrefix.Child("files").Index(i).Child("contentFrom", "secret", "name"),
128127
missingSecretNameMsg,
129128
),
130129
)
131130
}
132131
if file.ContentFrom.Secret.Key == "" {
133132
allErrs = append(
134133
allErrs,
135-
field.Invalid(
136-
field.NewPath("spec", "files").Index(i).Child("contentFrom", "secret", "key"),
137-
file,
134+
field.Required(
135+
pathPrefix.Child("files").Index(i).Child("contentFrom", "secret", "key"),
138136
missingSecretKeyMsg,
139137
),
140138
)
@@ -145,7 +143,7 @@ func (c *KubeadmConfigSpec) validateFiles() field.ErrorList {
145143
allErrs = append(
146144
allErrs,
147145
field.Invalid(
148-
field.NewPath("spec", "files").Index(i).Child("path"),
146+
pathPrefix.Child("files").Index(i).Child("path"),
149147
file,
150148
pathConflictMsg,
151149
),
@@ -157,18 +155,18 @@ func (c *KubeadmConfigSpec) validateFiles() field.ErrorList {
157155
return allErrs
158156
}
159157

160-
func (c *KubeadmConfigSpec) validateIgnition() field.ErrorList {
158+
func (c *KubeadmConfigSpec) validateIgnition(pathPrefix *field.Path) field.ErrorList {
161159
var allErrs field.ErrorList
162160

163161
if !feature.Gates.Enabled(feature.KubeadmBootstrapFormatIgnition) {
164162
if c.Format == Ignition {
165163
allErrs = append(allErrs, field.Forbidden(
166-
field.NewPath("spec", "format"), kubeadmBootstrapFormatIgnitionFeatureDisabledMsg))
164+
pathPrefix.Child("format"), kubeadmBootstrapFormatIgnitionFeatureDisabledMsg))
167165
}
168166

169167
if c.Ignition != nil {
170168
allErrs = append(allErrs, field.Forbidden(
171-
field.NewPath("spec", "ignition"), kubeadmBootstrapFormatIgnitionFeatureDisabledMsg))
169+
pathPrefix.Child("ignition"), kubeadmBootstrapFormatIgnitionFeatureDisabledMsg))
172170
}
173171

174172
return allErrs
@@ -179,7 +177,7 @@ func (c *KubeadmConfigSpec) validateIgnition() field.ErrorList {
179177
allErrs = append(
180178
allErrs,
181179
field.Invalid(
182-
field.NewPath("spec", "format"),
180+
pathPrefix.Child("format"),
183181
c.Format,
184182
fmt.Sprintf("must be set to %q if spec.ignition is set", Ignition),
185183
),
@@ -194,7 +192,7 @@ func (c *KubeadmConfigSpec) validateIgnition() field.ErrorList {
194192
allErrs = append(
195193
allErrs,
196194
field.Forbidden(
197-
field.NewPath("spec", "users").Index(i).Child("inactive"),
195+
pathPrefix.Child("users").Index(i).Child("inactive"),
198196
cannotUseWithIgnition,
199197
),
200198
)
@@ -205,7 +203,7 @@ func (c *KubeadmConfigSpec) validateIgnition() field.ErrorList {
205203
allErrs = append(
206204
allErrs,
207205
field.Forbidden(
208-
field.NewPath("spec", "useExperimentalRetryJoin"),
206+
pathPrefix.Child("useExperimentalRetryJoin"),
209207
cannotUseWithIgnition,
210208
),
211209
)
@@ -220,7 +218,7 @@ func (c *KubeadmConfigSpec) validateIgnition() field.ErrorList {
220218
allErrs = append(
221219
allErrs,
222220
field.Invalid(
223-
field.NewPath("spec", "diskSetup", "partitions").Index(i).Child("tableType"),
221+
pathPrefix.Child("diskSetup", "partitions").Index(i).Child("tableType"),
224222
*partition.TableType,
225223
fmt.Sprintf(
226224
"only partition type %q is supported when spec.format is set to %q",
@@ -237,7 +235,7 @@ func (c *KubeadmConfigSpec) validateIgnition() field.ErrorList {
237235
allErrs = append(
238236
allErrs,
239237
field.Forbidden(
240-
field.NewPath("spec", "diskSetup", "filesystems").Index(i).Child("replaceFS"),
238+
pathPrefix.Child("diskSetup", "filesystems").Index(i).Child("replaceFS"),
241239
cannotUseWithIgnition,
242240
),
243241
)
@@ -247,7 +245,7 @@ func (c *KubeadmConfigSpec) validateIgnition() field.ErrorList {
247245
allErrs = append(
248246
allErrs,
249247
field.Forbidden(
250-
field.NewPath("spec", "diskSetup", "filesystems").Index(i).Child("partition"),
248+
pathPrefix.Child("diskSetup", "filesystems").Index(i).Child("partition"),
251249
cannotUseWithIgnition,
252250
),
253251
)

bootstrap/kubeadm/api/v1beta1/kubeadmconfigtemplate_webhook.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ func (r *KubeadmConfigTemplate) ValidateDelete() error {
6161
func (r *KubeadmConfigTemplateSpec) validate(name string) error {
6262
var allErrs field.ErrorList
6363

64-
allErrs = append(allErrs, r.Template.Spec.Validate()...)
64+
allErrs = append(allErrs, r.Template.Spec.Validate(field.NewPath("spec", "template", "spec"))...)
6565

6666
if len(allErrs) == 0 {
6767
return nil

controlplane/kubeadm/api/v1beta1/kubeadm_control_plane_webhook.go

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ func (in *KubeadmControlPlane) ValidateCreate() error {
101101
spec := in.Spec
102102
allErrs := validateKubeadmControlPlaneSpec(spec, in.Namespace, field.NewPath("spec"))
103103
allErrs = append(allErrs, validateClusterConfiguration(spec.KubeadmConfigSpec.ClusterConfiguration, nil, field.NewPath("spec", "kubeadmConfigSpec", "clusterConfiguration"))...)
104-
allErrs = append(allErrs, in.Spec.KubeadmConfigSpec.Validate()...)
104+
allErrs = append(allErrs, spec.KubeadmConfigSpec.Validate(field.NewPath("spec", "kubeadmConfigSpec"))...)
105105
if len(allErrs) > 0 {
106106
return apierrors.NewInvalid(GroupVersion.WithKind("KubeadmControlPlane").GroupKind(), in.Name, allErrs)
107107
}
@@ -211,7 +211,7 @@ func (in *KubeadmControlPlane) ValidateUpdate(old runtime.Object) error {
211211
allErrs = append(allErrs, in.validateVersion(prev.Spec.Version)...)
212212
allErrs = append(allErrs, validateClusterConfiguration(in.Spec.KubeadmConfigSpec.ClusterConfiguration, prev.Spec.KubeadmConfigSpec.ClusterConfiguration, field.NewPath("spec", "kubeadmConfigSpec", "clusterConfiguration"))...)
213213
allErrs = append(allErrs, in.validateCoreDNSVersion(prev)...)
214-
allErrs = append(allErrs, in.Spec.KubeadmConfigSpec.Validate()...)
214+
allErrs = append(allErrs, in.Spec.KubeadmConfigSpec.Validate(field.NewPath("spec", "kubeadmConfigSpec"))...)
215215

216216
if len(allErrs) > 0 {
217217
return apierrors.NewInvalid(GroupVersion.WithKind("KubeadmControlPlane").GroupKind(), in.Name, allErrs)
@@ -374,6 +374,18 @@ func validateClusterConfiguration(newClusterConfiguration, oldClusterConfigurati
374374
)
375375
}
376376

377+
if newClusterConfiguration.DNS.ImageTag != "" {
378+
if _, err := version.ParseMajorMinorPatchTolerant(newClusterConfiguration.DNS.ImageTag); err != nil {
379+
allErrs = append(allErrs,
380+
field.Invalid(
381+
field.NewPath("dns", "imageTag"),
382+
newClusterConfiguration.DNS.ImageTag,
383+
fmt.Sprintf("failed to parse CoreDNS version: %v", err),
384+
),
385+
)
386+
}
387+
}
388+
377389
// TODO: Remove when kubeadm types include OpenAPI validation
378390
if newClusterConfiguration.Etcd.Local != nil && !container.ImageTagIsValid(newClusterConfiguration.Etcd.Local.ImageTag) {
379391
allErrs = append(
@@ -484,9 +496,10 @@ func (in *KubeadmControlPlane) validateCoreDNSVersion(prev *KubeadmControlPlane)
484496
fromVersion, err := version.ParseMajorMinorPatchTolerant(prev.Spec.KubeadmConfigSpec.ClusterConfiguration.DNS.ImageTag)
485497
if err != nil {
486498
allErrs = append(allErrs,
487-
field.InternalError(
499+
field.Invalid(
488500
field.NewPath("spec", "kubeadmConfigSpec", "clusterConfiguration", "dns", "imageTag"),
489-
fmt.Errorf("failed to parse CoreDNS current version: %v", prev.Spec.KubeadmConfigSpec.ClusterConfiguration.DNS.ImageTag),
501+
prev.Spec.KubeadmConfigSpec.ClusterConfiguration.DNS.ImageTag,
502+
fmt.Sprintf("failed to parse current CoreDNS version: %v", err),
490503
),
491504
)
492505
return allErrs
@@ -498,7 +511,7 @@ func (in *KubeadmControlPlane) validateCoreDNSVersion(prev *KubeadmControlPlane)
498511
field.Invalid(
499512
field.NewPath("spec", "kubeadmConfigSpec", "clusterConfiguration", "dns", "imageTag"),
500513
targetDNS.ImageTag,
501-
fmt.Sprintf("failed to parse CoreDNS target version: %v", targetDNS.ImageTag),
514+
fmt.Sprintf("failed to parse target CoreDNS version: %v", err),
502515
),
503516
)
504517
return allErrs

controlplane/kubeadm/api/v1beta1/kubeadm_control_plane_webhook_test.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,9 @@ func TestKubeadmControlPlaneValidateCreate(t *testing.T) {
8484
Name: "infraTemplate",
8585
},
8686
},
87+
KubeadmConfigSpec: bootstrapv1.KubeadmConfigSpec{
88+
ClusterConfiguration: &bootstrapv1.ClusterConfiguration{},
89+
},
8790
Replicas: pointer.Int32Ptr(1),
8891
Version: "v1.19.0",
8992
RolloutStrategy: &RolloutStrategy{
@@ -130,6 +133,9 @@ func TestKubeadmControlPlaneValidateCreate(t *testing.T) {
130133
invalidVersion2 := valid.DeepCopy()
131134
invalidVersion2.Spec.Version = "1.16.6"
132135

136+
invalidCoreDNSVersion := valid.DeepCopy()
137+
invalidCoreDNSVersion.Spec.KubeadmConfigSpec.ClusterConfiguration.DNS.ImageTag = "v1.7" // not a valid semantic version
138+
133139
invalidIgnitionConfiguration := valid.DeepCopy()
134140
invalidIgnitionConfiguration.Spec.KubeadmConfigSpec.Ignition = &bootstrapv1.IgnitionSpec{}
135141

@@ -188,6 +194,11 @@ func TestKubeadmControlPlaneValidateCreate(t *testing.T) {
188194
expectErr: true,
189195
kcp: invalidVersion1,
190196
},
197+
{
198+
name: "should return error when given an invalid semantic CoreDNS version",
199+
expectErr: true,
200+
kcp: invalidCoreDNSVersion,
201+
},
191202
{
192203
name: "should return error when maxSurge is not 1",
193204
expectErr: true,

controlplane/kubeadm/api/v1beta1/kubeadmcontrolplanetemplate_webhook.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ func (r *KubeadmControlPlaneTemplate) ValidateCreate() error {
6767
spec := r.Spec.Template.Spec
6868
allErrs := validateKubeadmControlPlaneTemplateResourceSpec(spec, field.NewPath("spec", "template", "spec"))
6969
allErrs = append(allErrs, validateClusterConfiguration(spec.KubeadmConfigSpec.ClusterConfiguration, nil, field.NewPath("spec", "template", "spec", "kubeadmConfigSpec", "clusterConfiguration"))...)
70+
allErrs = append(allErrs, spec.KubeadmConfigSpec.Validate(field.NewPath("spec", "template", "spec", "kubeadmConfigSpec"))...)
7071
if len(allErrs) > 0 {
7172
return apierrors.NewInvalid(GroupVersion.WithKind("KubeadmControlPlaneTemplate").GroupKind(), r.Name, allErrs)
7273
}

0 commit comments

Comments
 (0)