mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-25 04:33:26 +00:00
Remove use of CustomResourceSubresources feature gate, CRD field clearing
This commit is contained in:
parent
57f3a97bcb
commit
4c2eb77ee6
@ -15,7 +15,6 @@ go_library(
|
||||
"//staging/src/k8s.io/api/autoscaling/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1:go_default_library",
|
||||
"//staging/src/k8s.io/apiextensions-apiserver/pkg/features:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/validation:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
|
||||
@ -25,7 +24,6 @@ go_library(
|
||||
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/uuid: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/apiserver/pkg/util/webhook:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/kubernetes/scheme:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/rest:go_default_library",
|
||||
|
@ -21,11 +21,9 @@ import (
|
||||
|
||||
autoscalingv1 "k8s.io/api/autoscaling/v1"
|
||||
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||
apiextensionsfeatures "k8s.io/apiextensions-apiserver/pkg/features"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/apiserver/pkg/util/webhook"
|
||||
typedscheme "k8s.io/client-go/kubernetes/scheme"
|
||||
)
|
||||
@ -78,11 +76,9 @@ func (m *CRConverterFactory) NewConverter(crd *apiextensionsv1.CustomResourceDef
|
||||
|
||||
// Determine whether we should expect to be asked to "convert" autoscaling/v1 Scale types
|
||||
convertScale := false
|
||||
if utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceSubresources) {
|
||||
for _, version := range crd.Spec.Versions {
|
||||
if version.Subresources != nil && version.Subresources.Scale != nil {
|
||||
convertScale = true
|
||||
}
|
||||
for _, version := range crd.Spec.Versions {
|
||||
if version.Subresources != nil && version.Subresources.Scale != nil {
|
||||
convertScale = true
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,7 +44,6 @@ import (
|
||||
"k8s.io/apiextensions-apiserver/pkg/controller/finalizer"
|
||||
"k8s.io/apiextensions-apiserver/pkg/controller/openapi/builder"
|
||||
"k8s.io/apiextensions-apiserver/pkg/crdserverscheme"
|
||||
apiextensionsfeatures "k8s.io/apiextensions-apiserver/pkg/features"
|
||||
"k8s.io/apiextensions-apiserver/pkg/registry/customresource"
|
||||
"k8s.io/apiextensions-apiserver/pkg/registry/customresource/tableconvertor"
|
||||
|
||||
@ -701,7 +700,7 @@ func (r *crdHandler) getOrCreateServingInfoFor(uid types.UID, name string) (*crd
|
||||
utilruntime.HandleError(err)
|
||||
return nil, fmt.Errorf("the server could not properly serve the CR subresources")
|
||||
}
|
||||
if utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceSubresources) && subresources != nil && subresources.Status != nil {
|
||||
if subresources != nil && subresources.Status != nil {
|
||||
equivalentResourceRegistry.RegisterKindFor(resource, "status", kind)
|
||||
statusSpec = &apiextensionsinternal.CustomResourceSubresourceStatus{}
|
||||
if err := apiextensionsv1.Convert_v1_CustomResourceSubresourceStatus_To_apiextensions_CustomResourceSubresourceStatus(subresources.Status, statusSpec, nil); err != nil {
|
||||
@ -720,7 +719,7 @@ func (r *crdHandler) getOrCreateServingInfoFor(uid types.UID, name string) (*crd
|
||||
}
|
||||
|
||||
var scaleSpec *apiextensionsinternal.CustomResourceSubresourceScale
|
||||
if utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceSubresources) && subresources != nil && subresources.Scale != nil {
|
||||
if subresources != nil && subresources.Scale != nil {
|
||||
equivalentResourceRegistry.RegisterKindFor(resource, "scale", autoscalingv1.SchemeGroupVersion.WithKind("Scale"))
|
||||
scaleSpec = &apiextensionsinternal.CustomResourceSubresourceScale{}
|
||||
if err := apiextensionsv1.Convert_v1_CustomResourceSubresourceScale_To_apiextensions_CustomResourceSubresourceScale(subresources.Scale, scaleSpec, nil); err != nil {
|
||||
|
@ -22,7 +22,6 @@ go_library(
|
||||
"//staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/schema:go_default_library",
|
||||
"//staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/schema/objectmeta:go_default_library",
|
||||
"//staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/validation:go_default_library",
|
||||
"//staging/src/k8s.io/apiextensions-apiserver/pkg/features:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/equality:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/meta:go_default_library",
|
||||
@ -40,7 +39,6 @@ go_library(
|
||||
"//staging/src/k8s.io/apiserver/pkg/registry/rest:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/storage:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/storage/names:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//vendor/github.com/go-openapi/validate:go_default_library",
|
||||
],
|
||||
)
|
||||
|
@ -32,12 +32,10 @@ import (
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
apiserverstorage "k8s.io/apiserver/pkg/storage"
|
||||
"k8s.io/apiserver/pkg/storage/names"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
|
||||
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
|
||||
structuralschema "k8s.io/apiextensions-apiserver/pkg/apiserver/schema"
|
||||
schemaobjectmeta "k8s.io/apiextensions-apiserver/pkg/apiserver/schema/objectmeta"
|
||||
apiextensionsfeatures "k8s.io/apiextensions-apiserver/pkg/features"
|
||||
)
|
||||
|
||||
// customResourceStrategy implements behavior for CustomResources.
|
||||
@ -75,7 +73,7 @@ func (a customResourceStrategy) NamespaceScoped() bool {
|
||||
|
||||
// PrepareForCreate clears the status of a CustomResource before creation.
|
||||
func (a customResourceStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) {
|
||||
if utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceSubresources) && a.status != nil {
|
||||
if a.status != nil {
|
||||
customResourceObject := obj.(*unstructured.Unstructured)
|
||||
customResource := customResourceObject.UnstructuredContent()
|
||||
|
||||
@ -98,7 +96,7 @@ func (a customResourceStrategy) PrepareForUpdate(ctx context.Context, obj, old r
|
||||
oldCustomResource := oldCustomResourceObject.UnstructuredContent()
|
||||
|
||||
// If the /status subresource endpoint is installed, update is not allowed to set status.
|
||||
if utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceSubresources) && a.status != nil {
|
||||
if a.status != nil {
|
||||
_, ok1 := newCustomResource["status"]
|
||||
_, ok2 := oldCustomResource["status"]
|
||||
switch {
|
||||
|
@ -13,7 +13,6 @@ go_library(
|
||||
deps = [
|
||||
"//staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions: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/api/equality:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
@ -30,7 +29,6 @@ go_library(
|
||||
"//staging/src/k8s.io/apiserver/pkg/storage/errors:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/storage/names:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/dryrun:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@ -57,7 +55,6 @@ go_test(
|
||||
"//staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation: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/util/diff:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
|
||||
"//vendor/k8s.io/utils/pointer:go_default_library",
|
||||
],
|
||||
|
@ -22,7 +22,6 @@ import (
|
||||
|
||||
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
|
||||
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation"
|
||||
apiextensionsfeatures "k8s.io/apiextensions-apiserver/pkg/features"
|
||||
apiequality "k8s.io/apimachinery/pkg/api/equality"
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
@ -33,7 +32,6 @@ import (
|
||||
"k8s.io/apiserver/pkg/registry/generic"
|
||||
"k8s.io/apiserver/pkg/storage"
|
||||
"k8s.io/apiserver/pkg/storage/names"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
)
|
||||
|
||||
// strategy implements behavior for CustomResources.
|
||||
@ -56,8 +54,6 @@ func (strategy) PrepareForCreate(ctx context.Context, obj runtime.Object) {
|
||||
crd.Status = apiextensions.CustomResourceDefinitionStatus{}
|
||||
crd.Generation = 1
|
||||
|
||||
dropDisabledFields(&crd.Spec, nil)
|
||||
|
||||
for _, v := range crd.Spec.Versions {
|
||||
if v.Storage {
|
||||
if !apiextensions.IsStoredVersion(crd, v.Name) {
|
||||
@ -86,8 +82,6 @@ func (strategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) {
|
||||
newCRD.Generation = oldCRD.Generation + 1
|
||||
}
|
||||
|
||||
dropDisabledFields(&newCRD.Spec, &oldCRD.Spec)
|
||||
|
||||
for _, v := range newCRD.Spec.Versions {
|
||||
if v.Storage {
|
||||
if !apiextensions.IsStoredVersion(newCRD, v.Name) {
|
||||
@ -198,102 +192,3 @@ func MatchCustomResourceDefinition(label labels.Selector, field fields.Selector)
|
||||
func CustomResourceDefinitionToSelectableFields(obj *apiextensions.CustomResourceDefinition) fields.Set {
|
||||
return generic.ObjectMetaFieldsSet(&obj.ObjectMeta, true)
|
||||
}
|
||||
|
||||
func dropDisabledFields(crdSpec, oldCrdSpec *apiextensions.CustomResourceDefinitionSpec) {
|
||||
// if the feature gate is disabled, drop the feature.
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceValidation) &&
|
||||
!validationInUse(oldCrdSpec) {
|
||||
crdSpec.Validation = nil
|
||||
for i := range crdSpec.Versions {
|
||||
crdSpec.Versions[i].Schema = nil
|
||||
}
|
||||
}
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceSubresources) &&
|
||||
!subresourceInUse(oldCrdSpec) {
|
||||
crdSpec.Subresources = nil
|
||||
for i := range crdSpec.Versions {
|
||||
crdSpec.Versions[i].Subresources = nil
|
||||
}
|
||||
}
|
||||
|
||||
// 1. On CREATE (in which case the old CRD spec is nil), if the CustomResourceWebhookConversion feature gate is off, we auto-clear
|
||||
// the per-version fields. This is to be consistent with the other built-in types, as the
|
||||
// apiserver drops unknown fields.
|
||||
// 2. On UPDATE, if the CustomResourceWebhookConversion feature gate is off, we auto-clear
|
||||
// the per-version fields if the old CRD doesn't use per-version fields already.
|
||||
// This is to be consistent with the other built-in types, as the apiserver drops unknown
|
||||
// fields. If the old CRD already uses per-version fields, the CRD is allowed to continue
|
||||
// use per-version fields.
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceWebhookConversion) &&
|
||||
!hasPerVersionField(oldCrdSpec) {
|
||||
for i := range crdSpec.Versions {
|
||||
crdSpec.Versions[i].Schema = nil
|
||||
crdSpec.Versions[i].Subresources = nil
|
||||
crdSpec.Versions[i].AdditionalPrinterColumns = nil
|
||||
}
|
||||
}
|
||||
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceWebhookConversion) &&
|
||||
!conversionWebhookInUse(oldCrdSpec) {
|
||||
if crdSpec.Conversion != nil {
|
||||
crdSpec.Conversion.WebhookClientConfig = nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func validationInUse(crdSpec *apiextensions.CustomResourceDefinitionSpec) bool {
|
||||
if crdSpec == nil {
|
||||
return false
|
||||
}
|
||||
if crdSpec.Validation != nil {
|
||||
return true
|
||||
}
|
||||
|
||||
for i := range crdSpec.Versions {
|
||||
if crdSpec.Versions[i].Schema != nil {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func subresourceInUse(crdSpec *apiextensions.CustomResourceDefinitionSpec) bool {
|
||||
if crdSpec == nil {
|
||||
return false
|
||||
}
|
||||
if crdSpec.Subresources != nil {
|
||||
return true
|
||||
}
|
||||
|
||||
for i := range crdSpec.Versions {
|
||||
if crdSpec.Versions[i].Subresources != nil {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// hasPerVersionField returns true if a CRD uses per-version schema/subresources/columns fields.
|
||||
//func hasPerVersionField(versions []apiextensions.CustomResourceDefinitionVersion) bool {
|
||||
func hasPerVersionField(crdSpec *apiextensions.CustomResourceDefinitionSpec) bool {
|
||||
if crdSpec == nil {
|
||||
return false
|
||||
}
|
||||
for _, v := range crdSpec.Versions {
|
||||
if v.Schema != nil || v.Subresources != nil || len(v.AdditionalPrinterColumns) > 0 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func conversionWebhookInUse(crdSpec *apiextensions.CustomResourceDefinitionSpec) bool {
|
||||
if crdSpec == nil {
|
||||
return false
|
||||
}
|
||||
if crdSpec.Conversion == nil {
|
||||
return false
|
||||
}
|
||||
return crdSpec.Conversion.WebhookClientConfig != nil
|
||||
}
|
||||
|
@ -17,8 +17,6 @@ limitations under the License.
|
||||
package customresourcedefinition
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
|
||||
@ -26,333 +24,10 @@ import (
|
||||
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/util/diff"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
"k8s.io/utils/pointer"
|
||||
)
|
||||
|
||||
func TestDropDisableFieldsCustomResourceDefinition(t *testing.T) {
|
||||
t.Log("testing unversioned validation..")
|
||||
crdWithUnversionedValidation := func() *apiextensions.CustomResourceDefinition {
|
||||
// crd with non-versioned validation
|
||||
return &apiextensions.CustomResourceDefinition{
|
||||
Spec: apiextensions.CustomResourceDefinitionSpec{
|
||||
Validation: &apiextensions.CustomResourceValidation{
|
||||
OpenAPIV3Schema: &apiextensions.JSONSchemaProps{},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
crdWithoutUnversionedValidation := func() *apiextensions.CustomResourceDefinition {
|
||||
// crd with non-versioned validation
|
||||
return &apiextensions.CustomResourceDefinition{
|
||||
Spec: apiextensions.CustomResourceDefinitionSpec{},
|
||||
}
|
||||
}
|
||||
crdInfos := []struct {
|
||||
name string
|
||||
crd func() *apiextensions.CustomResourceDefinition
|
||||
}{
|
||||
{
|
||||
name: "has unversioned validation",
|
||||
crd: crdWithUnversionedValidation,
|
||||
},
|
||||
{
|
||||
name: "doesn't have unversioned validation",
|
||||
crd: crdWithoutUnversionedValidation,
|
||||
},
|
||||
{
|
||||
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()))
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
t.Log("testing unversioned subresources...")
|
||||
crdWithUnversionedSubresources := func() *apiextensions.CustomResourceDefinition {
|
||||
// crd with unversioned subresources
|
||||
return &apiextensions.CustomResourceDefinition{
|
||||
Spec: apiextensions.CustomResourceDefinitionSpec{
|
||||
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()))
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
t.Log("testing versioned validation..")
|
||||
crdWithVersionedValidation := func() *apiextensions.CustomResourceDefinition {
|
||||
// crd with versioned validation
|
||||
return &apiextensions.CustomResourceDefinition{
|
||||
Spec: apiextensions.CustomResourceDefinitionSpec{
|
||||
Versions: []apiextensions.CustomResourceDefinitionVersion{
|
||||
{
|
||||
Name: "v1",
|
||||
Schema: &apiextensions.CustomResourceValidation{
|
||||
OpenAPIV3Schema: &apiextensions.JSONSchemaProps{},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
crdWithoutVersionedValidation := func() *apiextensions.CustomResourceDefinition {
|
||||
// crd with versioned validation
|
||||
return &apiextensions.CustomResourceDefinition{
|
||||
Spec: apiextensions.CustomResourceDefinitionSpec{
|
||||
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
|
||||
}
|
||||
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 versioned subresources w/ conversion enabled..")
|
||||
crdWithVersionedSubresources := func() *apiextensions.CustomResourceDefinition {
|
||||
// crd with versioned subresources
|
||||
return &apiextensions.CustomResourceDefinition{
|
||||
Spec: apiextensions.CustomResourceDefinitionSpec{
|
||||
Versions: []apiextensions.CustomResourceDefinitionVersion{
|
||||
{
|
||||
Name: "v1",
|
||||
Subresources: &apiextensions.CustomResourceSubresources{},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
crdWithoutVersionedSubresources := func() *apiextensions.CustomResourceDefinition {
|
||||
// crd without versioned subresources
|
||||
return &apiextensions.CustomResourceDefinition{
|
||||
Spec: apiextensions.CustomResourceDefinitionSpec{
|
||||
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
|
||||
}
|
||||
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 conversion webhook..")
|
||||
crdWithUnversionedConversionWebhook := func() *apiextensions.CustomResourceDefinition {
|
||||
// crd with conversion webhook
|
||||
return &apiextensions.CustomResourceDefinition{
|
||||
Spec: apiextensions.CustomResourceDefinitionSpec{
|
||||
Conversion: &apiextensions.CustomResourceConversion{
|
||||
WebhookClientConfig: &apiextensions.WebhookClientConfig{},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
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 {
|
||||
return &in
|
||||
}
|
||||
|
1
vendor/modules.txt
vendored
1
vendor/modules.txt
vendored
@ -1182,7 +1182,6 @@ k8s.io/apiextensions-apiserver/pkg/controller/openapi/builder
|
||||
k8s.io/apiextensions-apiserver/pkg/controller/openapi/v2
|
||||
k8s.io/apiextensions-apiserver/pkg/controller/status
|
||||
k8s.io/apiextensions-apiserver/pkg/crdserverscheme
|
||||
k8s.io/apiextensions-apiserver/pkg/features
|
||||
k8s.io/apiextensions-apiserver/pkg/generated/openapi
|
||||
k8s.io/apiextensions-apiserver/pkg/registry/customresource
|
||||
k8s.io/apiextensions-apiserver/pkg/registry/customresource/tableconvertor
|
||||
|
Loading…
Reference in New Issue
Block a user