From 1f4a9dd9187899a46a4fb86b52af50198da59aaf Mon Sep 17 00:00:00 2001 From: Cici Huang Date: Sun, 5 Mar 2023 20:43:58 +0000 Subject: [PATCH] Update CRD validation rules path accordingly. --- .../apiextensions/validation/validation.go | 3 +- .../schema/cel/celcoststability_test.go | 7 ++-- .../pkg/apiserver/schema/cel/compilation.go | 23 ++---------- .../apiserver/schema/cel/compilation_test.go | 5 ++- .../pkg/apiserver/schema/cel/validation.go | 3 +- .../apiserver/schema/cel/validation_test.go | 37 ++++++++++--------- .../apiserver/schema/defaulting/validation.go | 7 ++-- .../apiserver/validation/validation_test.go | 7 ++-- .../customresource/status_strategy.go | 4 +- .../pkg/registry/customresource/strategy.go | 7 ++-- .../k8s.io/apiserver/pkg/apis/cel/config.go | 5 +-- .../src/k8s.io/apiserver/pkg/cel/limits.go | 4 +- 12 files changed, 53 insertions(+), 59 deletions(-) diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation/validation.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation/validation.go index ab69389e675..2ef5e7a1fc5 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation/validation.go +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation/validation.go @@ -35,6 +35,7 @@ import ( "k8s.io/apimachinery/pkg/util/sets" utilvalidation "k8s.io/apimachinery/pkg/util/validation" "k8s.io/apimachinery/pkg/util/validation/field" + celconfig "k8s.io/apiserver/pkg/apis/cel" apiservercel "k8s.io/apiserver/pkg/cel" "k8s.io/apiserver/pkg/util/webhook" @@ -1026,7 +1027,7 @@ func ValidateCustomResourceDefinitionOpenAPISchema(schema *apiextensions.JSONSch } else if typeInfo == nil { allErrs.CELErrors = append(allErrs.CELErrors, field.InternalError(fldPath.Child("x-kubernetes-validations"), fmt.Errorf("internal error: failed to retrieve type information for x-kubernetes-validations"))) } else { - compResults, err := cel.Compile(typeInfo.Schema, typeInfo.DeclType, cel.PerCallLimit) + compResults, err := cel.Compile(typeInfo.Schema, typeInfo.DeclType, celconfig.PerCallLimit) if err != nil { allErrs.CELErrors = append(allErrs.CELErrors, field.InternalError(fldPath.Child("x-kubernetes-validations"), err)) } else { diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel/celcoststability_test.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel/celcoststability_test.go index 22e9aa6e060..656f8898a66 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel/celcoststability_test.go +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel/celcoststability_test.go @@ -24,6 +24,7 @@ import ( "k8s.io/apiextensions-apiserver/pkg/apiserver/schema" "k8s.io/apimachinery/pkg/util/validation/field" + celconfig "k8s.io/apiserver/pkg/apis/cel" ) func TestCelCostStability(t *testing.T) { @@ -1096,16 +1097,16 @@ func TestCelCostStability(t *testing.T) { t.Run(testName, func(t *testing.T) { t.Parallel() s := withRule(*tt.schema, validRule) - celValidator := NewValidator(&s, true, PerCallLimit) + celValidator := NewValidator(&s, true, celconfig.PerCallLimit) if celValidator == nil { t.Fatal("expected non nil validator") } ctx := context.TODO() - errs, remainingBudegt := celValidator.Validate(ctx, field.NewPath("root"), &s, tt.obj, nil, RuntimeCELCostBudget) + errs, remainingBudegt := celValidator.Validate(ctx, field.NewPath("root"), &s, tt.obj, nil, celconfig.RuntimeCELCostBudget) for _, err := range errs { t.Errorf("unexpected error: %v", err) } - rtCost := RuntimeCELCostBudget - remainingBudegt + rtCost := celconfig.RuntimeCELCostBudget - remainingBudegt if rtCost != expectedCost { t.Fatalf("runtime cost %d does not match expected runtime cost %d", rtCost, expectedCost) } diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel/compilation.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel/compilation.go index 177671f098d..1f0c9861d1f 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel/compilation.go +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel/compilation.go @@ -27,6 +27,7 @@ import ( apiextensions "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apiextensions-apiserver/pkg/apiserver/schema" + celconfig "k8s.io/apiserver/pkg/apis/cel" apiservercel "k8s.io/apiserver/pkg/cel" "k8s.io/apiserver/pkg/cel/library" "k8s.io/apiserver/pkg/cel/metrics" @@ -40,22 +41,6 @@ const ( // OldScopedVarName is the variable name assigned to the existing value of the locally scoped data element of a // CEL validation expression. OldScopedVarName = "oldSelf" - - // PerCallLimit specify the actual cost limit per CEL validation call - // current PerCallLimit gives roughly 0.1 second for each expression validation call - PerCallLimit = 1000000 - - // RuntimeCELCostBudget is the overall cost budget for runtime CEL validation cost per CustomResource - // current RuntimeCELCostBudget gives roughly 1 seconds for CR validation - RuntimeCELCostBudget = 10000000 - - // checkFrequency configures the number of iterations within a comprehension to evaluate - // before checking whether the function evaluation has been interrupted - checkFrequency = 100 - - // maxRequestSizeBytes is the maximum size of a request to the API server - // TODO(DangerOnTheRanger): wire in MaxRequestBodyBytes from apiserver/pkg/server/options/server_run_options.go to make this configurable - maxRequestSizeBytes = apiservercel.DefaultMaxRequestSizeBytes ) // CompilationResult represents the cel compilation result for one rule @@ -103,7 +88,7 @@ func getBaseEnv() (*cel.Env, error) { // - nil Program, non-nil Error: Compilation resulted in an error // - nil Program, nil Error: The provided rule was empty so compilation was not attempted // -// perCallLimit was added for testing purpose only. Callers should always use const PerCallLimit as input. +// perCallLimit was added for testing purpose only. Callers should always use const PerCallLimit from k8s.io/apiserver/pkg/apis/cel/config.go as input. func Compile(s *schema.Structural, declType *apiservercel.DeclType, perCallLimit uint64) ([]CompilationResult, error) { t := time.Now() defer func() { @@ -195,7 +180,7 @@ func compileRule(rule apiextensions.ValidationRule, env *cel.Env, perCallLimit u cel.CostLimit(perCallLimit), cel.CostTracking(estimator), cel.OptimizeRegex(library.ExtensionLibRegexOptimizations...), - cel.InterruptCheckFrequency(checkFrequency), + cel.InterruptCheckFrequency(celconfig.CheckFrequency), ) if err != nil { compilationResult.Error = &apiservercel.Error{Type: apiservercel.ErrorTypeInvalid, Detail: "program instantiation failed: " + err.Error()} @@ -274,5 +259,5 @@ func (c *sizeEstimator) EstimateCallCost(function, overloadID string, target *ch // this function. func maxCardinality(minSize int64) uint64 { sz := minSize + 1 // assume at least one comma between elements - return uint64(maxRequestSizeBytes / sz) + return uint64(celconfig.MaxRequestSizeBytes / sz) } diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel/compilation_test.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel/compilation_test.go index f9f4f567503..0634d463baf 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel/compilation_test.go +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel/compilation_test.go @@ -27,6 +27,7 @@ import ( apiextensions "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apiextensions-apiserver/pkg/apiserver/schema" "k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel/model" + celconfig "k8s.io/apiserver/pkg/apis/cel" ) const ( @@ -645,7 +646,7 @@ func TestCelCompilation(t *testing.T) { for _, tt := range cases { t.Run(tt.name, func(t *testing.T) { - compilationResults, err := Compile(&tt.input, model.SchemaDeclType(&tt.input, false), PerCallLimit) + compilationResults, err := Compile(&tt.input, model.SchemaDeclType(&tt.input, false), celconfig.PerCallLimit) if err != nil { t.Errorf("Expected no error, but got: %v", err) } @@ -1081,7 +1082,7 @@ func genMapWithCustomItemRule(item *schema.Structural, rule string) func(maxProp // if expectedCostExceedsLimit is non-zero. Typically, only expectedCost or expectedCostExceedsLimit is non-zero, not both. func schemaChecker(schema *schema.Structural, expectedCost uint64, expectedCostExceedsLimit uint64, t *testing.T) func(t *testing.T) { return func(t *testing.T) { - compilationResults, err := Compile(schema, model.SchemaDeclType(schema, false), PerCallLimit) + compilationResults, err := Compile(schema, model.SchemaDeclType(schema, false), celconfig.PerCallLimit) if err != nil { t.Errorf("Expected no error, got: %v", err) } diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel/validation.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel/validation.go index 2a039b6b58e..dfa5822245c 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel/validation.go +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel/validation.go @@ -64,7 +64,7 @@ type Validator struct { // of the Structural schema and returns a custom resource validator that contains nested // validators for all items, properties and additionalProperties that transitively contain validator rules. // Returns nil if there are no validator rules in the Structural schema. May return a validator containing only errors. -// Adding perCallLimit as input arg for testing purpose only. Callers should always use const PerCallLimit as input +// Adding perCallLimit as input arg for testing purpose only. Callers should always use const PerCallLimit from k8s.io/apiserver/pkg/apis/cel/config.go as input func NewValidator(s *schema.Structural, isResourceRoot bool, perCallLimit uint64) *Validator { if !hasXValidations(s) { return nil @@ -75,6 +75,7 @@ func NewValidator(s *schema.Structural, isResourceRoot bool, perCallLimit uint64 // validator creates a Validator for all x-kubernetes-validations at the level of the provided schema and lower and // returns the Validator if any x-kubernetes-validations exist in the schema, or nil if no x-kubernetes-validations // exist. declType is expected to be a CEL DeclType corresponding to the structural schema. +// perCallLimit was added for testing purpose only. Callers should always use const PerCallLimit from k8s.io/apiserver/pkg/apis/cel/config.go as input. func validator(s *schema.Structural, isResourceRoot bool, declType *cel.DeclType, perCallLimit uint64) *Validator { compiledRules, err := Compile(s, declType, perCallLimit) var itemsValidator, additionalPropertiesValidator *Validator diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel/validation_test.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel/validation_test.go index b2d1fb07580..e1c885d9b7e 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel/validation_test.go +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel/validation_test.go @@ -30,6 +30,7 @@ import ( "k8s.io/apiextensions-apiserver/pkg/apiserver/schema" "k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel/model" "k8s.io/apimachinery/pkg/util/validation/field" + celconfig "k8s.io/apiserver/pkg/apis/cel" ) // TestValidationExpressions tests CEL integration with custom resource values and OpenAPIv3. @@ -1766,7 +1767,7 @@ func TestValidationExpressions(t *testing.T) { t.Run(tests[i].name, func(t *testing.T) { t.Parallel() tt := tests[i] - tt.costBudget = RuntimeCELCostBudget + tt.costBudget = celconfig.RuntimeCELCostBudget ctx := context.TODO() for j := range tt.valid { validRule := tt.valid[j] @@ -1777,7 +1778,7 @@ func TestValidationExpressions(t *testing.T) { t.Run(testName, func(t *testing.T) { t.Parallel() s := withRule(*tt.schema, validRule) - celValidator := validator(&s, tt.isRoot, model.SchemaDeclType(&s, tt.isRoot), PerCallLimit) + celValidator := validator(&s, tt.isRoot, model.SchemaDeclType(&s, tt.isRoot), celconfig.PerCallLimit) if celValidator == nil { t.Fatal("expected non nil validator") } @@ -1801,7 +1802,7 @@ func TestValidationExpressions(t *testing.T) { } t.Run(testName, func(t *testing.T) { s := withRule(*tt.schema, rule) - celValidator := NewValidator(&s, true, PerCallLimit) + celValidator := NewValidator(&s, true, celconfig.PerCallLimit) if celValidator == nil { t.Fatal("expected non nil validator") } @@ -2015,7 +2016,7 @@ func TestValidationExpressionsAtSchemaLevels(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() ctx := context.TODO() - celValidator := validator(tt.schema, true, model.SchemaDeclType(tt.schema, true), PerCallLimit) + celValidator := validator(tt.schema, true, model.SchemaDeclType(tt.schema, true), celconfig.PerCallLimit) if celValidator == nil { t.Fatal("expected non nil validator") } @@ -2082,7 +2083,7 @@ func TestCELValidationLimit(t *testing.T) { t.Run(validRule, func(t *testing.T) { t.Parallel() s := withRule(*tt.schema, validRule) - celValidator := validator(&s, false, model.SchemaDeclType(&s, false), PerCallLimit) + celValidator := validator(&s, false, model.SchemaDeclType(&s, false), celconfig.PerCallLimit) // test with cost budget exceeded errs, _ := celValidator.Validate(ctx, field.NewPath("root"), &s, tt.obj, nil, 0) @@ -2107,7 +2108,7 @@ func TestCELValidationLimit(t *testing.T) { if celValidator == nil { t.Fatal("expected non nil validator") } - errs, _ = celValidator.Validate(ctx, field.NewPath("root"), &s, tt.obj, nil, RuntimeCELCostBudget) + errs, _ = celValidator.Validate(ctx, field.NewPath("root"), &s, tt.obj, nil, celconfig.RuntimeCELCostBudget) for _, err := range errs { if err.Type == field.ErrorTypeInvalid && strings.Contains(err.Error(), "no further validation rules will be run due to call cost exceeds limit for rule") { found = true @@ -2150,11 +2151,11 @@ func TestCELValidationContextCancellation(t *testing.T) { t.Run(tt.name, func(t *testing.T) { ctx := context.TODO() s := withRule(*tt.schema, tt.rule) - celValidator := NewValidator(&s, true, PerCallLimit) + celValidator := NewValidator(&s, true, celconfig.PerCallLimit) if celValidator == nil { t.Fatal("expected non nil validator") } - errs, _ := celValidator.Validate(ctx, field.NewPath("root"), &s, tt.obj, nil, RuntimeCELCostBudget) + errs, _ := celValidator.Validate(ctx, field.NewPath("root"), &s, tt.obj, nil, celconfig.RuntimeCELCostBudget) for _, err := range errs { t.Errorf("unexpected error: %v", err) } @@ -2163,7 +2164,7 @@ func TestCELValidationContextCancellation(t *testing.T) { found := false evalCtx, cancel := context.WithTimeout(ctx, time.Microsecond) cancel() - errs, _ = celValidator.Validate(evalCtx, field.NewPath("root"), &s, tt.obj, nil, RuntimeCELCostBudget) + errs, _ = celValidator.Validate(evalCtx, field.NewPath("root"), &s, tt.obj, nil, celconfig.RuntimeCELCostBudget) for _, err := range errs { if err.Type == field.ErrorTypeInvalid && strings.Contains(err.Error(), "operation interrupted") { found = true @@ -2208,7 +2209,7 @@ func TestCELMaxRecursionDepth(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - tt.costBudget = RuntimeCELCostBudget + tt.costBudget = celconfig.RuntimeCELCostBudget ctx := context.TODO() for j := range tt.valid { validRule := tt.valid[j] @@ -2216,7 +2217,7 @@ func TestCELMaxRecursionDepth(t *testing.T) { t.Run(testName, func(t *testing.T) { t.Parallel() s := withRule(*tt.schema, validRule) - celValidator := validator(&s, tt.isRoot, model.SchemaDeclType(&s, tt.isRoot), PerCallLimit) + celValidator := validator(&s, tt.isRoot, model.SchemaDeclType(&s, tt.isRoot), celconfig.PerCallLimit) if celValidator == nil { t.Fatal("expected non nil validator") } @@ -2240,7 +2241,7 @@ func TestCELMaxRecursionDepth(t *testing.T) { } t.Run(testName, func(t *testing.T) { s := withRule(*tt.schema, rule) - celValidator := NewValidator(&s, true, PerCallLimit) + celValidator := NewValidator(&s, true, celconfig.PerCallLimit) if celValidator == nil { t.Fatal("expected non nil validator") } @@ -2285,12 +2286,12 @@ func BenchmarkCELValidationWithContext(b *testing.B) { b.Run(tt.name, func(b *testing.B) { ctx := context.TODO() s := withRule(*tt.schema, tt.rule) - celValidator := NewValidator(&s, true, PerCallLimit) + celValidator := NewValidator(&s, true, celconfig.PerCallLimit) if celValidator == nil { b.Fatal("expected non nil validator") } for i := 0; i < b.N; i++ { - errs, _ := celValidator.Validate(ctx, field.NewPath("root"), &s, tt.obj, nil, RuntimeCELCostBudget) + errs, _ := celValidator.Validate(ctx, field.NewPath("root"), &s, tt.obj, nil, celconfig.RuntimeCELCostBudget) for _, err := range errs { b.Fatalf("validation failed: %v", err) } @@ -2325,14 +2326,14 @@ func BenchmarkCELValidationWithCancelledContext(b *testing.B) { b.Run(tt.name, func(b *testing.B) { ctx := context.TODO() s := withRule(*tt.schema, tt.rule) - celValidator := NewValidator(&s, true, PerCallLimit) + celValidator := NewValidator(&s, true, celconfig.PerCallLimit) if celValidator == nil { b.Fatal("expected non nil validator") } for i := 0; i < b.N; i++ { evalCtx, cancel := context.WithTimeout(ctx, time.Microsecond) cancel() - errs, _ := celValidator.Validate(evalCtx, field.NewPath("root"), &s, tt.obj, nil, RuntimeCELCostBudget) + errs, _ := celValidator.Validate(evalCtx, field.NewPath("root"), &s, tt.obj, nil, celconfig.RuntimeCELCostBudget) //found := false //for _, err := range errs { // if err.Type == field.ErrorTypeInvalid && strings.Contains(err.Error(), "operation interrupted") { @@ -2379,7 +2380,7 @@ func BenchmarkCELValidationWithAndWithoutOldSelfReference(b *testing.B) { }, }, } - validator := NewValidator(s, true, PerCallLimit) + validator := NewValidator(s, true, celconfig.PerCallLimit) if validator == nil { b.Fatal("expected non nil validator") } @@ -2390,7 +2391,7 @@ func BenchmarkCELValidationWithAndWithoutOldSelfReference(b *testing.B) { b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { - errs, _ := validator.Validate(ctx, root, s, obj, obj, RuntimeCELCostBudget) + errs, _ := validator.Validate(ctx, root, s, obj, obj, celconfig.RuntimeCELCostBudget) for _, err := range errs { b.Errorf("unexpected error: %v", err) } diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/schema/defaulting/validation.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/schema/defaulting/validation.go index f89500b60bd..cd7c6e07558 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/schema/defaulting/validation.go +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/schema/defaulting/validation.go @@ -32,6 +32,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" + celconfig "k8s.io/apiserver/pkg/apis/cel" ) // ValidateDefaults checks that default values validate and are properly pruned. @@ -50,7 +51,7 @@ func ValidateDefaults(ctx context.Context, pth *field.Path, s *structuralschema. } } - allErr, error, _ := validate(ctx, pth, s, s, f, false, requirePrunedDefaults, cel.RuntimeCELCostBudget) + allErr, error, _ := validate(ctx, pth, s, s, f, false, requirePrunedDefaults, celconfig.RuntimeCELCostBudget) return allErr, error } @@ -91,7 +92,7 @@ func validate(ctx context.Context, pth *field.Path, s *structuralschema.Structur allErrs = append(allErrs, field.Invalid(pth.Child("default"), s.Default.Object, fmt.Sprintf("must result in valid metadata: %v", errs.ToAggregate()))) } else if errs := apiservervalidation.ValidateCustomResource(pth.Child("default"), s.Default.Object, validator); len(errs) > 0 { allErrs = append(allErrs, errs...) - } else if celValidator := cel.NewValidator(s, isResourceRoot, cel.PerCallLimit); celValidator != nil { + } else if celValidator := cel.NewValidator(s, isResourceRoot, celconfig.PerCallLimit); celValidator != nil { celErrs, rmCost := celValidator.Validate(ctx, pth.Child("default"), s, s.Default.Object, s.Default.Object, remainingCost) remainingCost = rmCost allErrs = append(allErrs, celErrs...) @@ -116,7 +117,7 @@ func validate(ctx context.Context, pth *field.Path, s *structuralschema.Structur allErrs = append(allErrs, errs...) } else if errs := apiservervalidation.ValidateCustomResource(pth.Child("default"), s.Default.Object, validator); len(errs) > 0 { allErrs = append(allErrs, errs...) - } else if celValidator := cel.NewValidator(s, isResourceRoot, cel.PerCallLimit); celValidator != nil { + } else if celValidator := cel.NewValidator(s, isResourceRoot, celconfig.PerCallLimit); celValidator != nil { celErrs, rmCost := celValidator.Validate(ctx, pth.Child("default"), s, s.Default.Object, s.Default.Object, remainingCost) remainingCost = rmCost allErrs = append(allErrs, celErrs...) diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/validation/validation_test.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/validation/validation_test.go index 49b1cab79d2..7bbeba3eae5 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/validation/validation_test.go +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/validation/validation_test.go @@ -42,6 +42,7 @@ import ( "k8s.io/apimachinery/pkg/runtime/serializer" "k8s.io/apimachinery/pkg/util/json" "k8s.io/apimachinery/pkg/util/sets" + celconfig "k8s.io/apiserver/pkg/apis/cel" ) // TestRoundTrip checks the conversion to go-openapi types. @@ -608,7 +609,7 @@ func TestValidateCustomResource(t *testing.T) { if err != nil { t.Fatal(err) } - celValidator := cel.NewValidator(structural, false, cel.PerCallLimit) + celValidator := cel.NewValidator(structural, false, celconfig.PerCallLimit) for i, obj := range tt.objects { var oldObject interface{} if len(tt.oldObjects) == len(tt.objects) { @@ -617,14 +618,14 @@ func TestValidateCustomResource(t *testing.T) { if errs := ValidateCustomResource(nil, obj, validator); len(errs) > 0 { t.Errorf("unexpected validation error for %v: %v", obj, errs) } - errs, _ := celValidator.Validate(context.TODO(), nil, structural, obj, oldObject, cel.RuntimeCELCostBudget) + errs, _ := celValidator.Validate(context.TODO(), nil, structural, obj, oldObject, celconfig.RuntimeCELCostBudget) if len(errs) > 0 { t.Errorf(errs.ToAggregate().Error()) } } for i, failingObject := range tt.failingObjects { errs := ValidateCustomResource(nil, failingObject.object, validator) - celErrs, _ := celValidator.Validate(context.TODO(), nil, structural, failingObject.object, failingObject.oldObject, cel.RuntimeCELCostBudget) + celErrs, _ := celValidator.Validate(context.TODO(), nil, structural, failingObject.object, failingObject.oldObject, celconfig.RuntimeCELCostBudget) errs = append(errs, celErrs...) if len(errs) == 0 { t.Errorf("missing error for %v", failingObject.object) 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 efd9b2dff55..8d3796ac9af 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 @@ -21,11 +21,11 @@ import ( "sigs.k8s.io/structured-merge-diff/v4/fieldpath" - "k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel" structurallisttype "k8s.io/apiextensions-apiserver/pkg/apiserver/schema/listtype" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" + celconfig "k8s.io/apiserver/pkg/apis/cel" ) type statusStrategy struct { @@ -113,7 +113,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.structuralSchemas[v], uNew.Object, oldObject, cel.RuntimeCELCostBudget) + err, _ := celValidator.Validate(ctx, nil, a.customResourceStrategy.structuralSchemas[v], uNew.Object, oldObject, celconfig.RuntimeCELCostBudget) errs = append(errs, err...) } } 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 926806af7fc..92a688a56d7 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 @@ -35,6 +35,7 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/validation/field" + celconfig "k8s.io/apiserver/pkg/apis/cel" "k8s.io/apiserver/pkg/features" apiserverstorage "k8s.io/apiserver/pkg/storage" "k8s.io/apiserver/pkg/storage/names" @@ -61,7 +62,7 @@ func NewStrategy(typer runtime.ObjectTyper, namespaceScoped bool, kind schema.Gr celValidators := map[string]*cel.Validator{} if utilfeature.DefaultFeatureGate.Enabled(features.CustomResourceValidationExpressions) { for name, s := range structuralSchemas { - v := cel.NewValidator(s, true, cel.PerCallLimit) // CEL programs are compiled and cached here + v := cel.NewValidator(s, true, celconfig.PerCallLimit) // CEL programs are compiled and cached here if v != nil { celValidators[name] = v } @@ -178,7 +179,7 @@ func (a customResourceStrategy) Validate(ctx context.Context, obj runtime.Object if has, err := hasBlockingErr(errs); has { errs = append(errs, err) } else { - err, _ := celValidator.Validate(ctx, nil, a.structuralSchemas[v], u.Object, nil, cel.RuntimeCELCostBudget) + err, _ := celValidator.Validate(ctx, nil, a.structuralSchemas[v], u.Object, nil, celconfig.RuntimeCELCostBudget) errs = append(errs, err...) } } @@ -235,7 +236,7 @@ func (a customResourceStrategy) ValidateUpdate(ctx context.Context, obj, old run if has, err := hasBlockingErr(errs); has { errs = append(errs, err) } else { - err, _ := celValidator.Validate(ctx, nil, a.structuralSchemas[v], uNew.Object, uOld.Object, cel.RuntimeCELCostBudget) + err, _ := celValidator.Validate(ctx, nil, a.structuralSchemas[v], uNew.Object, uOld.Object, celconfig.RuntimeCELCostBudget) errs = append(errs, err...) } } diff --git a/staging/src/k8s.io/apiserver/pkg/apis/cel/config.go b/staging/src/k8s.io/apiserver/pkg/apis/cel/config.go index 34f5f037b85..4e66868c14e 100644 --- a/staging/src/k8s.io/apiserver/pkg/apis/cel/config.go +++ b/staging/src/k8s.io/apiserver/pkg/apis/cel/config.go @@ -16,8 +16,6 @@ limitations under the License. package cel -import apiservercel "k8s.io/apiserver/pkg/cel" - const ( // PerCallLimit specify the actual cost limit per CEL validation call // current PerCallLimit gives roughly 0.1 second for each expression validation call @@ -33,5 +31,6 @@ const ( // MaxRequestSizeBytes is the maximum size of a request to the API server // TODO(DangerOnTheRanger): wire in MaxRequestBodyBytes from apiserver/pkg/server/options/server_run_options.go to make this configurable - MaxRequestSizeBytes = apiservercel.DefaultMaxRequestSizeBytes + // Note that even if server_run_options.go becomes configurable in the future, this cost constant should be fixed and it should be the max allowed request size for the server + MaxRequestSizeBytes = int64(3 * 1024 * 1024) ) diff --git a/staging/src/k8s.io/apiserver/pkg/cel/limits.go b/staging/src/k8s.io/apiserver/pkg/cel/limits.go index 7bdb958d05c..65c6ad5f3a3 100644 --- a/staging/src/k8s.io/apiserver/pkg/cel/limits.go +++ b/staging/src/k8s.io/apiserver/pkg/cel/limits.go @@ -16,9 +16,11 @@ limitations under the License. package cel +import celconfig "k8s.io/apiserver/pkg/apis/cel" + const ( // DefaultMaxRequestSizeBytes is the size of the largest request that will be accepted - DefaultMaxRequestSizeBytes = int64(3 * 1024 * 1024) + DefaultMaxRequestSizeBytes = celconfig.MaxRequestSizeBytes // MaxDurationSizeJSON // OpenAPI duration strings follow RFC 3339, section 5.6 - see the comment on maxDatetimeSizeJSON