Merge pull request #81965 from roycaihw/crd-feature-gates-to-ga

Bump the CRD feature gates to GA
This commit is contained in:
Kubernetes Prow Robot 2019-08-28 14:44:44 -07:00 committed by GitHub
commit f3828b776b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 298 additions and 418 deletions

View File

@ -575,10 +575,10 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS
// inherited features from apiextensions-apiserver, relisted here to get a conflict if it is changed // inherited features from apiextensions-apiserver, relisted here to get a conflict if it is changed
// unintentionally on either side: // unintentionally on either side:
apiextensionsfeatures.CustomResourceValidation: {Default: true, PreRelease: featuregate.Beta}, apiextensionsfeatures.CustomResourceValidation: {Default: true, PreRelease: featuregate.GA, LockToDefault: true},
apiextensionsfeatures.CustomResourceSubresources: {Default: true, PreRelease: featuregate.Beta}, apiextensionsfeatures.CustomResourceSubresources: {Default: true, PreRelease: featuregate.GA, LockToDefault: true},
apiextensionsfeatures.CustomResourceWebhookConversion: {Default: true, PreRelease: featuregate.Beta}, apiextensionsfeatures.CustomResourceWebhookConversion: {Default: true, PreRelease: featuregate.GA, LockToDefault: true},
apiextensionsfeatures.CustomResourcePublishOpenAPI: {Default: true, PreRelease: featuregate.Beta}, apiextensionsfeatures.CustomResourcePublishOpenAPI: {Default: true, PreRelease: featuregate.GA, LockToDefault: true},
apiextensionsfeatures.CustomResourceDefaulting: {Default: true, PreRelease: featuregate.Beta}, apiextensionsfeatures.CustomResourceDefaulting: {Default: true, PreRelease: featuregate.Beta},
// features that enable backwards compatibility but are scheduled to be removed // features that enable backwards compatibility but are scheduled to be removed

View File

@ -31,12 +31,15 @@ const (
// owner: @sttts, @nikhita // owner: @sttts, @nikhita
// alpha: v1.8 // alpha: v1.8
// beta: v1.9 // beta: v1.9
// GA: v1.16
// //
// CustomResourceValidation is a list of validation methods for CustomResources // CustomResourceValidation is a list of validation methods for CustomResources
CustomResourceValidation featuregate.Feature = "CustomResourceValidation" CustomResourceValidation featuregate.Feature = "CustomResourceValidation"
// owner: @roycaihw, @sttts // owner: @roycaihw, @sttts
// alpha: v1.14 // alpha: v1.14
// beta: v1.15
// GA: v1.16
// //
// CustomResourcePublishOpenAPI enables publishing of CRD OpenAPI specs. // CustomResourcePublishOpenAPI enables publishing of CRD OpenAPI specs.
CustomResourcePublishOpenAPI featuregate.Feature = "CustomResourcePublishOpenAPI" CustomResourcePublishOpenAPI featuregate.Feature = "CustomResourcePublishOpenAPI"
@ -44,12 +47,15 @@ const (
// owner: @sttts, @nikhita // owner: @sttts, @nikhita
// alpha: v1.10 // alpha: v1.10
// beta: v1.11 // beta: v1.11
// GA: v1.16
// //
// CustomResourceSubresources defines the subresources for CustomResources // CustomResourceSubresources defines the subresources for CustomResources
CustomResourceSubresources featuregate.Feature = "CustomResourceSubresources" CustomResourceSubresources featuregate.Feature = "CustomResourceSubresources"
// owner: @mbohlool, @roycaihw // owner: @mbohlool, @roycaihw
// alpha: v1.13 // alpha: v1.13
// beta: v1.15
// GA: v1.16
// //
// CustomResourceWebhookConversion defines the webhook conversion for Custom Resources. // CustomResourceWebhookConversion defines the webhook conversion for Custom Resources.
CustomResourceWebhookConversion featuregate.Feature = "CustomResourceWebhookConversion" CustomResourceWebhookConversion featuregate.Feature = "CustomResourceWebhookConversion"
@ -69,9 +75,9 @@ func init() {
// To add a new feature, define a key for it above and add it here. The features will be // To add a new feature, define a key for it above and add it here. The features will be
// available throughout Kubernetes binaries. // available throughout Kubernetes binaries.
var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureSpec{ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureSpec{
CustomResourceValidation: {Default: true, PreRelease: featuregate.Beta}, CustomResourceValidation: {Default: true, PreRelease: featuregate.GA, LockToDefault: true},
CustomResourceSubresources: {Default: true, PreRelease: featuregate.Beta}, CustomResourceSubresources: {Default: true, PreRelease: featuregate.GA, LockToDefault: true},
CustomResourceWebhookConversion: {Default: true, PreRelease: featuregate.Beta}, CustomResourceWebhookConversion: {Default: true, PreRelease: featuregate.GA, LockToDefault: true},
CustomResourcePublishOpenAPI: {Default: true, PreRelease: featuregate.Beta}, CustomResourcePublishOpenAPI: {Default: true, PreRelease: featuregate.GA, LockToDefault: true},
CustomResourceDefaulting: {Default: true, PreRelease: featuregate.Beta}, CustomResourceDefaulting: {Default: true, PreRelease: featuregate.Beta},
} }

View File

@ -55,13 +55,10 @@ go_test(
"//staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions:go_default_library", "//staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions:go_default_library",
"//staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1:go_default_library", "//staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1:go_default_library",
"//staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation:go_default_library", "//staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation:go_default_library",
"//staging/src/k8s.io/apiextensions-apiserver/pkg/features:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
"//staging/src/k8s.io/component-base/featuregate/testing:go_default_library",
"//vendor/k8s.io/utils/pointer:go_default_library", "//vendor/k8s.io/utils/pointer:go_default_library",
], ],
) )

