Skip to content

Commit d014591

Browse files
committed
apiextensions: forbid false x-kubernetes-preserve-unknown-fields
1 parent 6897c68 commit d014591

File tree

11 files changed

+83
-9
lines changed

11 files changed

+83
-9
lines changed

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,5 +258,15 @@ func (in *JSONSchemaProps) DeepCopy() *JSONSchemaProps {
258258
}
259259
}
260260

261+
if in.XPreserveUnknownFields != nil {
262+
in, out := &in.XPreserveUnknownFields, &out.XPreserveUnknownFields
263+
if *in == nil {
264+
*out = nil
265+
} else {
266+
*out = new(bool)
267+
**out = **in
268+
}
269+
}
270+
261271
return out
262272
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ type JSONSchemaProps struct {
6161
// in the validation schema. This affects fields recursively,
6262
// but switches back to normal pruning behaviour if nested
6363
// properties or additionalProperties are specified in the schema.
64-
XPreserveUnknownFields bool
64+
// This can either be true or undefined. False is forbidden.
65+
XPreserveUnknownFields *bool
6566

6667
// x-kubernetes-embedded-resource defines that the value is an
6768
// embedded Kubernetes runtime.Object, with TypeMeta and

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,5 +234,15 @@ func (in *JSONSchemaProps) DeepCopy() *JSONSchemaProps {
234234
}
235235
}
236236

237+
if in.XPreserveUnknownFields != nil {
238+
in, out := &in.XPreserveUnknownFields, &out.XPreserveUnknownFields
239+
if *in == nil {
240+
*out = nil
241+
} else {
242+
*out = new(bool)
243+
**out = **in
244+
}
245+
}
246+
237247
return out
238248
}

staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/generated.proto

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ type JSONSchemaProps struct {
6161
// in the validation schema. This affects fields recursively,
6262
// but switches back to normal pruning behaviour if nested
6363
// properties or additionalProperties are specified in the schema.
64-
XPreserveUnknownFields bool `json:"x-kubernetes-preserve-unknown-fields,omitempty" protobuf:"bytes,38,opt,name=xKubernetesPreserveUnknownFields"`
64+
// This can either be true or undefined. False is forbidden.
65+
XPreserveUnknownFields *bool `json:"x-kubernetes-preserve-unknown-fields,omitempty" protobuf:"bytes,38,opt,name=xKubernetesPreserveUnknownFields"`
6566

6667
// x-kubernetes-embedded-resource defines that the value is an
6768
// embedded Kubernetes runtime.Object, with TypeMeta and

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ go_test(
3434
"//staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions:go_default_library",
3535
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
3636
"//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
37+
"//vendor/k8s.io/utils/pointer:go_default_library",
3738
],
3839
)
3940

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -673,6 +673,10 @@ func ValidateCustomResourceDefinitionOpenAPISchema(schema *apiextensions.JSONSch
673673
}
674674
}
675675

676+
if schema.XPreserveUnknownFields != nil && *schema.XPreserveUnknownFields == false {
677+
allErrs = append(allErrs, field.Invalid(fldPath.Child("x-kubernetes-preserve-unknown-fields"), *schema.XPreserveUnknownFields, "must be true or undefined"))
678+
}
679+
676680
return allErrs
677681
}
678682

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

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
2323
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2424
"k8s.io/apimachinery/pkg/util/validation/field"
25+
"k8s.io/utils/pointer"
2526
)
2627

2728
type validationMatch struct {
@@ -935,6 +936,41 @@ func TestValidateCustomResourceDefinition(t *testing.T) {
935936
invalid("spec", "versions"),
936937
},
937938
},
939+
{
940+
name: "x-kubernetes-preserve-unknown-field: false",
941+
resource: &apiextensions.CustomResourceDefinition{
942+
ObjectMeta: metav1.ObjectMeta{Name: "plural.group.com"},
943+
Spec: apiextensions.CustomResourceDefinitionSpec{
944+
Group: "group.com",
945+
Version: "version",
946+
Validation: &apiextensions.CustomResourceValidation{
947+
OpenAPIV3Schema: &apiextensions.JSONSchemaProps{
948+
XPreserveUnknownFields: pointer.BoolPtr(false),
949+
},
950+
},
951+
Versions: []apiextensions.CustomResourceDefinitionVersion{
952+
{
953+
Name: "version",
954+
Served: true,
955+
Storage: true,
956+
},
957+
},
958+
Scope: apiextensions.NamespaceScoped,
959+
Names: apiextensions.CustomResourceDefinitionNames{
960+
Plural: "plural",
961+
Singular: "singular",
962+
Kind: "Plural",
963+
ListKind: "PluralList",
964+
},
965+
},
966+
Status: apiextensions.CustomResourceDefinitionStatus{
967+
StoredVersions: []string{"version"},
968+
},
969+
},
970+
errors: []validationMatch{
971+
invalid("spec", "validation", "openAPIV3Schema", "x-kubernetes-preserve-unknown-fields"),
972+
},
973+
},
938974
}
939975

940976
for _, tc := range tests {

staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/schema/convert.go

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -241,11 +241,19 @@ func newExtensions(s *apiextensions.JSONSchemaProps) (*Extensions, error) {
241241
return nil, nil
242242
}
243243

244-
return &Extensions{
245-
XPreserveUnknownFields: s.XPreserveUnknownFields,
246-
XEmbeddedResource: s.XEmbeddedResource,
247-
XIntOrString: s.XIntOrString,
248-
}, nil
244+
ret := &Extensions{
245+
XEmbeddedResource: s.XEmbeddedResource,
246+
XIntOrString: s.XIntOrString,
247+
}
248+
249+
if s.XPreserveUnknownFields != nil {
250+
if !*s.XPreserveUnknownFields {
251+
return nil, fmt.Errorf("'x-kubernetes-preserve-unknown-fields' must be true or undefined")
252+
}
253+
ret.XPreserveUnknownFields = true
254+
}
255+
256+
return ret, nil
249257
}
250258

251259
// validateUnsupportedFields checks that those fields rejected by validation are actually unset.

staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/schema/structural.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ type Extensions struct {
6666
// in the validation schema. This affects fields recursively,
6767
// but switches back to normal pruning behaviour if nested
6868
// properties or additionalProperties are specified in the schema.
69+
// False means that the pruning behaviour is inherited from the parent.
70+
// False does not mean to activate pruning.
6971
XPreserveUnknownFields bool
7072

7173
// x-kubernetes-embedded-resource defines that the value is an

0 commit comments

Comments
 (0)