Skip to content

Commit 2fcf418

Browse files
committed
drop crd api fields
1 parent 111d4ea commit 2fcf418

File tree

4 files changed

+590
-92
lines changed

4 files changed

+590
-92
lines changed

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

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -196,18 +196,8 @@ func ValidateCustomResourceDefinitionSpec(spec *apiextensions.CustomResourceDefi
196196
}
197197

198198
allErrs = append(allErrs, ValidateCustomResourceDefinitionNames(&spec.Names, fldPath.Child("names"))...)
199-
200-
if utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceValidation) {
201-
allErrs = append(allErrs, ValidateCustomResourceDefinitionValidation(spec.Validation, hasAnyStatusEnabled(spec), fldPath.Child("validation"))...)
202-
} else if spec.Validation != nil {
203-
allErrs = append(allErrs, field.Forbidden(fldPath.Child("validation"), "disabled by feature-gate CustomResourceValidation"))
204-
}
205-
206-
if utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceSubresources) {
207-
allErrs = append(allErrs, ValidateCustomResourceDefinitionSubresources(spec.Subresources, fldPath.Child("subresources"))...)
208-
} else if spec.Subresources != nil {
209-
allErrs = append(allErrs, field.Forbidden(fldPath.Child("subresources"), "disabled by feature-gate CustomResourceSubresources"))
210-
}
199+
allErrs = append(allErrs, ValidateCustomResourceDefinitionValidation(spec.Validation, hasAnyStatusEnabled(spec), fldPath.Child("validation"))...)
200+
allErrs = append(allErrs, ValidateCustomResourceDefinitionSubresources(spec.Subresources, fldPath.Child("subresources"))...)
211201

