Skip to content

Commit 7f61ab8

Browse files
authored
Merge pull request kubernetes#91928 from liggitt/bug/clarify-apiext-error-message
Give a reason when rejecting defaulting in CRDs
2 parents 418c2cb + 7c448e3 commit 7f61ab8

File tree

2 files changed

+21
-9
lines changed

2 files changed

+21
-9
lines changed

staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation/validation.go

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,10 @@ func ValidateCustomResourceDefinition(obj *apiextensions.CustomResourceDefinitio
5555
return ret
5656
}
5757

58+
allowDefaults, rejectDefaultsReason := allowDefaults(requestGV, nil)
5859
opts := validationOptions{
59-
allowDefaults: allowDefaults(requestGV, nil),
60+
allowDefaults: allowDefaults,
61+
disallowDefaultsReason: rejectDefaultsReason,
6062
requireRecognizedConversionReviewVersion: true,
6163
requireImmutableNames: false,
6264
requireOpenAPISchema: requireOpenAPISchema(requestGV, nil),
@@ -80,6 +82,8 @@ func ValidateCustomResourceDefinition(obj *apiextensions.CustomResourceDefinitio
8082
type validationOptions struct {
8183
// allowDefaults permits the validation schema to contain default attributes
8284
allowDefaults bool
85+
// disallowDefaultsReason gives a reason as to why allowDefaults is false (for better user feedback)
86+
disallowDefaultsReason string
8387
// requireRecognizedConversionReviewVersion requires accepted webhook conversion versions to contain a recognized version
8488
requireRecognizedConversionReviewVersion bool
8589
// requireImmutableNames disables changing spec.names
@@ -102,8 +106,10 @@ type validationOptions struct {
102106

103107
// ValidateCustomResourceDefinitionUpdate statically validates
104108
func ValidateCustomResourceDefinitionUpdate(obj, oldObj *apiextensions.CustomResourceDefinition, requestGV schema.GroupVersion) field.ErrorList {
109+
allowDefaults, rejectDefaultsReason := allowDefaults(requestGV, &oldObj.Spec)
105110
opts := validationOptions{
106-
allowDefaults: allowDefaults(requestGV, &oldObj.Spec),
111+
allowDefaults: allowDefaults,
112+
disallowDefaultsReason: rejectDefaultsReason,
107113
requireRecognizedConversionReviewVersion: oldObj.Spec.Conversion == nil || hasValidConversionReviewVersionOrEmpty(oldObj.Spec.Conversion.ConversionReviewVersions),
108114
requireImmutableNames: apiextensions.IsCRDConditionTrue(oldObj, apiextensions.Established),
109115
requireOpenAPISchema: requireOpenAPISchema(requestGV, &oldObj.Spec),
@@ -661,6 +667,7 @@ func validateCustomResourceDefinitionValidation(customResourceValidation *apiext
661667

662668
openAPIV3Schema := &specStandardValidatorV3{
663669
allowDefaults: opts.allowDefaults,
670+
disallowDefaultsReason: opts.disallowDefaultsReason,
664671
requireValidPropertyType: opts.requireValidPropertyType,
665672
}
666673

@@ -1110,16 +1117,17 @@ func allVersionsSpecifyOpenAPISchema(spec *apiextensions.CustomResourceDefinitio
11101117
return true
11111118
}
11121119

1113-
// allowDefaults returns true if the defaulting feature is enabled and the request group version allows adding defaults
1114-
func allowDefaults(requestGV schema.GroupVersion, oldCRDSpec *apiextensions.CustomResourceDefinitionSpec) bool {
1120+
// allowDefaults returns true if the defaulting feature is enabled and the request group version allows adding defaults,
1121+
// or false and a reason for the user if defaults are not allowed.
1122+
func allowDefaults(requestGV schema.GroupVersion, oldCRDSpec *apiextensions.CustomResourceDefinitionSpec) (bool, string) {
11151123
if oldCRDSpec != nil && specHasDefaults(oldCRDSpec) {
11161124
// don't tighten validation on existing persisted data
1117-
return true
1125+
return true, ""
11181126
}
11191127
if requestGV == apiextensionsv1beta1.SchemeGroupVersion {
1120-
return false
1128+
return false, "(cannot set default values in apiextensions.k8s.io/v1beta1 CRDs, must use apiextensions.k8s.io/v1)"
11211129
}
1122-
return true
1130+
return true, ""
11231131
}
11241132

11251133
func specHasDefaults(spec *apiextensions.CustomResourceDefinitionSpec) bool {

staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation/validation_test.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import (
3838
type validationMatch struct {
3939
path *field.Path
4040
errorType field.ErrorType
41+
contains string
4142
}
4243

4344
func required(path ...string) validationMatch {
@@ -58,9 +59,12 @@ func immutable(path ...string) validationMatch {
5859
func forbidden(path ...string) validationMatch {
5960
return validationMatch{path: field.NewPath(path[0], path[1:]...), errorType: field.ErrorTypeForbidden}
6061
}
62+
func forbiddenContains(contains string, path ...string) validationMatch {
63+
return validationMatch{path: field.NewPath(path[0], path[1:]...), errorType: field.ErrorTypeForbidden, contains: contains}
64+
}
6165

6266
func (v validationMatch) matches(err *field.Error) bool {
63-
return err.Type == v.errorType && err.Field == v.path.String()
67+
return err.Type == v.errorType && err.Field == v.path.String() && strings.Contains(err.Error(), v.contains)
6468
}
6569

6670
func strPtr(s string) *string { return &s }
@@ -1641,7 +1645,7 @@ func TestValidateCustomResourceDefinition(t *testing.T) {
16411645
},
16421646
requestGV: apiextensionsv1beta1.SchemeGroupVersion,
16431647
errors: []validationMatch{
1644-
forbidden("spec", "validation", "openAPIV3Schema", "properties[a]", "default"), // disallowed via v1beta1
1648+
forbiddenContains("cannot set default values in apiextensions.k8s.io/v1beta1", "spec", "validation", "openAPIV3Schema", "properties[a]", "default"), // disallowed via v1beta1
16451649
},
16461650
},
16471651
{

0 commit comments

Comments
 (0)