Merge pull request #116103 from cici37/context

Apply context cancellation to ValidatingAdmissionPolicy
This commit is contained in:
Kubernetes Prow Robot 2023-03-07 07:20:56 -08:00 committed by GitHub
commit 1030693d4e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 63 additions and 31 deletions

View File

@ -17,6 +17,7 @@ limitations under the License.
package cel package cel
import ( import (
"context"
"errors" "errors"
"fmt" "fmt"
"math" "math"
@ -119,7 +120,7 @@ func objectToResolveVal(r runtime.Object) (interface{}, error) {
// ForInput evaluates the compiled CEL expressions converting them into CELEvaluations // ForInput evaluates the compiled CEL expressions converting them into CELEvaluations
// errors per evaluation are returned on the Evaluation object // errors per evaluation are returned on the Evaluation object
// runtimeCELCostBudget was added for testing purpose only. Callers should always use const RuntimeCELCostBudget from k8s.io/apiserver/pkg/apis/cel/config.go as input. // runtimeCELCostBudget was added for testing purpose only. Callers should always use const RuntimeCELCostBudget from k8s.io/apiserver/pkg/apis/cel/config.go as input.
func (f *filter) ForInput(versionedAttr *generic.VersionedAttributes, request *admissionv1.AdmissionRequest, inputs OptionalVariableBindings, runtimeCELCostBudget int64) ([]EvaluationResult, error) { func (f *filter) ForInput(ctx context.Context, versionedAttr *generic.VersionedAttributes, request *admissionv1.AdmissionRequest, inputs OptionalVariableBindings, runtimeCELCostBudget int64) ([]EvaluationResult, error) {
// TODO: replace unstructured with ref.Val for CEL variables when native type support is available // TODO: replace unstructured with ref.Val for CEL variables when native type support is available
evaluations := make([]EvaluationResult, len(f.compilationResults)) evaluations := make([]EvaluationResult, len(f.compilationResults))
var err error var err error
@ -171,7 +172,7 @@ func (f *filter) ForInput(versionedAttr *generic.VersionedAttributes, request *a
continue continue
} }
t1 := time.Now() t1 := time.Now()
evalResult, evalDetails, err := compilationResult.Program.Eval(va) evalResult, evalDetails, err := compilationResult.Program.ContextEval(ctx, va)
elapsed := time.Since(t1) elapsed := time.Since(t1)
evaluation.Elapsed = elapsed evaluation.Elapsed = elapsed
if evalDetails == nil { if evalDetails == nil {

View File

@ -661,7 +661,8 @@ func TestFilter(t *testing.T) {
} }
optionalVars := OptionalVariableBindings{VersionedParams: tc.params, Authorizer: tc.authorizer} optionalVars := OptionalVariableBindings{VersionedParams: tc.params, Authorizer: tc.authorizer}
evalResults, err := f.ForInput(versionedAttr, CreateAdmissionRequest(versionedAttr.Attributes), optionalVars, celconfig.RuntimeCELCostBudget) ctx := context.TODO()
evalResults, err := f.ForInput(ctx, versionedAttr, CreateAdmissionRequest(versionedAttr.Attributes), optionalVars, celconfig.RuntimeCELCostBudget)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
@ -766,7 +767,8 @@ func TestRuntimeCELCostBudget(t *testing.T) {
tc.testRuntimeCELCostBudget = celconfig.RuntimeCELCostBudget tc.testRuntimeCELCostBudget = celconfig.RuntimeCELCostBudget
} }
optionalVars := OptionalVariableBindings{VersionedParams: tc.params, Authorizer: tc.authorizer} optionalVars := OptionalVariableBindings{VersionedParams: tc.params, Authorizer: tc.authorizer}
evalResults, err := f.ForInput(versionedAttr, CreateAdmissionRequest(versionedAttr.Attributes), optionalVars, tc.testRuntimeCELCostBudget) ctx := context.TODO()
evalResults, err := f.ForInput(ctx, versionedAttr, CreateAdmissionRequest(versionedAttr.Attributes), optionalVars, tc.testRuntimeCELCostBudget)
if tc.exceedBudget && err == nil { if tc.exceedBudget && err == nil {
t.Errorf("Expected RuntimeCELCostBudge to be exceeded but got nil") t.Errorf("Expected RuntimeCELCostBudge to be exceeded but got nil")
} }

View File

@ -17,6 +17,7 @@ limitations under the License.
package cel package cel
import ( import (
"context"
"time" "time"
"github.com/google/cel-go/cel" "github.com/google/cel-go/cel"
@ -93,7 +94,7 @@ type OptionalVariableBindings struct {
type Filter interface { type Filter interface {
// ForInput converts compiled CEL-typed values into evaluated CEL-typed values // ForInput converts compiled CEL-typed values into evaluated CEL-typed values
// runtimeCELCostBudget was added for testing purpose only. Callers should always use const RuntimeCELCostBudget from k8s.io/apiserver/pkg/apis/cel/config.go as input. // runtimeCELCostBudget was added for testing purpose only. Callers should always use const RuntimeCELCostBudget from k8s.io/apiserver/pkg/apis/cel/config.go as input.
ForInput(versionedAttr *generic.VersionedAttributes, request *v1.AdmissionRequest, optionalVars OptionalVariableBindings, runtimeCELCostBudget int64) ([]EvaluationResult, error) ForInput(ctx context.Context, versionedAttr *generic.VersionedAttributes, request *v1.AdmissionRequest, optionalVars OptionalVariableBindings, runtimeCELCostBudget int64) ([]EvaluationResult, error)
// CompilationErrors returns a list of errors from the compilation of the evaluator // CompilationErrors returns a list of errors from the compilation of the evaluator
CompilationErrors() []error CompilationErrors() []error

View File

@ -253,7 +253,7 @@ type fakeFilter struct {
keyId string keyId string
} }
func (f *fakeFilter) ForInput(versionedAttr *whgeneric.VersionedAttributes, request *admissionv1.AdmissionRequest, inputs cel.OptionalVariableBindings, runtimeCELCostBudget int64) ([]cel.EvaluationResult, error) { func (f *fakeFilter) ForInput(ctx context.Context, versionedAttr *whgeneric.VersionedAttributes, request *admissionv1.AdmissionRequest, inputs cel.OptionalVariableBindings, runtimeCELCostBudget int64) ([]cel.EvaluationResult, error) {
return []cel.EvaluationResult{}, nil return []cel.EvaluationResult{}, nil
} }
@ -265,10 +265,10 @@ var _ Validator = &fakeValidator{}
type fakeValidator struct { type fakeValidator struct {
validationFilter, auditAnnotationFilter *fakeFilter validationFilter, auditAnnotationFilter *fakeFilter
ValidateFunc func(versionedAttr *whgeneric.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult ValidateFunc func(ctx context.Context, versionedAttr *whgeneric.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult
} }
func (f *fakeValidator) RegisterDefinition(definition *v1alpha1.ValidatingAdmissionPolicy, validateFunc func(versionedAttr *whgeneric.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult) { func (f *fakeValidator) RegisterDefinition(definition *v1alpha1.ValidatingAdmissionPolicy, validateFunc func(ctx context.Context, versionedAttr *whgeneric.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult) {
//Key must be something that we can decipher from the inputs to Validate so using message which will be on the validationCondition object of evalResult //Key must be something that we can decipher from the inputs to Validate so using message which will be on the validationCondition object of evalResult
var key string var key string
if len(definition.Spec.Validations) > 0 { if len(definition.Spec.Validations) > 0 {
@ -285,8 +285,8 @@ func (f *fakeValidator) RegisterDefinition(definition *v1alpha1.ValidatingAdmiss
validatorMap[key] = f validatorMap[key] = f
} }
func (f *fakeValidator) Validate(versionedAttr *whgeneric.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult { func (f *fakeValidator) Validate(ctx context.Context, versionedAttr *whgeneric.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult {
return f.ValidateFunc(versionedAttr, versionedParams, runtimeCELCostBudget) return f.ValidateFunc(ctx, versionedAttr, versionedParams, runtimeCELCostBudget)
} }
var _ Matcher = &fakeMatcher{} var _ Matcher = &fakeMatcher{}
@ -769,7 +769,7 @@ func TestBasicPolicyDefinitionFailure(t *testing.T) {
} }
}) })
validator.RegisterDefinition(denyPolicy, func(versionedAttr *whgeneric.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult { validator.RegisterDefinition(denyPolicy, func(ctx context.Context, versionedAttr *whgeneric.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult {
return ValidateResult{ return ValidateResult{
Decisions: []PolicyDecision{ Decisions: []PolicyDecision{
{ {
@ -839,7 +839,7 @@ func TestDefinitionDoesntMatch(t *testing.T) {
} }
}) })
validator.RegisterDefinition(denyPolicy, func(versionedAttr *whgeneric.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult { validator.RegisterDefinition(denyPolicy, func(ctx context.Context, versionedAttr *whgeneric.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult {
return ValidateResult{ return ValidateResult{
Decisions: []PolicyDecision{ Decisions: []PolicyDecision{
{ {
@ -952,7 +952,7 @@ func TestReconfigureBinding(t *testing.T) {
} }
}) })
validator.RegisterDefinition(denyPolicy, func(versionedAttr *whgeneric.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult { validator.RegisterDefinition(denyPolicy, func(ctx context.Context, versionedAttr *whgeneric.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult {
return ValidateResult{ return ValidateResult{
Decisions: []PolicyDecision{ Decisions: []PolicyDecision{
{ {
@ -1062,7 +1062,7 @@ func TestRemoveDefinition(t *testing.T) {
} }
}) })
validator.RegisterDefinition(denyPolicy, func(versionedAttr *whgeneric.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult { validator.RegisterDefinition(denyPolicy, func(ctx context.Context, versionedAttr *whgeneric.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult {
return ValidateResult{ return ValidateResult{
Decisions: []PolicyDecision{ Decisions: []PolicyDecision{
{ {
@ -1131,7 +1131,7 @@ func TestRemoveBinding(t *testing.T) {
} }
}) })
validator.RegisterDefinition(denyPolicy, func(versionedAttr *whgeneric.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult { validator.RegisterDefinition(denyPolicy, func(ctx context.Context, versionedAttr *whgeneric.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult {
return ValidateResult{ return ValidateResult{
Decisions: []PolicyDecision{ Decisions: []PolicyDecision{
{ {
@ -1241,7 +1241,7 @@ func TestInvalidParamSourceInstanceName(t *testing.T) {
} }
}) })
validator.RegisterDefinition(denyPolicy, func(versionedAttr *whgeneric.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult { validator.RegisterDefinition(denyPolicy, func(ctx context.Context, versionedAttr *whgeneric.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult {
return ValidateResult{ return ValidateResult{
Decisions: []PolicyDecision{ Decisions: []PolicyDecision{
{ {
@ -1309,7 +1309,7 @@ func TestEmptyParamSource(t *testing.T) {
} }
}) })
validator.RegisterDefinition(denyPolicy, func(versionedAttr *whgeneric.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult { validator.RegisterDefinition(denyPolicy, func(ctx context.Context, versionedAttr *whgeneric.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult {
return ValidateResult{ return ValidateResult{
Decisions: []PolicyDecision{ Decisions: []PolicyDecision{
{ {
@ -1411,7 +1411,7 @@ func TestMultiplePoliciesSharedParamType(t *testing.T) {
} }
}) })
validator1.RegisterDefinition(&policy1, func(versionedAttr *whgeneric.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult { validator1.RegisterDefinition(&policy1, func(ctx context.Context, versionedAttr *whgeneric.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult {
evaluations1.Add(1) evaluations1.Add(1)
return ValidateResult{ return ValidateResult{
Decisions: []PolicyDecision{ Decisions: []PolicyDecision{
@ -1430,7 +1430,7 @@ func TestMultiplePoliciesSharedParamType(t *testing.T) {
} }
}) })
validator2.RegisterDefinition(&policy2, func(versionedAttr *whgeneric.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult { validator2.RegisterDefinition(&policy2, func(ctx context.Context, versionedAttr *whgeneric.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult {
evaluations2.Add(1) evaluations2.Add(1)
return ValidateResult{ return ValidateResult{
Decisions: []PolicyDecision{ Decisions: []PolicyDecision{
@ -1540,7 +1540,7 @@ func TestNativeTypeParam(t *testing.T) {
} }
}) })
validator.RegisterDefinition(&nativeTypeParamPolicy, func(versionedAttr *whgeneric.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult { validator.RegisterDefinition(&nativeTypeParamPolicy, func(ctx context.Context, versionedAttr *whgeneric.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult {
evaluations.Add(1) evaluations.Add(1)
if _, ok := versionedParams.(*v1.ConfigMap); ok { if _, ok := versionedParams.(*v1.ConfigMap); ok {
return ValidateResult{ return ValidateResult{
@ -1622,7 +1622,7 @@ func TestAuditValidationAction(t *testing.T) {
} }
}) })
validator.RegisterDefinition(denyPolicy, func(versionedAttr *whgeneric.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult { validator.RegisterDefinition(denyPolicy, func(ctx context.Context, versionedAttr *whgeneric.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult {
return ValidateResult{ return ValidateResult{
Decisions: []PolicyDecision{ Decisions: []PolicyDecision{
{ {
@ -1693,7 +1693,7 @@ func TestWarnValidationAction(t *testing.T) {
} }
}) })
validator.RegisterDefinition(denyPolicy, func(versionedAttr *whgeneric.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult { validator.RegisterDefinition(denyPolicy, func(ctx context.Context, versionedAttr *whgeneric.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult {
return ValidateResult{ return ValidateResult{
Decisions: []PolicyDecision{ Decisions: []PolicyDecision{
{ {
@ -1752,7 +1752,7 @@ func TestAllValidationActions(t *testing.T) {
} }
}) })
validator.RegisterDefinition(denyPolicy, func(versionedAttr *whgeneric.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult { validator.RegisterDefinition(denyPolicy, func(ctx context.Context, versionedAttr *whgeneric.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult {
return ValidateResult{ return ValidateResult{
Decisions: []PolicyDecision{ Decisions: []PolicyDecision{
{ {
@ -1823,7 +1823,7 @@ func TestAuditAnnotations(t *testing.T) {
} }
}) })
validator.RegisterDefinition(denyPolicy, func(versionedAttr *whgeneric.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult { validator.RegisterDefinition(denyPolicy, func(ctx context.Context, versionedAttr *whgeneric.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult {
o, err := meta.Accessor(versionedParams) o, err := meta.Accessor(versionedParams)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)

View File

@ -329,7 +329,7 @@ func (c *celAdmissionController) Validate(
versionedAttr = va versionedAttr = va
} }
validationResult := bindingInfo.validator.Validate(versionedAttr, param, celconfig.RuntimeCELCostBudget) validationResult := bindingInfo.validator.Validate(ctx, versionedAttr, param, celconfig.RuntimeCELCostBudget)
if err != nil { if err != nil {
// runtime error. Apply failure policy // runtime error. Apply failure policy
wrappedError := fmt.Errorf("failed to evaluate CEL expression: %w", err) wrappedError := fmt.Errorf("failed to evaluate CEL expression: %w", err)

View File

@ -17,6 +17,8 @@ limitations under the License.
package validatingadmissionpolicy package validatingadmissionpolicy
import ( import (
"context"
celgo "github.com/google/cel-go/cel" celgo "github.com/google/cel-go/cel"
"k8s.io/api/admissionregistration/v1alpha1" "k8s.io/api/admissionregistration/v1alpha1"
@ -84,5 +86,5 @@ type ValidateResult struct {
type Validator interface { type Validator interface {
// Validate is used to take cel evaluations and convert into decisions // Validate is used to take cel evaluations and convert into decisions
// runtimeCELCostBudget was added for testing purpose only. Callers should always use const RuntimeCELCostBudget from k8s.io/apiserver/pkg/apis/cel/config.go as input. // runtimeCELCostBudget was added for testing purpose only. Callers should always use const RuntimeCELCostBudget from k8s.io/apiserver/pkg/apis/cel/config.go as input.
Validate(versionedAttr *generic.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult Validate(ctx context.Context, versionedAttr *generic.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult
} }

View File

@ -17,6 +17,7 @@ limitations under the License.
package validatingadmissionpolicy package validatingadmissionpolicy
import ( import (
"context"
"fmt" "fmt"
"strings" "strings"
@ -65,7 +66,7 @@ func auditAnnotationEvaluationForError(f v1.FailurePolicyType) PolicyAuditAnnota
// Validate takes a list of Evaluation and a failure policy and converts them into actionable PolicyDecisions // Validate takes a list of Evaluation and a failure policy and converts them into actionable PolicyDecisions
// runtimeCELCostBudget was added for testing purpose only. Callers should always use const RuntimeCELCostBudget from k8s.io/apiserver/pkg/apis/cel/config.go as input. // runtimeCELCostBudget was added for testing purpose only. Callers should always use const RuntimeCELCostBudget from k8s.io/apiserver/pkg/apis/cel/config.go as input.
func (v *validator) Validate(versionedAttr *generic.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult { func (v *validator) Validate(ctx context.Context, versionedAttr *generic.VersionedAttributes, versionedParams runtime.Object, runtimeCELCostBudget int64) ValidateResult {
var f v1.FailurePolicyType var f v1.FailurePolicyType
if v.failPolicy == nil { if v.failPolicy == nil {
f = v1.Fail f = v1.Fail
@ -74,7 +75,7 @@ func (v *validator) Validate(versionedAttr *generic.VersionedAttributes, version
} }
optionalVars := cel.OptionalVariableBindings{VersionedParams: versionedParams, Authorizer: v.authorizer} optionalVars := cel.OptionalVariableBindings{VersionedParams: versionedParams, Authorizer: v.authorizer}
evalResults, err := v.validationFilter.ForInput(versionedAttr, cel.CreateAdmissionRequest(versionedAttr.Attributes), optionalVars, runtimeCELCostBudget) evalResults, err := v.validationFilter.ForInput(ctx, versionedAttr, cel.CreateAdmissionRequest(versionedAttr.Attributes), optionalVars, runtimeCELCostBudget)
if err != nil { if err != nil {
return ValidateResult{ return ValidateResult{
Decisions: []PolicyDecision{ Decisions: []PolicyDecision{
@ -123,7 +124,7 @@ func (v *validator) Validate(versionedAttr *generic.VersionedAttributes, version
} }
options := cel.OptionalVariableBindings{VersionedParams: versionedParams} options := cel.OptionalVariableBindings{VersionedParams: versionedParams}
auditAnnotationEvalResults, err := v.auditAnnotationFilter.ForInput(versionedAttr, cel.CreateAdmissionRequest(versionedAttr.Attributes), options, runtimeCELCostBudget) auditAnnotationEvalResults, err := v.auditAnnotationFilter.ForInput(ctx, versionedAttr, cel.CreateAdmissionRequest(versionedAttr.Attributes), options, runtimeCELCostBudget)
if err != nil { if err != nil {
return ValidateResult{ return ValidateResult{
Decisions: []PolicyDecision{ Decisions: []PolicyDecision{

View File

@ -17,6 +17,7 @@ limitations under the License.
package validatingadmissionpolicy package validatingadmissionpolicy
import ( import (
"context"
"errors" "errors"
"fmt" "fmt"
"strings" "strings"
@ -43,7 +44,7 @@ type fakeCelFilter struct {
throwError bool throwError bool
} }
func (f *fakeCelFilter) ForInput(*generic.VersionedAttributes, *admissionv1.AdmissionRequest, cel.OptionalVariableBindings, int64) ([]cel.EvaluationResult, error) { func (f *fakeCelFilter) ForInput(context.Context, *generic.VersionedAttributes, *admissionv1.AdmissionRequest, cel.OptionalVariableBindings, int64) ([]cel.EvaluationResult, error) {
if f.throwError { if f.throwError {
return nil, errors.New("test error") return nil, errors.New("test error")
} }
@ -586,7 +587,8 @@ func TestValidate(t *testing.T) {
throwError: tc.throwError, throwError: tc.throwError,
}, },
} }
validateResult := v.Validate(fakeVersionedAttr, nil, celconfig.RuntimeCELCostBudget) ctx := context.TODO()
validateResult := v.Validate(ctx, fakeVersionedAttr, nil, celconfig.RuntimeCELCostBudget)
require.Equal(t, len(validateResult.Decisions), len(tc.policyDecision)) require.Equal(t, len(validateResult.Decisions), len(tc.policyDecision))
@ -618,3 +620,26 @@ func TestValidate(t *testing.T) {
}) })
} }
} }
func TestContextCanceled(t *testing.T) {
fail := v1.Fail
fakeAttr := admission.NewAttributesRecord(nil, nil, schema.GroupVersionKind{}, "default", "foo", schema.GroupVersionResource{}, "", admission.Create, nil, false, nil)
fakeVersionedAttr, _ := generic.NewVersionedAttributes(fakeAttr, schema.GroupVersionKind{}, nil)
fc := cel.NewFilterCompiler()
f := fc.Compile([]cel.ExpressionAccessor{&ValidationCondition{Expression: "[1,2,3,4,5,6,7,8,9,10].map(x, [1,2,3,4,5,6,7,8,9,10].map(y, x*y)) == []"}}, cel.OptionalVariableDeclarations{HasParams: false, HasAuthorizer: false}, celconfig.PerCallLimit)
v := validator{
failPolicy: &fail,
validationFilter: f,
auditAnnotationFilter: &fakeCelFilter{
evaluations: nil,
throwError: false,
},
}
ctx, cancel := context.WithCancel(context.TODO())
cancel()
validationResult := v.Validate(ctx, fakeVersionedAttr, nil, celconfig.RuntimeCELCostBudget)
if len(validationResult.Decisions) != 1 || !strings.Contains(validationResult.Decisions[0].Message, "operation interrupted") {
t.Errorf("Expected 'operation interrupted' but got %v", validationResult.Decisions)
}
}