From cc0264f7fc8db64d3d828226bc00627cd892beca Mon Sep 17 00:00:00 2001 From: Alexander Zielenski Date: Wed, 18 Oct 2023 14:58:26 -0700 Subject: [PATCH 1/4] cleanup: check unstructured for Validate(Update) before validating logic is the same. sets us up for another refactor --- .../pkg/registry/customresource/strategy.go | 42 +++++++++------- .../pkg/registry/customresource/validator.go | 50 +++++-------------- 2 files changed, 35 insertions(+), 57 deletions(-) diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/strategy.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/strategy.go index 0fdac7635b9..80a9ef5fa9b 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/strategy.go +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/strategy.go @@ -18,6 +18,7 @@ package customresource import ( "context" + "fmt" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions" structuralschema "k8s.io/apiextensions-apiserver/pkg/apiserver/schema" @@ -163,25 +164,28 @@ func copyNonMetadata(original map[string]interface{}) map[string]interface{} { // Validate validates a new CustomResource. func (a customResourceStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { + u, ok := obj.(*unstructured.Unstructured) + if !ok { + return field.ErrorList{field.Invalid(field.NewPath(""), u, fmt.Sprintf("has type %T. Must be a pointer to an Unstructured type", u))} + } + var errs field.ErrorList - errs = append(errs, a.validator.Validate(ctx, obj, a.scale)...) + errs = append(errs, a.validator.Validate(ctx, u, a.scale)...) // validate embedded resources - if u, ok := obj.(*unstructured.Unstructured); ok { - v := obj.GetObjectKind().GroupVersionKind().Version - errs = append(errs, schemaobjectmeta.Validate(nil, u.Object, a.structuralSchemas[v], false)...) + v := obj.GetObjectKind().GroupVersionKind().Version + errs = append(errs, schemaobjectmeta.Validate(nil, u.Object, a.structuralSchemas[v], false)...) - // validate x-kubernetes-list-type "map" and "set" invariant - errs = append(errs, structurallisttype.ValidateListSetsAndMaps(nil, a.structuralSchemas[v], u.Object)...) + // validate x-kubernetes-list-type "map" and "set" invariant + errs = append(errs, structurallisttype.ValidateListSetsAndMaps(nil, a.structuralSchemas[v], u.Object)...) - // validate x-kubernetes-validations rules - if celValidator, ok := a.celValidators[v]; ok { - if has, err := hasBlockingErr(errs); has { - errs = append(errs, err) - } else { - err, _ := celValidator.Validate(ctx, nil, a.structuralSchemas[v], u.Object, nil, celconfig.RuntimeCELCostBudget) - errs = append(errs, err...) - } + // validate x-kubernetes-validations rules + if celValidator, ok := a.celValidators[v]; ok { + if has, err := hasBlockingErr(errs); has { + errs = append(errs, err) + } else { + err, _ := celValidator.Validate(ctx, nil, a.structuralSchemas[v], u.Object, nil, celconfig.RuntimeCELCostBudget) + errs = append(errs, err...) } } @@ -234,18 +238,18 @@ func (customResourceStrategy) AllowUnconditionalUpdate() bool { // ValidateUpdate is the default update validation for an end user updating status. func (a customResourceStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { - var errs field.ErrorList - errs = append(errs, a.validator.ValidateUpdate(ctx, obj, old, a.scale)...) - uNew, ok := obj.(*unstructured.Unstructured) if !ok { - return errs + return field.ErrorList{field.Invalid(field.NewPath(""), obj, fmt.Sprintf("has type %T. Must be a pointer to an Unstructured type", obj))} } uOld, ok := old.(*unstructured.Unstructured) if !ok { - return errs + return field.ErrorList{field.Invalid(field.NewPath(""), old, fmt.Sprintf("has type %T. Must be a pointer to an Unstructured type", old))} } + var errs field.ErrorList + errs = append(errs, a.validator.ValidateUpdate(ctx, uNew, uOld, a.scale)...) + // Checks the embedded objects. We don't make a difference between update and create for those. v := obj.GetObjectKind().GroupVersionKind().Version errs = append(errs, schemaobjectmeta.Validate(nil, uNew.Object, a.structuralSchemas[v], false)...) diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/validator.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/validator.go index 54be1db9752..82163fa8221 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/validator.go +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/validator.go @@ -44,58 +44,32 @@ type customResourceValidator struct { statusSchemaValidator apiextensionsvalidation.SchemaValidator } -func (a customResourceValidator) Validate(ctx context.Context, obj runtime.Object, scale *apiextensions.CustomResourceSubresourceScale) field.ErrorList { - u, ok := obj.(*unstructured.Unstructured) - if !ok { - return field.ErrorList{field.Invalid(field.NewPath(""), u, fmt.Sprintf("has type %T. Must be a pointer to an Unstructured type", u))} - } - accessor, err := meta.Accessor(obj) - if err != nil { - return field.ErrorList{field.Invalid(field.NewPath("metadata"), nil, err.Error())} - } - - if errs := a.ValidateTypeMeta(ctx, u); len(errs) > 0 { +func (a customResourceValidator) Validate(ctx context.Context, obj *unstructured.Unstructured, scale *apiextensions.CustomResourceSubresourceScale) field.ErrorList { + if errs := a.ValidateTypeMeta(ctx, obj); len(errs) > 0 { return errs } var allErrs field.ErrorList - allErrs = append(allErrs, validation.ValidateObjectMetaAccessor(accessor, a.namespaceScoped, validation.NameIsDNSSubdomain, field.NewPath("metadata"))...) - allErrs = append(allErrs, apiextensionsvalidation.ValidateCustomResource(nil, u.UnstructuredContent(), a.schemaValidator)...) - allErrs = append(allErrs, a.ValidateScaleSpec(ctx, u, scale)...) - allErrs = append(allErrs, a.ValidateScaleStatus(ctx, u, scale)...) + allErrs = append(allErrs, validation.ValidateObjectMetaAccessor(obj, a.namespaceScoped, validation.NameIsDNSSubdomain, field.NewPath("metadata"))...) + allErrs = append(allErrs, apiextensionsvalidation.ValidateCustomResource(nil, obj.UnstructuredContent(), a.schemaValidator)...) + allErrs = append(allErrs, a.ValidateScaleSpec(ctx, obj, scale)...) + allErrs = append(allErrs, a.ValidateScaleStatus(ctx, obj, scale)...) return allErrs } -func (a customResourceValidator) ValidateUpdate(ctx context.Context, obj, old runtime.Object, scale *apiextensions.CustomResourceSubresourceScale) field.ErrorList { - u, ok := obj.(*unstructured.Unstructured) - if !ok { - return field.ErrorList{field.Invalid(field.NewPath(""), u, fmt.Sprintf("has type %T. Must be a pointer to an Unstructured type", u))} - } - oldU, ok := old.(*unstructured.Unstructured) - if !ok { - return field.ErrorList{field.Invalid(field.NewPath(""), old, fmt.Sprintf("has type %T. Must be a pointer to an Unstructured type", u))} - } - objAccessor, err := meta.Accessor(obj) - if err != nil { - return field.ErrorList{field.Invalid(field.NewPath("metadata"), nil, err.Error())} - } - oldAccessor, err := meta.Accessor(old) - if err != nil { - return field.ErrorList{field.Invalid(field.NewPath("metadata"), nil, err.Error())} - } - - if errs := a.ValidateTypeMeta(ctx, u); len(errs) > 0 { +func (a customResourceValidator) ValidateUpdate(ctx context.Context, obj, old *unstructured.Unstructured, scale *apiextensions.CustomResourceSubresourceScale) field.ErrorList { + if errs := a.ValidateTypeMeta(ctx, obj); len(errs) > 0 { return errs } var allErrs field.ErrorList - allErrs = append(allErrs, validation.ValidateObjectMetaAccessorUpdate(objAccessor, oldAccessor, field.NewPath("metadata"))...) - allErrs = append(allErrs, apiextensionsvalidation.ValidateCustomResourceUpdate(nil, u.UnstructuredContent(), oldU.UnstructuredContent(), a.schemaValidator)...) - allErrs = append(allErrs, a.ValidateScaleSpec(ctx, u, scale)...) - allErrs = append(allErrs, a.ValidateScaleStatus(ctx, u, scale)...) + allErrs = append(allErrs, validation.ValidateObjectMetaAccessorUpdate(obj, old, field.NewPath("metadata"))...) + allErrs = append(allErrs, apiextensionsvalidation.ValidateCustomResourceUpdate(nil, obj.UnstructuredContent(), old.UnstructuredContent(), a.schemaValidator)...) + allErrs = append(allErrs, a.ValidateScaleSpec(ctx, obj, scale)...) + allErrs = append(allErrs, a.ValidateScaleStatus(ctx, obj, scale)...) return allErrs } From d151f22780376eaaa5033c846c912f11dd48d547 Mon Sep 17 00:00:00 2001 From: Alexander Zielenski Date: Wed, 18 Oct 2023 15:04:47 -0700 Subject: [PATCH 2/4] cleanup: remove unused versions of cel validators and structural schemas from CRD strategy --- .../pkg/apiserver/customresource_handler.go | 2 +- .../customresource/status_strategy.go | 10 ++-- .../customresource/status_strategy_test.go | 4 +- .../pkg/registry/customresource/strategy.go | 54 +++++++++---------- 4 files changed, 30 insertions(+), 40 deletions(-) diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler.go index 05b553ef864..39fa18c5792 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler.go +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler.go @@ -805,7 +805,7 @@ func (r *crdHandler) getOrCreateServingInfoFor(uid types.UID, name string) (*crd kind, validator, statusValidator, - structuralSchemas, + structuralSchemas[v.Name], statusSpec, scaleSpec, ), diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/status_strategy.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/status_strategy.go index 8d3796ac9af..a3b363c798c 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/status_strategy.go +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/status_strategy.go @@ -99,21 +99,19 @@ func (a statusStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Obj oldObject = uOld.Object } - v := obj.GetObjectKind().GroupVersionKind().Version - // ratcheting validation of x-kubernetes-list-type value map and set - if newErrs := structurallisttype.ValidateListSetsAndMaps(nil, a.structuralSchemas[v], uNew.Object); len(newErrs) > 0 { - if oldErrs := structurallisttype.ValidateListSetsAndMaps(nil, a.structuralSchemas[v], oldObject); len(oldErrs) == 0 { + if newErrs := structurallisttype.ValidateListSetsAndMaps(nil, a.structuralSchema, uNew.Object); len(newErrs) > 0 { + if oldErrs := structurallisttype.ValidateListSetsAndMaps(nil, a.structuralSchema, oldObject); len(oldErrs) == 0 { errs = append(errs, newErrs...) } } // validate x-kubernetes-validations rules - if celValidator, ok := a.customResourceStrategy.celValidators[v]; ok { + if celValidator := a.customResourceStrategy.celValidator; celValidator != nil { if has, err := hasBlockingErr(errs); has { errs = append(errs, err) } else { - err, _ := celValidator.Validate(ctx, nil, a.customResourceStrategy.structuralSchemas[v], uNew.Object, oldObject, celconfig.RuntimeCELCostBudget) + err, _ := celValidator.Validate(ctx, nil, a.customResourceStrategy.structuralSchema, uNew.Object, oldObject, celconfig.RuntimeCELCostBudget) errs = append(errs, err...) } } diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/status_strategy_test.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/status_strategy_test.go index a91e8f0587d..97538054286 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/status_strategy_test.go +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/status_strategy_test.go @@ -198,9 +198,7 @@ func TestStatusStrategyValidateUpdate(t *testing.T) { } strategy.customResourceStrategy.validator.kind = kind ss, _ := structuralschema.NewStructural(crd.Spec.Versions[0].Schema.OpenAPIV3Schema) - strategy.structuralSchemas = map[string]*structuralschema.Structural{ - crd.Spec.Versions[0].Name: ss, - } + strategy.structuralSchema = ss ctx := context.TODO() diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/strategy.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/strategy.go index 80a9ef5fa9b..193acaee283 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/strategy.go +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/strategy.go @@ -45,29 +45,25 @@ import ( "sigs.k8s.io/structured-merge-diff/v4/fieldpath" ) -// customResourceStrategy implements behavior for CustomResources. +// customResourceStrategy implements behavior for CustomResources for a single +// version type customResourceStrategy struct { runtime.ObjectTyper names.NameGenerator - namespaceScoped bool - validator customResourceValidator - structuralSchemas map[string]*structuralschema.Structural - celValidators map[string]*cel.Validator - status *apiextensions.CustomResourceSubresourceStatus - scale *apiextensions.CustomResourceSubresourceScale - kind schema.GroupVersionKind + namespaceScoped bool + validator customResourceValidator + structuralSchema *structuralschema.Structural + celValidator *cel.Validator + status *apiextensions.CustomResourceSubresourceStatus + scale *apiextensions.CustomResourceSubresourceScale + kind schema.GroupVersionKind } -func NewStrategy(typer runtime.ObjectTyper, namespaceScoped bool, kind schema.GroupVersionKind, schemaValidator, statusSchemaValidator validation.SchemaValidator, structuralSchemas map[string]*structuralschema.Structural, status *apiextensions.CustomResourceSubresourceStatus, scale *apiextensions.CustomResourceSubresourceScale) customResourceStrategy { - celValidators := map[string]*cel.Validator{} +func NewStrategy(typer runtime.ObjectTyper, namespaceScoped bool, kind schema.GroupVersionKind, schemaValidator, statusSchemaValidator validation.SchemaValidator, structuralSchema *structuralschema.Structural, status *apiextensions.CustomResourceSubresourceStatus, scale *apiextensions.CustomResourceSubresourceScale) customResourceStrategy { + var celValidator *cel.Validator if utilfeature.DefaultFeatureGate.Enabled(features.CustomResourceValidationExpressions) { - for name, s := range structuralSchemas { - v := cel.NewValidator(s, true, celconfig.PerCallLimit) // CEL programs are compiled and cached here - if v != nil { - celValidators[name] = v - } - } + celValidator = cel.NewValidator(structuralSchema, true, celconfig.PerCallLimit) // CEL programs are compiled and cached here } return customResourceStrategy{ @@ -82,9 +78,9 @@ func NewStrategy(typer runtime.ObjectTyper, namespaceScoped bool, kind schema.Gr schemaValidator: schemaValidator, statusSchemaValidator: statusSchemaValidator, }, - structuralSchemas: structuralSchemas, - celValidators: celValidators, - kind: kind, + structuralSchema: structuralSchema, + celValidator: celValidator, + kind: kind, } } @@ -173,18 +169,17 @@ func (a customResourceStrategy) Validate(ctx context.Context, obj runtime.Object errs = append(errs, a.validator.Validate(ctx, u, a.scale)...) // validate embedded resources - v := obj.GetObjectKind().GroupVersionKind().Version - errs = append(errs, schemaobjectmeta.Validate(nil, u.Object, a.structuralSchemas[v], false)...) + errs = append(errs, schemaobjectmeta.Validate(nil, u.Object, a.structuralSchema, false)...) // validate x-kubernetes-list-type "map" and "set" invariant - errs = append(errs, structurallisttype.ValidateListSetsAndMaps(nil, a.structuralSchemas[v], u.Object)...) + errs = append(errs, structurallisttype.ValidateListSetsAndMaps(nil, a.structuralSchema, u.Object)...) // validate x-kubernetes-validations rules - if celValidator, ok := a.celValidators[v]; ok { + if celValidator := a.celValidator; celValidator != nil { if has, err := hasBlockingErr(errs); has { errs = append(errs, err) } else { - err, _ := celValidator.Validate(ctx, nil, a.structuralSchemas[v], u.Object, nil, celconfig.RuntimeCELCostBudget) + err, _ := celValidator.Validate(ctx, nil, a.structuralSchema, u.Object, nil, celconfig.RuntimeCELCostBudget) errs = append(errs, err...) } } @@ -251,20 +246,19 @@ func (a customResourceStrategy) ValidateUpdate(ctx context.Context, obj, old run errs = append(errs, a.validator.ValidateUpdate(ctx, uNew, uOld, a.scale)...) // Checks the embedded objects. We don't make a difference between update and create for those. - v := obj.GetObjectKind().GroupVersionKind().Version - errs = append(errs, schemaobjectmeta.Validate(nil, uNew.Object, a.structuralSchemas[v], false)...) + errs = append(errs, schemaobjectmeta.Validate(nil, uNew.Object, a.structuralSchema, false)...) // ratcheting validation of x-kubernetes-list-type value map and set - if oldErrs := structurallisttype.ValidateListSetsAndMaps(nil, a.structuralSchemas[v], uOld.Object); len(oldErrs) == 0 { - errs = append(errs, structurallisttype.ValidateListSetsAndMaps(nil, a.structuralSchemas[v], uNew.Object)...) + if oldErrs := structurallisttype.ValidateListSetsAndMaps(nil, a.structuralSchema, uOld.Object); len(oldErrs) == 0 { + errs = append(errs, structurallisttype.ValidateListSetsAndMaps(nil, a.structuralSchema, uNew.Object)...) } // validate x-kubernetes-validations rules - if celValidator, ok := a.celValidators[v]; ok { + if celValidator := a.celValidator; celValidator != nil { if has, err := hasBlockingErr(errs); has { errs = append(errs, err) } else { - err, _ := celValidator.Validate(ctx, nil, a.structuralSchemas[v], uNew.Object, uOld.Object, celconfig.RuntimeCELCostBudget) + err, _ := celValidator.Validate(ctx, nil, a.structuralSchema, uNew.Object, uOld.Object, celconfig.RuntimeCELCostBudget) errs = append(errs, err...) } } From 31a1c00e49ce299cc531c0e0fe9edc69150eb9d2 Mon Sep 17 00:00:00 2001 From: Alexander Zielenski Date: Wed, 18 Oct 2023 15:08:43 -0700 Subject: [PATCH 3/4] cleanup: move unstructured check earlier in status update --- .../customresource/status_strategy.go | 18 +++++------ .../pkg/registry/customresource/validator.go | 30 ++++--------------- 2 files changed, 14 insertions(+), 34 deletions(-) diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/status_strategy.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/status_strategy.go index a3b363c798c..ceaf56629b0 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/status_strategy.go +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/status_strategy.go @@ -18,6 +18,7 @@ package customresource import ( "context" + "fmt" "sigs.k8s.io/structured-merge-diff/v4/fieldpath" @@ -84,24 +85,21 @@ func (a statusStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.O // ValidateUpdate is the default update validation for an end user updating status. func (a statusStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { - var errs field.ErrorList - errs = append(errs, a.customResourceStrategy.validator.ValidateStatusUpdate(ctx, obj, old, a.scale)...) - uNew, ok := obj.(*unstructured.Unstructured) if !ok { - return errs + return field.ErrorList{field.Invalid(field.NewPath(""), obj, fmt.Sprintf("has type %T. Must be a pointer to an Unstructured type", obj))} } uOld, ok := old.(*unstructured.Unstructured) - var oldObject map[string]interface{} if !ok { - oldObject = nil - } else { - oldObject = uOld.Object + return field.ErrorList{field.Invalid(field.NewPath(""), old, fmt.Sprintf("has type %T. Must be a pointer to an Unstructured type", old))} } + var errs field.ErrorList + errs = append(errs, a.customResourceStrategy.validator.ValidateStatusUpdate(ctx, uNew, uOld, a.scale)...) + // ratcheting validation of x-kubernetes-list-type value map and set if newErrs := structurallisttype.ValidateListSetsAndMaps(nil, a.structuralSchema, uNew.Object); len(newErrs) > 0 { - if oldErrs := structurallisttype.ValidateListSetsAndMaps(nil, a.structuralSchema, oldObject); len(oldErrs) == 0 { + if oldErrs := structurallisttype.ValidateListSetsAndMaps(nil, a.structuralSchema, uOld.Object); len(oldErrs) == 0 { errs = append(errs, newErrs...) } } @@ -111,7 +109,7 @@ func (a statusStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Obj if has, err := hasBlockingErr(errs); has { errs = append(errs, err) } else { - err, _ := celValidator.Validate(ctx, nil, a.customResourceStrategy.structuralSchema, uNew.Object, oldObject, celconfig.RuntimeCELCostBudget) + err, _ := celValidator.Validate(ctx, nil, a.customResourceStrategy.structuralSchema, uNew.Object, uOld.Object, celconfig.RuntimeCELCostBudget) errs = append(errs, err...) } } diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/validator.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/validator.go index 82163fa8221..a1a15108d6a 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/validator.go +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/validator.go @@ -27,7 +27,6 @@ import ( "k8s.io/apimachinery/pkg/api/validation" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/sets" apimachineryvalidation "k8s.io/apimachinery/pkg/util/validation" @@ -93,35 +92,18 @@ func validateKubeFinalizerName(stringValue string, fldPath *field.Path) []string return allWarnings } -func (a customResourceValidator) ValidateStatusUpdate(ctx context.Context, obj, old runtime.Object, scale *apiextensions.CustomResourceSubresourceScale) field.ErrorList { - u, ok := obj.(*unstructured.Unstructured) - if !ok { - return field.ErrorList{field.Invalid(field.NewPath(""), u, fmt.Sprintf("has type %T. Must be a pointer to an Unstructured type", u))} - } - oldU, ok := old.(*unstructured.Unstructured) - if !ok { - return field.ErrorList{field.Invalid(field.NewPath(""), old, fmt.Sprintf("has type %T. Must be a pointer to an Unstructured type", u))} - } - objAccessor, err := meta.Accessor(obj) - if err != nil { - return field.ErrorList{field.Invalid(field.NewPath("metadata"), nil, err.Error())} - } - oldAccessor, err := meta.Accessor(old) - if err != nil { - return field.ErrorList{field.Invalid(field.NewPath("metadata"), nil, err.Error())} - } - - if errs := a.ValidateTypeMeta(ctx, u); len(errs) > 0 { +func (a customResourceValidator) ValidateStatusUpdate(ctx context.Context, obj, old *unstructured.Unstructured, scale *apiextensions.CustomResourceSubresourceScale) field.ErrorList { + if errs := a.ValidateTypeMeta(ctx, obj); len(errs) > 0 { return errs } var allErrs field.ErrorList - allErrs = append(allErrs, validation.ValidateObjectMetaAccessorUpdate(objAccessor, oldAccessor, field.NewPath("metadata"))...) - if status, hasStatus := u.UnstructuredContent()["status"]; hasStatus { - allErrs = append(allErrs, apiextensionsvalidation.ValidateCustomResourceUpdate(nil, status, oldU.UnstructuredContent()["status"], a.statusSchemaValidator)...) + allErrs = append(allErrs, validation.ValidateObjectMetaAccessorUpdate(obj, old, field.NewPath("metadata"))...) + if status, hasStatus := obj.UnstructuredContent()["status"]; hasStatus { + allErrs = append(allErrs, apiextensionsvalidation.ValidateCustomResourceUpdate(nil, status, old.UnstructuredContent()["status"], a.statusSchemaValidator)...) } - allErrs = append(allErrs, a.ValidateScaleStatus(ctx, u, scale)...) + allErrs = append(allErrs, a.ValidateScaleStatus(ctx, obj, scale)...) return allErrs } From c5e25637c643b95d3aee6afaa355a9176a8419b7 Mon Sep 17 00:00:00 2001 From: Alexander Zielenski Date: Thu, 19 Oct 2023 07:28:24 -0700 Subject: [PATCH 4/4] fix typo --- .../pkg/registry/customresource/strategy.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/strategy.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/strategy.go index 193acaee283..1f49c60f4e7 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/strategy.go +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/strategy.go @@ -162,7 +162,7 @@ func copyNonMetadata(original map[string]interface{}) map[string]interface{} { func (a customResourceStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { u, ok := obj.(*unstructured.Unstructured) if !ok { - return field.ErrorList{field.Invalid(field.NewPath(""), u, fmt.Sprintf("has type %T. Must be a pointer to an Unstructured type", u))} + return field.ErrorList{field.Invalid(field.NewPath(""), u, fmt.Sprintf("has type %T. Must be a pointer to an Unstructured type", obj))} } var errs field.ErrorList