Files
Ben PerryandGitHub f13599ffdb
Scorecard supply-chain security / Scorecard analysis (push) Failing after 1m10s
Post / coverage (push) Failing after 30m9s
Post / images (amd64) (push) Failing after 3m38s
Post / images (arm64) (push) Failing after 2m50s
Post / image manifest (push) Has been skipped
Post / trigger clusteradm e2e (push) Has been skipped
Close stale issues and PRs / stale (push) Successful in 35s
Refactor common CEL eval functions into shared pkg (#1003)
Signed-off-by: Ben Perry <bhperry94@gmail.com>
2025-05-26 14:36:04 +00:00

72 lines
1.8 KiB
Go

package helpers
import (
"context"
"math"
"github.com/google/cel-go/cel"
"github.com/google/cel-go/common/types/ref"
"k8s.io/klog/v2"
)
// EvaluateSingleExpression evaluates one CEL expression and handles its cost accounting.
// Returns (evalResult, newBudget) if evaluation succeeds, otherwise (nil, -1 or remaining budget).
func EvaluateSingleExpression(
ctx context.Context,
program cel.Program,
budget int64,
expression string,
input any,
) (ref.Val, int64) {
logger := klog.FromContext(ctx)
// Evaluate the expression
evalResult, evalDetails, err := program.ContextEval(ctx, input)
// Cost calculation
ok, rtCost := CostCalculation(ctx, evalDetails, budget, expression)
if !ok {
return nil, -1
}
remainingBudget := budget - rtCost
// Handle evaluation error
if err != nil {
logger.Info("Expression evaluation failed", "rule", expression, "cluster", "err", err)
return nil, remainingBudget
}
return evalResult, remainingBudget
}
// CostCalculation processes the cost details of an evaluation
func CostCalculation(ctx context.Context, evalDetails *cel.EvalDetails, budget int64, expression string) (bool, int64) {
logger := klog.FromContext(ctx)
// Check if cost details are available
if evalDetails == nil {
logger.Info("Runtime cost calculation failed: no evaluation details",
"rule", expression)
return false, -1
}
rtCost := evalDetails.ActualCost()
if rtCost == nil {
logger.Info("Runtime cost calculation failed: no cost information",
"rule", expression)
return false, -1
}
// Validate cost against budget
if *rtCost > math.MaxInt64 || int64(*rtCost) > budget {
logger.Info("Cost budget exceeded",
"rule", expression,
"cost", *rtCost,
"budget", budget)
return false, -1
}
// Safe to convert since we checked for overflow
return true, int64(*rtCost) //nolint:gosec
}