remove test cases disabling the gates

please review with whitespace change ignored (-w)
This commit is contained in:
Haowei Cai 2019-08-26 14:35:33 -07:00
parent 7997058d73
commit 6960bf9f4f

View File

@ -24,456 +24,333 @@ 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{ Spec: apiextensions.CustomResourceDefinitionSpec{
Spec: apiextensions.CustomResourceDefinitionSpec{ Validation: &apiextensions.CustomResourceValidation{
Validation: &apiextensions.CustomResourceValidation{ OpenAPIV3Schema: &apiextensions.JSONSchemaProps{},
OpenAPIV3Schema: &apiextensions.JSONSchemaProps{},
},
}, },
}
}
crdWithoutUnversionedValidation := func() *apiextensions.CustomResourceDefinition {
// crd with non-versioned validation
return &apiextensions.CustomResourceDefinition{
Spec: apiextensions.CustomResourceDefinitionSpec{},
}
}
crdInfos := []struct {
name string
hasCRValidation bool
crd func() *apiextensions.CustomResourceDefinition
}{
{
name: "has unversioned validation",
hasCRValidation: true,
crd: crdWithUnversionedValidation,
},
{
name: "doesn't have unversioned validation",
hasCRValidation: false,
crd: crdWithoutUnversionedValidation,
},
{
name: "nil",
hasCRValidation: false,
crd: func() *apiextensions.CustomResourceDefinition { return nil },
}, },
} }
for _, oldCRDInfo := range crdInfos { }
for _, newCRDInfo := range crdInfos { crdWithoutUnversionedValidation := func() *apiextensions.CustomResourceDefinition {
oldCRDHasValidation, oldCRD := oldCRDInfo.hasCRValidation, oldCRDInfo.crd() // crd with non-versioned validation
newCRDHasValidation, newCRD := newCRDInfo.hasCRValidation, newCRDInfo.crd() return &apiextensions.CustomResourceDefinition{
if newCRD == nil { Spec: apiextensions.CustomResourceDefinitionSpec{},
continue }
} }
t.Run(fmt.Sprintf("validation feature enabled=%v, old CRD %v, new CRD %v", validationEnabled, oldCRDInfo.name, newCRDInfo.name), crdInfos := []struct {
func(t *testing.T) { name string
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, apiextensionsfeatures.CustomResourceValidation, validationEnabled)() crd func() *apiextensions.CustomResourceDefinition
var oldCRDSpec *apiextensions.CustomResourceDefinitionSpec }{
if oldCRD != nil { {
oldCRDSpec = &oldCRD.Spec name: "has unversioned validation",
} crd: crdWithUnversionedValidation,
dropDisabledFields(&newCRD.Spec, oldCRDSpec) },
// old CRD should never be changed {
if !reflect.DeepEqual(oldCRD, oldCRDInfo.crd()) { name: "doesn't have unversioned validation",
t.Errorf("old crd changed: %v", diff.ObjectReflectDiff(oldCRD, oldCRDInfo.crd())) crd: crdWithoutUnversionedValidation,
} },
switch { {
case validationEnabled || oldCRDHasValidation: name: "nil",
if !reflect.DeepEqual(newCRD, newCRDInfo.crd()) { crd: func() *apiextensions.CustomResourceDefinition { return nil },
t.Errorf("new crd changed: %v", diff.ObjectReflectDiff(newCRD, newCRDInfo.crd())) },
} }
case newCRDHasValidation: for _, oldCRDInfo := range crdInfos {
if reflect.DeepEqual(newCRD, newCRDInfo.crd()) { for _, newCRDInfo := range crdInfos {
t.Errorf("new crd was not changed") oldCRD := oldCRDInfo.crd()
} newCRD := newCRDInfo.crd()
if !reflect.DeepEqual(newCRD, crdWithoutUnversionedValidation()) { if newCRD == nil {
t.Errorf("new crd had unversioned validation: %v", diff.ObjectReflectDiff(newCRD, crdWithoutUnversionedValidation())) continue
}
default:
if !reflect.DeepEqual(newCRD, newCRDInfo.crd()) {
t.Errorf("new crd changed: %v", diff.ObjectReflectDiff(newCRD, newCRDInfo.crd()))
}
}
},
)
} }
t.Run(fmt.Sprintf("old CRD %v, new CRD %v", oldCRDInfo.name, newCRDInfo.name),
func(t *testing.T) {
var oldCRDSpec *apiextensions.CustomResourceDefinitionSpec
if oldCRD != nil {
oldCRDSpec = &oldCRD.Spec
}
dropDisabledFields(&newCRD.Spec, oldCRDSpec)
// old CRD should never be changed
if !reflect.DeepEqual(oldCRD, oldCRDInfo.crd()) {
t.Errorf("old crd changed: %v", diff.ObjectReflectDiff(oldCRD, oldCRDInfo.crd()))
}
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{ Spec: apiextensions.CustomResourceDefinitionSpec{
Spec: apiextensions.CustomResourceDefinitionSpec{ Subresources: &apiextensions.CustomResourceSubresources{},
Subresources: &apiextensions.CustomResourceSubresources{}, },
}
}
crdWithoutUnversionedSubresources := func() *apiextensions.CustomResourceDefinition {
// crd without unversioned subresources
return &apiextensions.CustomResourceDefinition{
Spec: apiextensions.CustomResourceDefinitionSpec{},
}
}
crdInfos = []struct {
name string
crd func() *apiextensions.CustomResourceDefinition
}{
{
name: "has unversioned subresources",
crd: crdWithUnversionedSubresources,
},
{
name: "doesn't have unversioned subresources",
crd: crdWithoutUnversionedSubresources,
},
{
name: "nil",
crd: func() *apiextensions.CustomResourceDefinition { return nil },
},
}
for _, oldCRDInfo := range crdInfos {
for _, newCRDInfo := range crdInfos {
oldCRD := oldCRDInfo.crd()
newCRD := newCRDInfo.crd()
if newCRD == nil {
continue
}
t.Run(fmt.Sprintf("old CRD %v, new CRD %v", oldCRDInfo.name, newCRDInfo.name),
func(t *testing.T) {
var oldCRDSpec *apiextensions.CustomResourceDefinitionSpec
if oldCRD != nil {
oldCRDSpec = &oldCRD.Spec
}
dropDisabledFields(&newCRD.Spec, oldCRDSpec)
// old CRD should never be changed
if !reflect.DeepEqual(oldCRD, oldCRDInfo.crd()) {
t.Errorf("old crd changed: %v", diff.ObjectReflectDiff(oldCRD, oldCRDInfo.crd()))
}
if !reflect.DeepEqual(newCRD, newCRDInfo.crd()) {
t.Errorf("new crd changed: %v", diff.ObjectReflectDiff(newCRD, newCRDInfo.crd()))
}
}, },
} )
}
crdWithoutUnversionedSubresources := func() *apiextensions.CustomResourceDefinition {
// crd without unversioned subresources
return &apiextensions.CustomResourceDefinition{
Spec: apiextensions.CustomResourceDefinitionSpec{},
}
}
crdInfos := []struct {
name string
hasCRSubresources bool
crd func() *apiextensions.CustomResourceDefinition
}{
{
name: "has unversioned subresources",
hasCRSubresources: true,
crd: crdWithUnversionedSubresources,
},
{
name: "doesn't have unversioned subresources",
hasCRSubresources: false,
crd: crdWithoutUnversionedSubresources,
},
{
name: "nil",
hasCRSubresources: false,
crd: func() *apiextensions.CustomResourceDefinition { return nil },
},
}
for _, oldCRDInfo := range crdInfos {
for _, newCRDInfo := range crdInfos {
oldCRDHasSubresources, oldCRD := oldCRDInfo.hasCRSubresources, oldCRDInfo.crd()
newCRDHasSubresources, newCRD := newCRDInfo.hasCRSubresources, newCRDInfo.crd()
if newCRD == nil {
continue
}
t.Run(fmt.Sprintf("subresources feature enabled=%v, old CRD %v, new CRD %v", validationEnabled, oldCRDInfo.name, newCRDInfo.name),
func(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, apiextensionsfeatures.CustomResourceSubresources, validationEnabled)()
var oldCRDSpec *apiextensions.CustomResourceDefinitionSpec
if oldCRD != nil {
oldCRDSpec = &oldCRD.Spec
}
dropDisabledFields(&newCRD.Spec, oldCRDSpec)
// old CRD should never be changed
if !reflect.DeepEqual(oldCRD, oldCRDInfo.crd()) {
t.Errorf("old crd changed: %v", diff.ObjectReflectDiff(oldCRD, oldCRDInfo.crd()))
}
switch {
case validationEnabled || oldCRDHasSubresources:
if !reflect.DeepEqual(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} { crdWithVersionedValidation := func() *apiextensions.CustomResourceDefinition {
for _, validationEnabled := range []bool{true, false} { // crd with versioned validation
crdWithVersionedValidation := func() *apiextensions.CustomResourceDefinition { return &apiextensions.CustomResourceDefinition{
// crd with versioned validation Spec: apiextensions.CustomResourceDefinitionSpec{
return &apiextensions.CustomResourceDefinition{ Versions: []apiextensions.CustomResourceDefinitionVersion{
Spec: apiextensions.CustomResourceDefinitionSpec{ {
Versions: []apiextensions.CustomResourceDefinitionVersion{ Name: "v1",
{ Schema: &apiextensions.CustomResourceValidation{
Name: "v1", OpenAPIV3Schema: &apiextensions.JSONSchemaProps{},
Schema: &apiextensions.CustomResourceValidation{
OpenAPIV3Schema: &apiextensions.JSONSchemaProps{},
},
},
}, },
}, },
} },
} },
crdWithoutVersionedValidation := func() *apiextensions.CustomResourceDefinition { }
// crd with versioned validation }
return &apiextensions.CustomResourceDefinition{ crdWithoutVersionedValidation := func() *apiextensions.CustomResourceDefinition {
Spec: apiextensions.CustomResourceDefinitionSpec{ // crd with versioned validation
Versions: []apiextensions.CustomResourceDefinitionVersion{ return &apiextensions.CustomResourceDefinition{
{ Spec: apiextensions.CustomResourceDefinitionSpec{
Name: "v1", Versions: []apiextensions.CustomResourceDefinitionVersion{
}, {
}, Name: "v1",
}, },
} },
},
}
}
crdInfos = []struct {
name string
crd func() *apiextensions.CustomResourceDefinition
}{
{
name: "has versioned validation",
crd: crdWithVersionedValidation,
},
{
name: "doesn't have versioned validation",
crd: crdWithoutVersionedValidation,
},
{
name: "nil",
crd: func() *apiextensions.CustomResourceDefinition { return nil },
},
}
for _, oldCRDInfo := range crdInfos {
for _, newCRDInfo := range crdInfos {
oldCRD := oldCRDInfo.crd()
newCRD := newCRDInfo.crd()
if newCRD == nil {
continue
} }
crdInfos := []struct { t.Run(fmt.Sprintf("old CRD %v, new CRD %v", oldCRDInfo.name, newCRDInfo.name),
name string func(t *testing.T) {
hasCRValidation bool var oldCRDSpec *apiextensions.CustomResourceDefinitionSpec
crd func() *apiextensions.CustomResourceDefinition if oldCRD != nil {
}{ oldCRDSpec = &oldCRD.Spec
{
name: "has versioned validation",
hasCRValidation: true,
crd: crdWithVersionedValidation,
},
{
name: "doesn't have versioned validation",
hasCRValidation: false,
crd: crdWithoutVersionedValidation,
},
{
name: "nil",
hasCRValidation: false,
crd: func() *apiextensions.CustomResourceDefinition { return nil },
},
}
for _, oldCRDInfo := range crdInfos {
for _, newCRDInfo := range crdInfos {
oldCRDHasValidation, oldCRD := oldCRDInfo.hasCRValidation, oldCRDInfo.crd()
newCRDHasValidation, newCRD := newCRDInfo.hasCRValidation, newCRDInfo.crd()
if newCRD == nil {
continue
} }
t.Run(fmt.Sprintf("validation feature enabled=%v, old CRD %v, new CRD %v", validationEnabled, oldCRDInfo.name, newCRDInfo.name), dropDisabledFields(&newCRD.Spec, oldCRDSpec)
func(t *testing.T) { // old CRD should never be changed
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, apiextensionsfeatures.CustomResourceValidation, validationEnabled)() if !reflect.DeepEqual(oldCRD, oldCRDInfo.crd()) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, apiextensionsfeatures.CustomResourceWebhookConversion, conversionEnabled)() t.Errorf("old crd changed: %v", diff.ObjectReflectDiff(oldCRD, oldCRDInfo.crd()))
var oldCRDSpec *apiextensions.CustomResourceDefinitionSpec }
if oldCRD != nil { if !reflect.DeepEqual(newCRD, newCRDInfo.crd()) {
oldCRDSpec = &oldCRD.Spec t.Errorf("new crd changed: %v", diff.ObjectReflectDiff(newCRD, newCRDInfo.crd()))
} }
dropDisabledFields(&newCRD.Spec, oldCRDSpec) },
// old CRD should never be changed )
if !reflect.DeepEqual(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()) {
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} { crdWithVersionedSubresources := func() *apiextensions.CustomResourceDefinition {
for _, validationEnabled := range []bool{true, false} { // crd with versioned subresources
crdWithVersionedSubresources := func() *apiextensions.CustomResourceDefinition { return &apiextensions.CustomResourceDefinition{
// crd with versioned subresources Spec: apiextensions.CustomResourceDefinitionSpec{
return &apiextensions.CustomResourceDefinition{ Versions: []apiextensions.CustomResourceDefinitionVersion{
Spec: apiextensions.CustomResourceDefinitionSpec{ {
Versions: []apiextensions.CustomResourceDefinitionVersion{ Name: "v1",
{ Subresources: &apiextensions.CustomResourceSubresources{},
Name: "v1",
Subresources: &apiextensions.CustomResourceSubresources{},
},
},
}, },
} },
} },
crdWithoutVersionedSubresources := func() *apiextensions.CustomResourceDefinition { }
// crd without versioned subresources }
return &apiextensions.CustomResourceDefinition{ crdWithoutVersionedSubresources := func() *apiextensions.CustomResourceDefinition {
Spec: apiextensions.CustomResourceDefinitionSpec{ // crd without versioned subresources
Versions: []apiextensions.CustomResourceDefinitionVersion{ return &apiextensions.CustomResourceDefinition{
{ Spec: apiextensions.CustomResourceDefinitionSpec{
Name: "v1", Versions: []apiextensions.CustomResourceDefinitionVersion{
}, {
}, Name: "v1",
}, },
} },
},
}
}
crdInfos = []struct {
name string
crd func() *apiextensions.CustomResourceDefinition
}{
{
name: "has versioned subresources",
crd: crdWithVersionedSubresources,
},
{
name: "doesn't have versioned subresources",
crd: crdWithoutVersionedSubresources,
},
{
name: "nil",
crd: func() *apiextensions.CustomResourceDefinition { return nil },
},
}
for _, oldCRDInfo := range crdInfos {
for _, newCRDInfo := range crdInfos {
oldCRD := oldCRDInfo.crd()
newCRD := newCRDInfo.crd()
if newCRD == nil {
continue
} }
crdInfos := []struct { t.Run(fmt.Sprintf("old CRD %v, new CRD %v", oldCRDInfo.name, newCRDInfo.name),
name string func(t *testing.T) {
hasCRSubresources bool var oldCRDSpec *apiextensions.CustomResourceDefinitionSpec
crd func() *apiextensions.CustomResourceDefinition if oldCRD != nil {
}{ oldCRDSpec = &oldCRD.Spec
{
name: "has versioned subresources",
hasCRSubresources: true,
crd: crdWithVersionedSubresources,
},
{
name: "doesn't have versioned subresources",
hasCRSubresources: false,
crd: crdWithoutVersionedSubresources,
},
{
name: "nil",
hasCRSubresources: false,
crd: func() *apiextensions.CustomResourceDefinition { return nil },
},
}
for _, oldCRDInfo := range crdInfos {
for _, newCRDInfo := range crdInfos {
oldCRDHasSubresources, oldCRD := oldCRDInfo.hasCRSubresources, oldCRDInfo.crd()
newCRDHasSubresources, newCRD := newCRDInfo.hasCRSubresources, newCRDInfo.crd()
if newCRD == nil {
continue
} }
t.Run(fmt.Sprintf("subresources feature enabled=%v, old CRD %v, new CRD %v", validationEnabled, oldCRDInfo.name, newCRDInfo.name), dropDisabledFields(&newCRD.Spec, oldCRDSpec)
func(t *testing.T) { // old CRD should never be changed
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, apiextensionsfeatures.CustomResourceSubresources, validationEnabled)() if !reflect.DeepEqual(oldCRD, oldCRDInfo.crd()) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, apiextensionsfeatures.CustomResourceWebhookConversion, conversionEnabled)() t.Errorf("old crd changed: %v", diff.ObjectReflectDiff(oldCRD, oldCRDInfo.crd()))
var oldCRDSpec *apiextensions.CustomResourceDefinitionSpec }
if oldCRD != nil { if !reflect.DeepEqual(newCRD, newCRDInfo.crd()) {
oldCRDSpec = &oldCRD.Spec t.Errorf("new crd changed: %v", diff.ObjectReflectDiff(newCRD, newCRDInfo.crd()))
} }
dropDisabledFields(&newCRD.Spec, oldCRDSpec) },
// old CRD should never be changed )
if !reflect.DeepEqual(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()) {
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{ Spec: apiextensions.CustomResourceDefinitionSpec{
Spec: apiextensions.CustomResourceDefinitionSpec{ Conversion: &apiextensions.CustomResourceConversion{
Conversion: &apiextensions.CustomResourceConversion{ WebhookClientConfig: &apiextensions.WebhookClientConfig{},
WebhookClientConfig: &apiextensions.WebhookClientConfig{},
},
}, },
}
}
crdWithoutUnversionedConversionWebhook := func() *apiextensions.CustomResourceDefinition {
// crd with conversion webhook
return &apiextensions.CustomResourceDefinition{
Spec: apiextensions.CustomResourceDefinitionSpec{
Conversion: &apiextensions.CustomResourceConversion{},
},
}
}
crdInfos := []struct {
name string
hasCRConversionWebhook bool
crd func() *apiextensions.CustomResourceDefinition
}{
{
name: "has conversion webhook",
hasCRConversionWebhook: true,
crd: crdWithUnversionedConversionWebhook,
}, },
{
name: "doesn't have conversion webhook",
hasCRConversionWebhook: false,
crd: crdWithoutUnversionedConversionWebhook,
},
{
name: "nil",
hasCRConversionWebhook: false,
crd: func() *apiextensions.CustomResourceDefinition { return nil },
},
}
for _, oldCRDInfo := range crdInfos {
for _, newCRDInfo := range crdInfos {
oldCRDHasConversionWebhook, oldCRD := oldCRDInfo.hasCRConversionWebhook, oldCRDInfo.crd()
newCRDHasConversionWebhook, newCRD := newCRDInfo.hasCRConversionWebhook, newCRDInfo.crd()
if newCRD == nil {
continue
}
t.Run(fmt.Sprintf("subresources feature enabled=%v, old CRD %v, new CRD %v", validationEnabled, oldCRDInfo.name, newCRDInfo.name),
func(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, apiextensionsfeatures.CustomResourceWebhookConversion, validationEnabled)()
var oldCRDSpec *apiextensions.CustomResourceDefinitionSpec
if oldCRD != nil {
oldCRDSpec = &oldCRD.Spec
}
dropDisabledFields(&newCRD.Spec, oldCRDSpec)
// old CRD should never be changed
if !reflect.DeepEqual(oldCRD, oldCRDInfo.crd()) {
t.Errorf("old crd changed: %v", diff.ObjectReflectDiff(oldCRD, oldCRDInfo.crd()))
}
switch {
case validationEnabled || oldCRDHasConversionWebhook:
if !reflect.DeepEqual(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()))
}
}
},
)
}
} }
} }
crdWithoutUnversionedConversionWebhook := func() *apiextensions.CustomResourceDefinition {
// crd with conversion webhook
return &apiextensions.CustomResourceDefinition{
Spec: apiextensions.CustomResourceDefinitionSpec{
Conversion: &apiextensions.CustomResourceConversion{},
},
}
}
crdInfos = []struct {
name string
crd func() *apiextensions.CustomResourceDefinition
}{
{
name: "has conversion webhook",
crd: crdWithUnversionedConversionWebhook,
},
{
name: "doesn't have conversion webhook",
crd: crdWithoutUnversionedConversionWebhook,
},
{
name: "nil",
crd: func() *apiextensions.CustomResourceDefinition { return nil },
},
}
for _, oldCRDInfo := range crdInfos {
for _, newCRDInfo := range crdInfos {
oldCRD := oldCRDInfo.crd()
newCRD := newCRDInfo.crd()
if newCRD == nil {
continue
}
t.Run(fmt.Sprintf("old CRD %v, new CRD %v", oldCRDInfo.name, newCRDInfo.name),
func(t *testing.T) {
var oldCRDSpec *apiextensions.CustomResourceDefinitionSpec
if oldCRD != nil {
oldCRDSpec = &oldCRD.Spec
}
dropDisabledFields(&newCRD.Spec, oldCRDSpec)
// old CRD should never be changed
if !reflect.DeepEqual(oldCRD, oldCRDInfo.crd()) {
t.Errorf("old crd changed: %v", diff.ObjectReflectDiff(oldCRD, oldCRDInfo.crd()))
}
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 {