212202
for i := range spec.AdditionalPrinterColumns {
213203
if errs := ValidateCustomResourceColumnDefinition(&spec.AdditionalPrinterColumns[i], fldPath.Child("additionalPrinterColumns").Index(i)); len(errs) > 0 {
@@ -481,7 +471,7 @@ func ValidateCustomResourceDefinitionValidation(customResourceValidation *apiext
481471
if schema := customResourceValidation.OpenAPIV3Schema; schema != nil {
482472
// if the status subresource is enabled, only certain fields are allowed inside the root schema.
483473
// these fields are chosen such that, if status is extracted as properties["status"], it's validation is not lost.
484-
if utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceSubresources) && statusSubresourceEnabled {
474+
if statusSubresourceEnabled {
485475
v := reflect.ValueOf(schema).Elem()
486476
for i := 0; i < v.NumField(); i++ {
487477
// skip zero values

staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresourcedefinition/BUILD

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
package(default_visibility = ["//visibility:public"])
22

3-
load(
4-
"@io_bazel_rules_go//go:def.bzl",
5-
"go_library",
6-
)
3+
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
74

85
go_library(
96
name = "go_default_library",
@@ -47,3 +44,16 @@ filegroup(
4744
srcs = [":package-srcs"],
4845
tags = ["automanaged"],
4946
)
47+
48+
go_test(
49+
name = "go_default_test",
50+
srcs = ["strategy_test.go"],
51+
embed = [":go_default_library"],
52+
deps = [
53+
"//staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions:go_default_library",
54+
"//staging/src/k8s.io/apiextensions-apiserver/pkg/features:go_default_library",
55+
"//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library",
56+
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
57+
"//staging/src/k8s.io/apiserver/pkg/util/feature/testing:go_default_library",
58+
],
59+
)

staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresourcedefinition/strategy.go

Lines changed: 101 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -54,32 +54,7 @@ func (strategy) PrepareForCreate(ctx context.Context, obj runtime.Object) {
5454
crd.Status = apiextensions.CustomResourceDefinitionStatus{}
5555
crd.Generation = 1
5656

57-
// if the feature gate is disabled, drop the feature.
58-
if !utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceValidation) {
59-
crd.Spec.Validation = nil
60-
for i := range crd.Spec.Versions {
61-
crd.Spec.Versions[i].Schema = nil
62-
}
63-
}
64-
if !utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceSubresources) {
65-
crd.Spec.Subresources = nil
66-
for i := range crd.Spec.Versions {
67-
crd.Spec.Versions[i].Subresources = nil
68-
}
69-
}
70-
// On CREATE, if the CustomResourceWebhookConversion feature gate is off, we auto-clear
71-
// the per-version fields. This is to be consistent with the other built-in types, as the
72-
// apiserver drops unknown fields.
73-
if !utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceWebhookConversion) {
74-
for i := range crd.Spec.Versions {
75-
crd.Spec.Versions[i].Schema = nil
76-
crd.Spec.Versions[i].Subresources = nil
77-
crd.Spec.Versions[i].AdditionalPrinterColumns = nil
78-
}
79-
}
80-
if !utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceWebhookConversion) && crd.Spec.Conversion != nil {
81-
crd.Spec.Conversion.WebhookClientConfig = nil
82-
}
57+
dropDisabledFields(&crd.Spec, nil)
8358

8459
for _, v := range crd.Spec.Versions {
8560
if v.Storage {
@@ -109,45 +84,7 @@ func (strategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) {
10984
newCRD.Generation = oldCRD.Generation + 1
11085
}
11186

112-
if !utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceValidation) {
113-
newCRD.Spec.Validation = nil
114-
oldCRD.Spec.Validation = nil
115-
for i := range newCRD.Spec.Versions {
116-
newCRD.Spec.Versions[i].Schema = nil
117-
}
118-
for i := range oldCRD.Spec.Versions {
119-
oldCRD.Spec.Versions[i].Schema = nil
120-
}
121-
}
122-
if !utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceSubresources) {
123-
newCRD.Spec.Subresources = nil
124-
oldCRD.Spec.Subresources = nil
125-
for i := range newCRD.Spec.Versions {
126-
newCRD.Spec.Versions[i].Subresources = nil
127-
}
128-
for i := range oldCRD.Spec.Versions {
129-
oldCRD.Spec.Versions[i].Subresources = nil
130-
}
131-
}
132-
133-
// On UPDATE, if the CustomResourceWebhookConversion feature gate is off, we auto-clear
134-
// the per-version fields if the old CRD doesn't use per-version fields already.
135-
// This is to be consistent with the other built-in types, as the apiserver drops unknown
136-
// fields. If the old CRD already uses per-version fields, the CRD is allowed to continue
137-
// use per-version fields.
138-
if !utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceWebhookConversion) &&
139-
!hasPerVersionField(oldCRD.Spec.Versions) {
140-
for i := range newCRD.Spec.Versions {
141-
newCRD.Spec.Versions[i].Schema = nil
142-
newCRD.Spec.Versions[i].Subresources = nil
143-
newCRD.Spec.Versions[i].AdditionalPrinterColumns = nil
144-
}
145-
}
146-
if !utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceWebhookConversion) && newCRD.Spec.Conversion != nil {
147-
if oldCRD.Spec.Conversion == nil || newCRD.Spec.Conversion.WebhookClientConfig == nil {
148-
newCRD.Spec.Conversion.WebhookClientConfig = nil
149-
}
150-
}
87+
dropDisabledFields(&newCRD.Spec, &oldCRD.Spec)
15188

15289
for _, v := range newCRD.Spec.Versions {
15390
if v.Storage {
@@ -159,16 +96,6 @@ func (strategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) {
15996
}
16097
}
16198

162-
// hasPerVersionField returns true if a CRD uses per-version schema/subresources/columns fields.
163-
func hasPerVersionField(versions []apiextensions.CustomResourceDefinitionVersion) bool {
164-
for _, v := range versions {
165-
if v.Schema != nil || v.Subresources != nil || len(v.AdditionalPrinterColumns) > 0 {
166-
return true
167-
}
168-
}
169-
return false
170-
}
171-
17299
// Validate validates a new CustomResourceDefinition.
173100
func (strategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList {
174101
return validation.ValidateCustomResourceDefinition(obj.(*apiextensions.CustomResourceDefinition))
@@ -259,3 +186,102 @@ func MatchCustomResourceDefinition(label labels.Selector, field fields.Selector)
259186
func CustomResourceDefinitionToSelectableFields(obj *apiextensions.CustomResourceDefinition) fields.Set {
260187
return generic.ObjectMetaFieldsSet(&obj.ObjectMeta, true)
261188
}
189+
190+
func dropDisabledFields(crdSpec, oldCrdSpec *apiextensions.CustomResourceDefinitionSpec) {
191+
// if the feature gate is disabled, drop the feature.
192+
if !utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceValidation) &&
193+
!validationInUse(oldCrdSpec) {
194+
crdSpec.Validation = nil
195+
for i := range crdSpec.Versions {
196+
crdSpec.Versions[i].Schema = nil
197+
}
198+
}
199+
if !utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceSubresources) &&
200+
!subresourceInUse(oldCrdSpec) {
201+
crdSpec.Subresources = nil
202+
for i := range crdSpec.Versions {
203+
crdSpec.Versions[i].Subresources = nil
204+
}
205+
}
206+
207+
// 1. On CREATE (in which case the old CRD spec is nil), if the CustomResourceWebhookConversion feature gate is off, we auto-clear
208+
// the per-version fields. This is to be consistent with the other built-in types, as the
209+
// apiserver drops unknown fields.
210+
// 2. On UPDATE, if the CustomResourceWebhookConversion feature gate is off, we auto-clear
211+
// the per-version fields if the old CRD doesn't use per-version fields already.
212+
// This is to be consistent with the other built-in types, as the apiserver drops unknown
213+
// fields. If the old CRD already uses per-version fields, the CRD is allowed to continue
214+
// use per-version fields.
215+
if !utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceWebhookConversion) &&
216+
!hasPerVersionField(oldCrdSpec) {
217+
for i := range crdSpec.Versions {
218+
crdSpec.Versions[i].Schema = nil
219+
crdSpec.Versions[i].Subresources = nil
220+
crdSpec.Versions[i].AdditionalPrinterColumns = nil
221+
}
222+
}
223+
224+
if !utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceWebhookConversion) &&
225+
!conversionWebhookInUse(oldCrdSpec) {
226+
if crdSpec.Conversion != nil {
227+
crdSpec.Conversion.WebhookClientConfig = nil
228+
}
229+
}
230+
231+
}
232+
233+
func validationInUse(crdSpec *apiextensions.CustomResourceDefinitionSpec) bool {
234+
if crdSpec == nil {
235+
return false
236+
}
237+
if crdSpec.Validation != nil {
238+
return true
239+
}
240+
241+
for i := range crdSpec.Versions {
242+
if crdSpec.Versions[i].Schema != nil {
243+
return true
244+
}
245+
}
246+
return false
247+
}
248+
249+
func subresourceInUse(crdSpec *apiextensions.CustomResourceDefinitionSpec) bool {
250+
if crdSpec == nil {
251+
return false
252+
}
253+
if crdSpec.Subresources != nil {
254+
return true
255+
}
256+
257+
for i := range crdSpec.Versions {
258+
if crdSpec.Versions[i].Subresources != nil {
259+
return true
260+
}
261+
}
262+
return false
263+
}
264+
265+
// hasPerVersionField returns true if a CRD uses per-version schema/subresources/columns fields.
266+
//func hasPerVersionField(versions []apiextensions.CustomResourceDefinitionVersion) bool {
267+
func hasPerVersionField(crdSpec *apiextensions.CustomResourceDefinitionSpec) bool {
268+
if crdSpec == nil {
269+
return false
270+
}
271+
for _, v := range crdSpec.Versions {
272+
if v.Schema != nil || v.Subresources != nil || len(v.AdditionalPrinterColumns) > 0 {
273+
return true
274+
}
275+
}
276+
return false
277+
}
278+
279+
func conversionWebhookInUse(crdSpec *apiextensions.CustomResourceDefinitionSpec) bool {
280+
if crdSpec == nil {
281+
return false
282+
}
283+
if crdSpec.Conversion == nil {
284+
return false
285+
}
286+
return crdSpec.Conversion.WebhookClientConfig != nil
287+
}

0 commit comments

Comments
 (0)