make Err wrap one or zero error.

This commit is contained in:
Jiahui Feng 2024-04-25 17:59:32 -07:00 committed by Cici Huang
parent b846c39047
commit ce45a82346
5 changed files with 18 additions and 18 deletions

View File

@ -163,12 +163,12 @@ type variableDeclEnvs map[OptionalVariableDeclarations]*environment.EnvSet
// CompileCELExpression returns a compiled CEL expression. // CompileCELExpression returns a compiled CEL expression.
// perCallLimit was added for testing purpose only. Callers should always use const PerCallLimit from k8s.io/apiserver/pkg/apis/cel/config.go 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 (c compiler) CompileCELExpression(expressionAccessor ExpressionAccessor, options OptionalVariableDeclarations, envType environment.Type) CompilationResult { func (c compiler) CompileCELExpression(expressionAccessor ExpressionAccessor, options OptionalVariableDeclarations, envType environment.Type) CompilationResult {
resultError := func(errorString string, errType apiservercel.ErrorType, errors ...error) CompilationResult { resultError := func(errorString string, errType apiservercel.ErrorType, cause error) CompilationResult {
return CompilationResult{ return CompilationResult{
Error: &apiservercel.Error{ Error: &apiservercel.Error{
Type: errType, Type: errType,
Detail: errorString, Detail: errorString,
Errors: errors, Cause: cause,
}, },
ExpressionAccessor: expressionAccessor, ExpressionAccessor: expressionAccessor,
} }
@ -176,7 +176,7 @@ func (c compiler) CompileCELExpression(expressionAccessor ExpressionAccessor, op
env, err := c.varEnvs[options].Env(envType) env, err := c.varEnvs[options].Env(envType)
if err != nil { if err != nil {
return resultError(fmt.Sprintf("unexpected error loading CEL environment: %v", err), apiservercel.ErrorTypeInternal) return resultError(fmt.Sprintf("unexpected error loading CEL environment: %v", err), apiservercel.ErrorTypeInternal, nil)
} }
ast, issues := env.Compile(expressionAccessor.GetExpression()) ast, issues := env.Compile(expressionAccessor.GetExpression())
@ -199,19 +199,19 @@ func (c compiler) CompileCELExpression(expressionAccessor ExpressionAccessor, op
reason = fmt.Sprintf("must evaluate to one of %v", returnTypes) reason = fmt.Sprintf("must evaluate to one of %v", returnTypes)
} }
return resultError(reason, apiservercel.ErrorTypeInvalid) return resultError(reason, apiservercel.ErrorTypeInvalid, nil)
} }
_, err = cel.AstToCheckedExpr(ast) _, err = cel.AstToCheckedExpr(ast)
if err != nil { if err != nil {
// should be impossible since env.Compile returned no issues // should be impossible since env.Compile returned no issues
return resultError("unexpected compilation error: "+err.Error(), apiservercel.ErrorTypeInternal) return resultError("unexpected compilation error: "+err.Error(), apiservercel.ErrorTypeInternal, nil)
} }
prog, err := env.Program(ast, prog, err := env.Program(ast,
cel.InterruptCheckFrequency(celconfig.CheckFrequency), cel.InterruptCheckFrequency(celconfig.CheckFrequency),
) )
if err != nil { if err != nil {
return resultError("program instantiation failed: "+err.Error(), apiservercel.ErrorTypeInternal) return resultError("program instantiation failed: "+err.Error(), apiservercel.ErrorTypeInternal, nil)
} }
return CompilationResult{ return CompilationResult{
Program: prog, Program: prog,

View File

@ -192,7 +192,7 @@ func (f *filter) ForInput(ctx context.Context, versionedAttr *admission.Versione
evaluation.Error = &cel.Error{ evaluation.Error = &cel.Error{
Type: cel.ErrorTypeInvalid, Type: cel.ErrorTypeInvalid,
Detail: fmt.Sprintf("compilation error: %v", compilationResult.Error), Detail: fmt.Sprintf("compilation error: %v", compilationResult.Error),
Errors: []error{compilationResult.Error}, Cause: compilationResult.Error,
} }
continue continue
} }
@ -212,7 +212,7 @@ func (f *filter) ForInput(ctx context.Context, versionedAttr *admission.Versione
return nil, -1, &cel.Error{ return nil, -1, &cel.Error{
Type: cel.ErrorTypeInvalid, Type: cel.ErrorTypeInvalid,
Detail: fmt.Sprintf("validation failed due to running out of cost budget, no further validation rules will be run"), Detail: fmt.Sprintf("validation failed due to running out of cost budget, no further validation rules will be run"),
Errors: []error{cel.ErrOutOfBudget}, Cause: cel.ErrOutOfBudget,
} }
} }
remainingBudget -= compositionCost remainingBudget -= compositionCost
@ -230,14 +230,14 @@ func (f *filter) ForInput(ctx context.Context, versionedAttr *admission.Versione
return nil, -1, &cel.Error{ return nil, -1, &cel.Error{
Type: cel.ErrorTypeInvalid, Type: cel.ErrorTypeInvalid,
Detail: fmt.Sprintf("runtime cost could not be calculated for expression: %v, no further expression will be run", compilationResult.ExpressionAccessor.GetExpression()), Detail: fmt.Sprintf("runtime cost could not be calculated for expression: %v, no further expression will be run", compilationResult.ExpressionAccessor.GetExpression()),
Errors: []error{cel.ErrOutOfBudget}, Cause: cel.ErrOutOfBudget,
} }
} else { } else {
if *rtCost > math.MaxInt64 || int64(*rtCost) > remainingBudget { if *rtCost > math.MaxInt64 || int64(*rtCost) > remainingBudget {
return nil, -1, &cel.Error{ return nil, -1, &cel.Error{
Type: cel.ErrorTypeInvalid, Type: cel.ErrorTypeInvalid,
Detail: fmt.Sprintf("validation failed due to running out of cost budget, no further validation rules will be run"), Detail: fmt.Sprintf("validation failed due to running out of cost budget, no further validation rules will be run"),
Errors: []error{cel.ErrOutOfBudget}, Cause: cel.ErrOutOfBudget,
} }
} }
remainingBudget -= int64(*rtCost) remainingBudget -= int64(*rtCost)

View File

@ -53,7 +53,7 @@ func (f *fakeCelFilter) ForInput(ctx context.Context, versionedAttr *admission.V
return nil, -1, &apiservercel.Error{ return nil, -1, &apiservercel.Error{
Type: apiservercel.ErrorTypeInvalid, Type: apiservercel.ErrorTypeInvalid,
Detail: fmt.Sprintf("validation failed due to running out of cost budget, no further validation rules will be run"), Detail: fmt.Sprintf("validation failed due to running out of cost budget, no further validation rules will be run"),
Errors: []error{apiservercel.ErrOutOfBudget}, Cause: apiservercel.ErrOutOfBudget,
} }
} }
if f.throwError { if f.throwError {

View File

@ -53,9 +53,9 @@ type Error struct {
Type ErrorType Type ErrorType
Detail string Detail string
// Errors are optional wrapped errors that can be useful to // Cause is an optional wrapped errors that can be useful to
// programmatically retrieve detailed errors. // programmatically retrieve detailed errors.
Errors []error Cause error
} }
var _ error = &Error{} var _ error = &Error{}
@ -77,9 +77,9 @@ func (v *Error) Is(err error) bool {
return false return false
} }
// Unwrap returns wrapped errors. // Unwrap returns the wrapped Cause.
func (v *Error) Unwrap() []error { func (v *Error) Unwrap() error {
return v.Errors return v.Cause
} }
// ErrorType is a machine-readable value providing more detail about why // ErrorType is a machine-readable value providing more detail about why

View File

@ -27,7 +27,7 @@ func TestOutOfBudgetError(t *testing.T) {
err := &Error{ err := &Error{
Type: ErrorTypeInvalid, Type: ErrorTypeInvalid,
Detail: "expression out of budget", Detail: "expression out of budget",
Errors: []error{ErrOutOfBudget}, Cause: ErrOutOfBudget,
} }
if !errors.Is(err, ErrOutOfBudget) { if !errors.Is(err, ErrOutOfBudget) {
t.Errorf("unexpected %v is not %v", err, ErrOutOfBudget) t.Errorf("unexpected %v is not %v", err, ErrOutOfBudget)
@ -45,7 +45,7 @@ func TestCompilationError(t *testing.T) {
err := &Error{ err := &Error{
Type: ErrorTypeInvalid, Type: ErrorTypeInvalid,
Detail: "fake compilation failed", Detail: "fake compilation failed",
Errors: []error{NewCompilationError(issues)}, Cause: NewCompilationError(issues),
} }
if !errors.Is(err, ErrCompilation) { if !errors.Is(err, ErrCompilation) {
t.Errorf("unexpected %v is not %v", err, ErrCompilation) t.Errorf("unexpected %v is not %v", err, ErrCompilation)