View File

@ -24,19 +24,15 @@ import (
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation"
apiextensionsfeatures "k8s.io/apiextensions-apiserver/pkg/features"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/diff" "k8s.io/apimachinery/pkg/util/diff"
"k8s.io/apimachinery/pkg/util/validation/field" "k8s.io/apimachinery/pkg/util/validation/field"
utilfeature "k8s.io/apiserver/pkg/util/feature"
featuregatetesting "k8s.io/component-base/featuregate/testing"
"k8s.io/utils/pointer" "k8s.io/utils/pointer"
) )
func TestDropDisableFieldsCustomResourceDefinition(t *testing.T) { func TestDropDisableFieldsCustomResourceDefinition(t *testing.T) {
t.Log("testing unversioned validation..") t.Log("testing unversioned validation..")
for _, validationEnabled := range []bool{true, false} {
crdWithUnversionedValidation := func() *apiextensions.CustomResourceDefinition { crdWithUnversionedValidation := func() *apiextensions.CustomResourceDefinition {
// crd with non-versioned validation // crd with non-versioned validation
return &apiextensions.CustomResourceDefinition{ return &apiextensions.CustomResourceDefinition{
@ -55,35 +51,30 @@ func TestDropDisableFieldsCustomResourceDefinition(t *testing.T) {
} }
crdInfos := []struct { crdInfos := []struct {
name string name string
hasCRValidation bool
crd func() *apiextensions.CustomResourceDefinition crd func() *apiextensions.CustomResourceDefinition
}{ }{
{ {
name: "has unversioned validation", name: "has unversioned validation",
hasCRValidation: true,
crd: crdWithUnversionedValidation, crd: crdWithUnversionedValidation,
}, },
{ {
name: "doesn't have unversioned validation", name: "doesn't have unversioned validation",
hasCRValidation: false,
crd: crdWithoutUnversionedValidation, crd: crdWithoutUnversionedValidation,
}, },
{ {
name: "nil", name: "nil",
hasCRValidation: false,
crd: func() *apiextensions.CustomResourceDefinition { return nil }, crd: func() *apiextensions.CustomResourceDefinition { return nil },
}, },
} }
for _, oldCRDInfo := range crdInfos { for _, oldCRDInfo := range crdInfos {
for _, newCRDInfo := range crdInfos { for _, newCRDInfo := range crdInfos {
oldCRDHasValidation, oldCRD := oldCRDInfo.hasCRValidation, oldCRDInfo.crd() oldCRD := oldCRDInfo.crd()
newCRDHasValidation, newCRD := newCRDInfo.hasCRValidation, newCRDInfo.crd() newCRD := newCRDInfo.crd()
if newCRD == nil { if newCRD == nil {
continue continue
} }
t.Run(fmt.Sprintf("validation feature enabled=%v, old CRD %v, new CRD %v", validationEnabled, oldCRDInfo.name, newCRDInfo.name), t.Run(fmt.Sprintf("old CRD %v, new CRD %v", oldCRDInfo.name, newCRDInfo.name),
func(t *testing.T) { func(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, apiextensionsfeatures.CustomResourceValidation, validationEnabled)()
var oldCRDSpec *apiextensions.CustomResourceDefinitionSpec var oldCRDSpec *apiextensions.CustomResourceDefinitionSpec
if oldCRD != nil { if oldCRD != nil {
oldCRDSpec = &oldCRD.Spec oldCRDSpec = &oldCRD.Spec
@ -93,31 +84,15 @@ func TestDropDisableFieldsCustomResourceDefinition(t *testing.T) {
if !reflect.DeepEqual(oldCRD, oldCRDInfo.crd()) { if !reflect.DeepEqual(oldCRD, oldCRDInfo.crd()) {
t.Errorf("old crd changed: %v", diff.ObjectReflectDiff(oldCRD, oldCRDInfo.crd())) t.Errorf("old crd changed: %v", diff.ObjectReflectDiff(oldCRD, oldCRDInfo.crd()))
} }
switch {
case validationEnabled || oldCRDHasValidation:
if !reflect.DeepEqual(newCRD, newCRDInfo.crd()) { if !reflect.DeepEqual(newCRD, newCRDInfo.crd()) {
t.Errorf("new crd changed: %v", diff.ObjectReflectDiff(newCRD, newCRDInfo.crd())) t.Errorf("new crd changed: %v", diff.ObjectReflectDiff(newCRD, newCRDInfo.crd()))
} }
case newCRDHasValidation:
if reflect.DeepEqual(newCRD, newCRDInfo.crd()) {
t.Errorf("new crd was not changed")
}
if !reflect.DeepEqual(newCRD, crdWithoutUnversionedValidation()) {
t.Errorf("new crd had unversioned validation: %v", diff.ObjectReflectDiff(newCRD, crdWithoutUnversionedValidation()))
}
default:
if !reflect.DeepEqual(newCRD, newCRDInfo.crd()) {
t.Errorf("new crd changed: %v", diff.ObjectReflectDiff(newCRD, newCRDInfo.crd()))
}
}
}, },
) )
} }
} }
}
t.Log("testing unversioned subresources...") t.Log("testing unversioned subresources...")
for _, validationEnabled := range []bool{true, false} {
crdWithUnversionedSubresources := func() *apiextensions.CustomResourceDefinition { crdWithUnversionedSubresources := func() *apiextensions.CustomResourceDefinition {
// crd with unversioned subresources // crd with unversioned subresources
return &apiextensions.CustomResourceDefinition{ return &apiextensions.CustomResourceDefinition{
@ -132,37 +107,32 @@ func TestDropDisableFieldsCustomResourceDefinition(t *testing.T) {
Spec: apiextensions.CustomResourceDefinitionSpec{}, Spec: apiextensions.CustomResourceDefinitionSpec{},
} }
} }
crdInfos := []struct { crdInfos = []struct {
name string name string
hasCRSubresources bool
crd func() *apiextensions.CustomResourceDefinition crd func() *apiextensions.CustomResourceDefinition
}{ }{
{ {
name: "has unversioned subresources", name: "has unversioned subresources",
hasCRSubresources: true,
crd: crdWithUnversionedSubresources, crd: crdWithUnversionedSubresources,
}, },
{ {
name: "doesn't have unversioned subresources", name: "doesn't have unversioned subresources",
hasCRSubresources: false,
crd: crdWithoutUnversionedSubresources, crd: crdWithoutUnversionedSubresources,
}, },
{ {
name: "nil", name: "nil",
hasCRSubresources: false,
crd: func() *apiextensions.CustomResourceDefinition { return nil }, crd: func() *apiextensions.CustomResourceDefinition { return nil },
}, },
} }
for _, oldCRDInfo := range crdInfos { for _, oldCRDInfo := range crdInfos {
for _, newCRDInfo := range crdInfos { for _, newCRDInfo := range crdInfos {
oldCRDHasSubresources, oldCRD := oldCRDInfo.hasCRSubresources, oldCRDInfo.crd() oldCRD := oldCRDInfo.crd()
newCRDHasSubresources, newCRD := newCRDInfo.hasCRSubresources, newCRDInfo.crd() newCRD := newCRDInfo.crd()
if newCRD == nil { if newCRD == nil {
continue continue
} }
t.Run(fmt.Sprintf("subresources feature enabled=%v, old CRD %v, new CRD %v", validationEnabled, oldCRDInfo.name, newCRDInfo.name), t.Run(fmt.Sprintf("old CRD %v, new CRD %v", oldCRDInfo.name, newCRDInfo.name),
func(t *testing.T) { func(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, apiextensionsfeatures.CustomResourceSubresources, validationEnabled)()
var oldCRDSpec *apiextensions.CustomResourceDefinitionSpec var oldCRDSpec *apiextensions.CustomResourceDefinitionSpec
if oldCRD != nil { if oldCRD != nil {
oldCRDSpec = &oldCRD.Spec oldCRDSpec = &oldCRD.Spec
@ -172,32 +142,15 @@ func TestDropDisableFieldsCustomResourceDefinition(t *testing.T) {
if !reflect.DeepEqual(oldCRD, oldCRDInfo.crd()) { if !reflect.DeepEqual(oldCRD, oldCRDInfo.crd()) {
t.Errorf("old crd changed: %v", diff.ObjectReflectDiff(oldCRD, oldCRDInfo.crd())) t.Errorf("old crd changed: %v", diff.ObjectReflectDiff(oldCRD, oldCRDInfo.crd()))
} }
switch {
case validationEnabled || oldCRDHasSubresources:
if !reflect.DeepEqual(newCRD, newCRDInfo.crd()) { if !reflect.DeepEqual(newCRD, newCRDInfo.crd()) {
t.Errorf("new crd changed: %v", diff.ObjectReflectDiff(newCRD, newCRDInfo.crd())) t.Errorf("new crd changed: %v", diff.ObjectReflectDiff(newCRD, newCRDInfo.crd()))
} }
case newCRDHasSubresources:
if reflect.DeepEqual(newCRD, newCRDInfo.crd()) {
t.Errorf("new crd was not changed")
}
if !reflect.DeepEqual(newCRD, crdWithoutUnversionedSubresources()) {
t.Errorf("new crd had unversioned subresources: %v", diff.ObjectReflectDiff(newCRD, crdWithoutUnversionedSubresources()))
}
default:
if !reflect.DeepEqual(newCRD, newCRDInfo.crd()) {
t.Errorf("new crd changed: %v", diff.ObjectReflectDiff(newCRD, newCRDInfo.crd()))
}
}
}, },
) )
} }
} }
}
t.Log("testing versioned validation..") t.Log("testing versioned validation..")
for _, conversionEnabled := range []bool{true, false} {
for _, validationEnabled := range []bool{true, false} {
crdWithVersionedValidation := func() *apiextensions.CustomResourceDefinition { crdWithVersionedValidation := func() *apiextensions.CustomResourceDefinition {
// crd with versioned validation // crd with versioned validation
return &apiextensions.CustomResourceDefinition{ return &apiextensions.CustomResourceDefinition{
@ -225,38 +178,32 @@ func TestDropDisableFieldsCustomResourceDefinition(t *testing.T) {
}, },
} }
} }
crdInfos := []struct { crdInfos = []struct {
name string name string
hasCRValidation bool
crd func() *apiextensions.CustomResourceDefinition crd func() *apiextensions.CustomResourceDefinition
}{ }{
{ {
name: "has versioned validation", name: "has versioned validation",
hasCRValidation: true,
crd: crdWithVersionedValidation, crd: crdWithVersionedValidation,
}, },
{ {
name: "doesn't have versioned validation", name: "doesn't have versioned validation",
hasCRValidation: false,
crd: crdWithoutVersionedValidation, crd: crdWithoutVersionedValidation,
}, },
{ {
name: "nil", name: "nil",
hasCRValidation: false,
crd: func() *apiextensions.CustomResourceDefinition { return nil }, crd: func() *apiextensions.CustomResourceDefinition { return nil },
}, },
} }
for _, oldCRDInfo := range crdInfos { for _, oldCRDInfo := range crdInfos {
for _, newCRDInfo := range crdInfos { for _, newCRDInfo := range crdInfos {
oldCRDHasValidation, oldCRD := oldCRDInfo.hasCRValidation, oldCRDInfo.crd() oldCRD := oldCRDInfo.crd()
newCRDHasValidation, newCRD := newCRDInfo.hasCRValidation, newCRDInfo.crd() newCRD := newCRDInfo.crd()
if newCRD == nil { if newCRD == nil {
continue continue
} }
t.Run(fmt.Sprintf("validation feature enabled=%v, old CRD %v, new CRD %v", validationEnabled, oldCRDInfo.name, newCRDInfo.name), t.Run(fmt.Sprintf("old CRD %v, new CRD %v", oldCRDInfo.name, newCRDInfo.name),
func(t *testing.T) { func(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, apiextensionsfeatures.CustomResourceValidation, validationEnabled)()
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, apiextensionsfeatures.CustomResourceWebhookConversion, conversionEnabled)()
var oldCRDSpec *apiextensions.CustomResourceDefinitionSpec var oldCRDSpec *apiextensions.CustomResourceDefinitionSpec
if oldCRD != nil { if oldCRD != nil {
oldCRDSpec = &oldCRD.Spec oldCRDSpec = &oldCRD.Spec
@ -266,37 +213,15 @@ func TestDropDisableFieldsCustomResourceDefinition(t *testing.T) {
if !reflect.DeepEqual(oldCRD, oldCRDInfo.crd()) { if !reflect.DeepEqual(oldCRD, oldCRDInfo.crd()) {
t.Errorf("old crd changed: %v", diff.ObjectReflectDiff(oldCRD, oldCRDInfo.crd())) t.Errorf("old crd changed: %v", diff.ObjectReflectDiff(oldCRD, oldCRDInfo.crd()))
} }
switch {
case (conversionEnabled && validationEnabled) || oldCRDHasValidation:
if !reflect.DeepEqual(newCRD, newCRDInfo.crd()) { if !reflect.DeepEqual(newCRD, newCRDInfo.crd()) {
t.Errorf("new crd changed: %v", diff.ObjectReflectDiff(newCRD, newCRDInfo.crd())) t.Errorf("new crd changed: %v", diff.ObjectReflectDiff(newCRD, newCRDInfo.crd()))
} }
case !conversionEnabled && !oldCRDHasValidation:
if !reflect.DeepEqual(newCRD, crdWithoutVersionedValidation()) {
t.Errorf("new crd was not changed")
}
case newCRDHasValidation:
if reflect.DeepEqual(newCRD, newCRDInfo.crd()) {
t.Errorf("new crd was not changed")
}
if !reflect.DeepEqual(newCRD, crdWithoutVersionedValidation()) {
t.Errorf("new crd had unversioned validation: %v", diff.ObjectReflectDiff(newCRD, crdWithoutVersionedValidation()))
}
default:
if !reflect.DeepEqual(newCRD, newCRDInfo.crd()) {
t.Errorf("new crd changed: %v", diff.ObjectReflectDiff(newCRD, newCRDInfo.crd()))
}
}
}, },
) )
} }
} }
}
}
t.Log("testing versioned subresources w/ conversion enabled..") t.Log("testing versioned subresources w/ conversion enabled..")
for _, conversionEnabled := range []bool{true, false} {
for _, validationEnabled := range []bool{true, false} {
crdWithVersionedSubresources := func() *apiextensions.CustomResourceDefinition { crdWithVersionedSubresources := func() *apiextensions.CustomResourceDefinition {
// crd with versioned subresources // crd with versioned subresources
return &apiextensions.CustomResourceDefinition{ return &apiextensions.CustomResourceDefinition{
@ -322,38 +247,32 @@ func TestDropDisableFieldsCustomResourceDefinition(t *testing.T) {
}, },
} }
} }
crdInfos := []struct { crdInfos = []struct {
name string name string
hasCRSubresources bool
crd func() *apiextensions.CustomResourceDefinition crd func() *apiextensions.CustomResourceDefinition
}{ }{
{ {
name: "has versioned subresources", name: "has versioned subresources",
hasCRSubresources: true,
crd: crdWithVersionedSubresources, crd: crdWithVersionedSubresources,
}, },
{ {
name: "doesn't have versioned subresources", name: "doesn't have versioned subresources",
hasCRSubresources: false,
crd: crdWithoutVersionedSubresources, crd: crdWithoutVersionedSubresources,
}, },
{ {
name: "nil", name: "nil",
hasCRSubresources: false,
crd: func() *apiextensions.CustomResourceDefinition { return nil }, crd: func() *apiextensions.CustomResourceDefinition { return nil },
}, },
} }
for _, oldCRDInfo := range crdInfos { for _, oldCRDInfo := range crdInfos {
for _, newCRDInfo := range crdInfos { for _, newCRDInfo := range crdInfos {
oldCRDHasSubresources, oldCRD := oldCRDInfo.hasCRSubresources, oldCRDInfo.crd() oldCRD := oldCRDInfo.crd()
newCRDHasSubresources, newCRD := newCRDInfo.hasCRSubresources, newCRDInfo.crd() newCRD := newCRDInfo.crd()
if newCRD == nil { if newCRD == nil {
continue continue
} }
t.Run(fmt.Sprintf("subresources feature enabled=%v, old CRD %v, new CRD %v", validationEnabled, oldCRDInfo.name, newCRDInfo.name), t.Run(fmt.Sprintf("old CRD %v, new CRD %v", oldCRDInfo.name, newCRDInfo.name),
func(t *testing.T) { func(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, apiextensionsfeatures.CustomResourceSubresources, validationEnabled)()
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, apiextensionsfeatures.CustomResourceWebhookConversion, conversionEnabled)()
var oldCRDSpec *apiextensions.CustomResourceDefinitionSpec var oldCRDSpec *apiextensions.CustomResourceDefinitionSpec
if oldCRD != nil { if oldCRD != nil {
oldCRDSpec = &oldCRD.Spec oldCRDSpec = &oldCRD.Spec
@ -363,36 +282,15 @@ func TestDropDisableFieldsCustomResourceDefinition(t *testing.T) {
if !reflect.DeepEqual(oldCRD, oldCRDInfo.crd()) { if !reflect.DeepEqual(oldCRD, oldCRDInfo.crd()) {
t.Errorf("old crd changed: %v", diff.ObjectReflectDiff(oldCRD, oldCRDInfo.crd())) t.Errorf("old crd changed: %v", diff.ObjectReflectDiff(oldCRD, oldCRDInfo.crd()))
} }
switch {
case (conversionEnabled && validationEnabled) || oldCRDHasSubresources:
if !reflect.DeepEqual(newCRD, newCRDInfo.crd()) { if !reflect.DeepEqual(newCRD, newCRDInfo.crd()) {
t.Errorf("new crd changed: %v", diff.ObjectReflectDiff(newCRD, newCRDInfo.crd())) t.Errorf("new crd changed: %v", diff.ObjectReflectDiff(newCRD, newCRDInfo.crd()))
} }
case !conversionEnabled && !oldCRDHasSubresources:
if !reflect.DeepEqual(newCRD, crdWithoutVersionedSubresources()) {
t.Errorf("new crd was not changed")
}
case newCRDHasSubresources:
if reflect.DeepEqual(newCRD, newCRDInfo.crd()) {
t.Errorf("new crd was not changed")
}
if !reflect.DeepEqual(newCRD, crdWithoutVersionedSubresources()) {
t.Errorf("new crd had versioned subresources: %v", diff.ObjectReflectDiff(newCRD, crdWithoutVersionedSubresources()))
}
default:
if !reflect.DeepEqual(newCRD, newCRDInfo.crd()) {
t.Errorf("new crd changed: %v", diff.ObjectReflectDiff(newCRD, newCRDInfo.crd()))
}
}
}, },
) )
} }
} }
}
}
t.Log("testing conversion webhook..") t.Log("testing conversion webhook..")
for _, validationEnabled := range []bool{true, false} {
crdWithUnversionedConversionWebhook := func() *apiextensions.CustomResourceDefinition { crdWithUnversionedConversionWebhook := func() *apiextensions.CustomResourceDefinition {
// crd with conversion webhook // crd with conversion webhook
return &apiextensions.CustomResourceDefinition{ return &apiextensions.CustomResourceDefinition{
@ -411,37 +309,32 @@ func TestDropDisableFieldsCustomResourceDefinition(t *testing.T) {
}, },
} }
} }
crdInfos := []struct { crdInfos = []struct {
name string name string
hasCRConversionWebhook bool
crd func() *apiextensions.CustomResourceDefinition crd func() *apiextensions.CustomResourceDefinition
}{ }{
{ {
name: "has conversion webhook", name: "has conversion webhook",
hasCRConversionWebhook: true,
crd: crdWithUnversionedConversionWebhook, crd: crdWithUnversionedConversionWebhook,
}, },
{ {
name: "doesn't have conversion webhook", name: "doesn't have conversion webhook",
hasCRConversionWebhook: false,
crd: crdWithoutUnversionedConversionWebhook, crd: crdWithoutUnversionedConversionWebhook,
}, },
{ {
name: "nil", name: "nil",
hasCRConversionWebhook: false,
crd: func() *apiextensions.CustomResourceDefinition { return nil }, crd: func() *apiextensions.CustomResourceDefinition { return nil },
}, },
} }
for _, oldCRDInfo := range crdInfos { for _, oldCRDInfo := range crdInfos {
for _, newCRDInfo := range crdInfos { for _, newCRDInfo := range crdInfos {
oldCRDHasConversionWebhook, oldCRD := oldCRDInfo.hasCRConversionWebhook, oldCRDInfo.crd() oldCRD := oldCRDInfo.crd()
newCRDHasConversionWebhook, newCRD := newCRDInfo.hasCRConversionWebhook, newCRDInfo.crd() newCRD := newCRDInfo.crd()
if newCRD == nil { if newCRD == nil {
continue continue
} }
t.Run(fmt.Sprintf("subresources feature enabled=%v, old CRD %v, new CRD %v", validationEnabled, oldCRDInfo.name, newCRDInfo.name), t.Run(fmt.Sprintf("old CRD %v, new CRD %v", oldCRDInfo.name, newCRDInfo.name),
func(t *testing.T) { func(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, apiextensionsfeatures.CustomResourceWebhookConversion, validationEnabled)()
var oldCRDSpec *apiextensions.CustomResourceDefinitionSpec var oldCRDSpec *apiextensions.CustomResourceDefinitionSpec
if oldCRD != nil { if oldCRD != nil {
oldCRDSpec = &oldCRD.Spec oldCRDSpec = &oldCRD.Spec
@ -451,29 +344,13 @@ func TestDropDisableFieldsCustomResourceDefinition(t *testing.T) {
if !reflect.DeepEqual(oldCRD, oldCRDInfo.crd()) { if !reflect.DeepEqual(oldCRD, oldCRDInfo.crd()) {
t.Errorf("old crd changed: %v", diff.ObjectReflectDiff(oldCRD, oldCRDInfo.crd())) t.Errorf("old crd changed: %v", diff.ObjectReflectDiff(oldCRD, oldCRDInfo.crd()))
} }
switch {
case validationEnabled || oldCRDHasConversionWebhook:
if !reflect.DeepEqual(newCRD, newCRDInfo.crd()) { if !reflect.DeepEqual(newCRD, newCRDInfo.crd()) {
t.Errorf("new crd changed: %v", diff.ObjectReflectDiff(newCRD, newCRDInfo.crd())) t.Errorf("new crd changed: %v", diff.ObjectReflectDiff(newCRD, newCRDInfo.crd()))
} }
case newCRDHasConversionWebhook:
if reflect.DeepEqual(newCRD, newCRDInfo.crd()) {
t.Errorf("new crd was not changed")
}
if !reflect.DeepEqual(newCRD, crdWithoutUnversionedConversionWebhook()) {
t.Errorf("new crd had webhook conversion: %v", diff.ObjectReflectDiff(newCRD, crdWithoutUnversionedConversionWebhook()))
}
default:
if !reflect.DeepEqual(newCRD, newCRDInfo.crd()) {
t.Errorf("new crd changed: %v", diff.ObjectReflectDiff(newCRD, newCRDInfo.crd()))
}
}
}, },
) )
} }
} }
}
} }
func strPtr(in string) *string { func strPtr(in string) *string {