feat: kubesphere 4.0 (#6115)
* feat: kubesphere 4.0 Signed-off-by: ci-bot <ci-bot@kubesphere.io> * feat: kubesphere 4.0 Signed-off-by: ci-bot <ci-bot@kubesphere.io> --------- Signed-off-by: ci-bot <ci-bot@kubesphere.io> Co-authored-by: ks-ci-bot <ks-ci-bot@example.com> Co-authored-by: joyceliu <joyceliu@yunify.com>
This commit is contained in:
committed by
GitHub
parent
b5015ec7b9
commit
447a51f08b
161
vendor/github.com/google/cel-go/cel/program.go
generated
vendored
161
vendor/github.com/google/cel-go/cel/program.go
generated
vendored
@@ -17,11 +17,9 @@ package cel
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math"
|
||||
"sync"
|
||||
|
||||
exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
|
||||
|
||||
celast "github.com/google/cel-go/common/ast"
|
||||
"github.com/google/cel-go/common/types"
|
||||
"github.com/google/cel-go/common/types/ref"
|
||||
"github.com/google/cel-go/interpreter"
|
||||
@@ -31,7 +29,7 @@ import (
|
||||
type Program interface {
|
||||
// Eval returns the result of an evaluation of the Ast and environment against the input vars.
|
||||
//
|
||||
// The vars value may either be an `interpreter.Activation` or a `map[string]interface{}`.
|
||||
// The vars value may either be an `interpreter.Activation` or a `map[string]any`.
|
||||
//
|
||||
// If the `OptTrackState`, `OptTrackCost` or `OptExhaustiveEval` flags are used, the `details` response will
|
||||
// be non-nil. Given this caveat on `details`, the return state from evaluation will be:
|
||||
@@ -43,16 +41,16 @@ type Program interface {
|
||||
// An unsuccessful evaluation is typically the result of a series of incompatible `EnvOption`
|
||||
// or `ProgramOption` values used in the creation of the evaluation environment or executable
|
||||
// program.
|
||||
Eval(interface{}) (ref.Val, *EvalDetails, error)
|
||||
Eval(any) (ref.Val, *EvalDetails, error)
|
||||
|
||||
// ContextEval evaluates the program with a set of input variables and a context object in order
|
||||
// to support cancellation and timeouts. This method must be used in conjunction with the
|
||||
// InterruptCheckFrequency() option for cancellation interrupts to be impact evaluation.
|
||||
//
|
||||
// The vars value may either be an `interpreter.Activation` or `map[string]interface{}`.
|
||||
// The vars value may either be an `interpreter.Activation` or `map[string]any`.
|
||||
//
|
||||
// The output contract for `ContextEval` is otherwise identical to the `Eval` method.
|
||||
ContextEval(context.Context, interface{}) (ref.Val, *EvalDetails, error)
|
||||
ContextEval(context.Context, any) (ref.Val, *EvalDetails, error)
|
||||
}
|
||||
|
||||
// NoVars returns an empty Activation.
|
||||
@@ -63,9 +61,12 @@ func NoVars() interpreter.Activation {
|
||||
// PartialVars returns a PartialActivation which contains variables and a set of AttributePattern
|
||||
// values that indicate variables or parts of variables whose value are not yet known.
|
||||
//
|
||||
// This method relies on manually configured sets of missing attribute patterns. For a method which
|
||||
// infers the missing variables from the input and the configured environment, use Env.PartialVars().
|
||||
//
|
||||
// The `vars` value may either be an interpreter.Activation or any valid input to the
|
||||
// interpreter.NewActivation call.
|
||||
func PartialVars(vars interface{},
|
||||
func PartialVars(vars any,
|
||||
unknowns ...*interpreter.AttributePattern) (interpreter.PartialActivation, error) {
|
||||
return interpreter.NewPartialActivation(vars, unknowns...)
|
||||
}
|
||||
@@ -105,7 +106,7 @@ func (ed *EvalDetails) State() interpreter.EvalState {
|
||||
// ActualCost returns the tracked cost through the course of execution when `CostTracking` is enabled.
|
||||
// Otherwise, returns nil if the cost was not enabled.
|
||||
func (ed *EvalDetails) ActualCost() *uint64 {
|
||||
if ed.costTracker == nil {
|
||||
if ed == nil || ed.costTracker == nil {
|
||||
return nil
|
||||
}
|
||||
cost := ed.costTracker.ActualCost()
|
||||
@@ -129,10 +130,14 @@ type prog struct {
|
||||
// Interpretable configured from an Ast and aggregate decorator set based on program options.
|
||||
interpretable interpreter.Interpretable
|
||||
callCostEstimator interpreter.ActualCostEstimator
|
||||
costOptions []interpreter.CostTrackerOption
|
||||
costLimit *uint64
|
||||
}
|
||||
|
||||
func (p *prog) clone() *prog {
|
||||
costOptsCopy := make([]interpreter.CostTrackerOption, len(p.costOptions))
|
||||
copy(costOptsCopy, p.costOptions)
|
||||
|
||||
return &prog{
|
||||
Env: p.Env,
|
||||
evalOpts: p.evalOpts,
|
||||
@@ -154,9 +159,10 @@ func newProgram(e *Env, ast *Ast, opts []ProgramOption) (Program, error) {
|
||||
// Ensure the default attribute factory is set after the adapter and provider are
|
||||
// configured.
|
||||
p := &prog{
|
||||
Env: e,
|
||||
decorators: []interpreter.InterpretableDecorator{},
|
||||
dispatcher: disp,
|
||||
Env: e,
|
||||
decorators: []interpreter.InterpretableDecorator{},
|
||||
dispatcher: disp,
|
||||
costOptions: []interpreter.CostTrackerOption{},
|
||||
}
|
||||
|
||||
// Configure the program via the ProgramOption values.
|
||||
@@ -170,7 +176,7 @@ func newProgram(e *Env, ast *Ast, opts []ProgramOption) (Program, error) {
|
||||
|
||||
// Add the function bindings created via Function() options.
|
||||
for _, fn := range e.functions {
|
||||
bindings, err := fn.bindings()
|
||||
bindings, err := fn.Bindings()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -207,12 +213,46 @@ func newProgram(e *Env, ast *Ast, opts []ProgramOption) (Program, error) {
|
||||
if len(p.regexOptimizations) > 0 {
|
||||
decorators = append(decorators, interpreter.CompileRegexConstants(p.regexOptimizations...))
|
||||
}
|
||||
// Enable compile-time checking of syntax/cardinality for string.format calls.
|
||||
if p.evalOpts&OptCheckStringFormat == OptCheckStringFormat {
|
||||
var isValidType func(id int64, validTypes ...ref.Type) (bool, error)
|
||||
if ast.IsChecked() {
|
||||
isValidType = func(id int64, validTypes ...ref.Type) (bool, error) {
|
||||
t := ast.typeMap[id]
|
||||
if t.Kind() == DynKind {
|
||||
return true, nil
|
||||
}
|
||||
for _, vt := range validTypes {
|
||||
k, err := typeValueToKind(vt)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if t.Kind() == k {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
} else {
|
||||
// if the AST isn't type-checked, short-circuit validation
|
||||
isValidType = func(id int64, validTypes ...ref.Type) (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
decorators = append(decorators, interpreter.InterpolateFormattedString(isValidType))
|
||||
}
|
||||
|
||||
// Enable exhaustive eval, state tracking and cost tracking last since they require a factory.
|
||||
if p.evalOpts&(OptExhaustiveEval|OptTrackState|OptTrackCost) != 0 {
|
||||
factory := func(state interpreter.EvalState, costTracker *interpreter.CostTracker) (Program, error) {
|
||||
costTracker.Estimator = p.callCostEstimator
|
||||
costTracker.Limit = p.costLimit
|
||||
for _, costOpt := range p.costOptions {
|
||||
err := costOpt(costTracker)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
// Limit capacity to guarantee a reallocation when calling 'append(decs, ...)' below. This
|
||||
// prevents the underlying memory from being shared between factory function calls causing
|
||||
// undesired mutations.
|
||||
@@ -254,10 +294,11 @@ func (p *prog) initInterpretable(ast *Ast, decs []interpreter.InterpretableDecor
|
||||
}
|
||||
|
||||
// When the AST has been checked it contains metadata that can be used to speed up program execution.
|
||||
var checked *exprpb.CheckedExpr
|
||||
checked, err := AstToCheckedExpr(ast)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
checked := &celast.CheckedAST{
|
||||
Expr: ast.Expr(),
|
||||
SourceInfo: ast.SourceInfo(),
|
||||
TypeMap: ast.typeMap,
|
||||
ReferenceMap: ast.refMap,
|
||||
}
|
||||
interpretable, err := p.interpreter.NewInterpretable(checked, decs...)
|
||||
if err != nil {
|
||||
@@ -268,7 +309,7 @@ func (p *prog) initInterpretable(ast *Ast, decs []interpreter.InterpretableDecor
|
||||
}
|
||||
|
||||
// Eval implements the Program interface method.
|
||||
func (p *prog) Eval(input interface{}) (v ref.Val, det *EvalDetails, err error) {
|
||||
func (p *prog) Eval(input any) (v ref.Val, det *EvalDetails, err error) {
|
||||
// Configure error recovery for unexpected panics during evaluation. Note, the use of named
|
||||
// return values makes it possible to modify the error response during the recovery
|
||||
// function.
|
||||
@@ -287,11 +328,11 @@ func (p *prog) Eval(input interface{}) (v ref.Val, det *EvalDetails, err error)
|
||||
switch v := input.(type) {
|
||||
case interpreter.Activation:
|
||||
vars = v
|
||||
case map[string]interface{}:
|
||||
case map[string]any:
|
||||
vars = activationPool.Setup(v)
|
||||
defer activationPool.Put(vars)
|
||||
default:
|
||||
return nil, nil, fmt.Errorf("invalid input, wanted Activation or map[string]interface{}, got: (%T)%v", input, input)
|
||||
return nil, nil, fmt.Errorf("invalid input, wanted Activation or map[string]any, got: (%T)%v", input, input)
|
||||
}
|
||||
if p.defaultVars != nil {
|
||||
vars = interpreter.NewHierarchicalActivation(p.defaultVars, vars)
|
||||
@@ -307,7 +348,7 @@ func (p *prog) Eval(input interface{}) (v ref.Val, det *EvalDetails, err error)
|
||||
}
|
||||
|
||||
// ContextEval implements the Program interface.
|
||||
func (p *prog) ContextEval(ctx context.Context, input interface{}) (ref.Val, *EvalDetails, error) {
|
||||
func (p *prog) ContextEval(ctx context.Context, input any) (ref.Val, *EvalDetails, error) {
|
||||
if ctx == nil {
|
||||
return nil, nil, fmt.Errorf("context can not be nil")
|
||||
}
|
||||
@@ -318,22 +359,17 @@ func (p *prog) ContextEval(ctx context.Context, input interface{}) (ref.Val, *Ev
|
||||
case interpreter.Activation:
|
||||
vars = ctxActivationPool.Setup(v, ctx.Done(), p.interruptCheckFrequency)
|
||||
defer ctxActivationPool.Put(vars)
|
||||
case map[string]interface{}:
|
||||
case map[string]any:
|
||||
rawVars := activationPool.Setup(v)
|
||||
defer activationPool.Put(rawVars)
|
||||
vars = ctxActivationPool.Setup(rawVars, ctx.Done(), p.interruptCheckFrequency)
|
||||
defer ctxActivationPool.Put(vars)
|
||||
default:
|
||||
return nil, nil, fmt.Errorf("invalid input, wanted Activation or map[string]interface{}, got: (%T)%v", input, input)
|
||||
return nil, nil, fmt.Errorf("invalid input, wanted Activation or map[string]any, got: (%T)%v", input, input)
|
||||
}
|
||||
return p.Eval(vars)
|
||||
}
|
||||
|
||||
// Cost implements the Coster interface method.
|
||||
func (p *prog) Cost() (min, max int64) {
|
||||
return estimateCost(p.interpretable)
|
||||
}
|
||||
|
||||
// progFactory is a helper alias for marking a program creation factory function.
|
||||
type progFactory func(interpreter.EvalState, *interpreter.CostTracker) (Program, error)
|
||||
|
||||
@@ -346,7 +382,11 @@ type progGen struct {
|
||||
// the test is successful.
|
||||
func newProgGen(factory progFactory) (Program, error) {
|
||||
// Test the factory to make sure that configuration errors are spotted at config
|
||||
_, err := factory(interpreter.NewEvalState(), &interpreter.CostTracker{})
|
||||
tracker, err := interpreter.NewCostTracker(nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, err = factory(interpreter.NewEvalState(), tracker)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -354,12 +394,15 @@ func newProgGen(factory progFactory) (Program, error) {
|
||||
}
|
||||
|
||||
// Eval implements the Program interface method.
|
||||
func (gen *progGen) Eval(input interface{}) (ref.Val, *EvalDetails, error) {
|
||||
func (gen *progGen) Eval(input any) (ref.Val, *EvalDetails, error) {
|
||||
// The factory based Eval() differs from the standard evaluation model in that it generates a
|
||||
// new EvalState instance for each call to ensure that unique evaluations yield unique stateful
|
||||
// results.
|
||||
state := interpreter.NewEvalState()
|
||||
costTracker := &interpreter.CostTracker{}
|
||||
costTracker, err := interpreter.NewCostTracker(nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
det := &EvalDetails{state: state, costTracker: costTracker}
|
||||
|
||||
// Generate a new instance of the interpretable using the factory configured during the call to
|
||||
@@ -379,7 +422,7 @@ func (gen *progGen) Eval(input interface{}) (ref.Val, *EvalDetails, error) {
|
||||
}
|
||||
|
||||
// ContextEval implements the Program interface method.
|
||||
func (gen *progGen) ContextEval(ctx context.Context, input interface{}) (ref.Val, *EvalDetails, error) {
|
||||
func (gen *progGen) ContextEval(ctx context.Context, input any) (ref.Val, *EvalDetails, error) {
|
||||
if ctx == nil {
|
||||
return nil, nil, fmt.Errorf("context can not be nil")
|
||||
}
|
||||
@@ -387,7 +430,10 @@ func (gen *progGen) ContextEval(ctx context.Context, input interface{}) (ref.Val
|
||||
// new EvalState instance for each call to ensure that unique evaluations yield unique stateful
|
||||
// results.
|
||||
state := interpreter.NewEvalState()
|
||||
costTracker := &interpreter.CostTracker{}
|
||||
costTracker, err := interpreter.NewCostTracker(nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
det := &EvalDetails{state: state, costTracker: costTracker}
|
||||
|
||||
// Generate a new instance of the interpretable using the factory configured during the call to
|
||||
@@ -406,29 +452,6 @@ func (gen *progGen) ContextEval(ctx context.Context, input interface{}) (ref.Val
|
||||
return v, det, nil
|
||||
}
|
||||
|
||||
// Cost implements the Coster interface method.
|
||||
func (gen *progGen) Cost() (min, max int64) {
|
||||
// Use an empty state value since no evaluation is performed.
|
||||
p, err := gen.factory(emptyEvalState, nil)
|
||||
if err != nil {
|
||||
return 0, math.MaxInt64
|
||||
}
|
||||
return estimateCost(p)
|
||||
}
|
||||
|
||||
// EstimateCost returns the heuristic cost interval for the program.
|
||||
func EstimateCost(p Program) (min, max int64) {
|
||||
return estimateCost(p)
|
||||
}
|
||||
|
||||
func estimateCost(i interface{}) (min, max int64) {
|
||||
c, ok := i.(interpreter.Coster)
|
||||
if !ok {
|
||||
return 0, math.MaxInt64
|
||||
}
|
||||
return c.Cost()
|
||||
}
|
||||
|
||||
type ctxEvalActivation struct {
|
||||
parent interpreter.Activation
|
||||
interrupt <-chan struct{}
|
||||
@@ -438,7 +461,7 @@ type ctxEvalActivation struct {
|
||||
|
||||
// ResolveName implements the Activation interface method, but adds a special #interrupted variable
|
||||
// which is capable of testing whether a 'done' signal is provided from a context.Context channel.
|
||||
func (a *ctxEvalActivation) ResolveName(name string) (interface{}, bool) {
|
||||
func (a *ctxEvalActivation) ResolveName(name string) (any, bool) {
|
||||
if name == "#interrupted" {
|
||||
a.interruptCheckCount++
|
||||
if a.interruptCheckCount%a.interruptCheckFrequency == 0 {
|
||||
@@ -461,7 +484,7 @@ func (a *ctxEvalActivation) Parent() interpreter.Activation {
|
||||
func newCtxEvalActivationPool() *ctxEvalActivationPool {
|
||||
return &ctxEvalActivationPool{
|
||||
Pool: sync.Pool{
|
||||
New: func() interface{} {
|
||||
New: func() any {
|
||||
return &ctxEvalActivation{}
|
||||
},
|
||||
},
|
||||
@@ -483,21 +506,21 @@ func (p *ctxEvalActivationPool) Setup(vars interpreter.Activation, done <-chan s
|
||||
}
|
||||
|
||||
type evalActivation struct {
|
||||
vars map[string]interface{}
|
||||
lazyVars map[string]interface{}
|
||||
vars map[string]any
|
||||
lazyVars map[string]any
|
||||
}
|
||||
|
||||
// ResolveName looks up the value of the input variable name, if found.
|
||||
//
|
||||
// Lazy bindings may be supplied within the map-based input in either of the following forms:
|
||||
// - func() interface{}
|
||||
// - func() any
|
||||
// - func() ref.Val
|
||||
//
|
||||
// The lazy binding will only be invoked once per evaluation.
|
||||
//
|
||||
// Values which are not represented as ref.Val types on input may be adapted to a ref.Val using
|
||||
// the ref.TypeAdapter configured in the environment.
|
||||
func (a *evalActivation) ResolveName(name string) (interface{}, bool) {
|
||||
// the types.Adapter configured in the environment.
|
||||
func (a *evalActivation) ResolveName(name string) (any, bool) {
|
||||
v, found := a.vars[name]
|
||||
if !found {
|
||||
return nil, false
|
||||
@@ -510,7 +533,7 @@ func (a *evalActivation) ResolveName(name string) (interface{}, bool) {
|
||||
lazy := obj()
|
||||
a.lazyVars[name] = lazy
|
||||
return lazy, true
|
||||
case func() interface{}:
|
||||
case func() any:
|
||||
if resolved, found := a.lazyVars[name]; found {
|
||||
return resolved, true
|
||||
}
|
||||
@@ -530,8 +553,8 @@ func (a *evalActivation) Parent() interpreter.Activation {
|
||||
func newEvalActivationPool() *evalActivationPool {
|
||||
return &evalActivationPool{
|
||||
Pool: sync.Pool{
|
||||
New: func() interface{} {
|
||||
return &evalActivation{lazyVars: make(map[string]interface{})}
|
||||
New: func() any {
|
||||
return &evalActivation{lazyVars: make(map[string]any)}
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -542,13 +565,13 @@ type evalActivationPool struct {
|
||||
}
|
||||
|
||||
// Setup initializes a pooled Activation object with the map input.
|
||||
func (p *evalActivationPool) Setup(vars map[string]interface{}) *evalActivation {
|
||||
func (p *evalActivationPool) Setup(vars map[string]any) *evalActivation {
|
||||
a := p.Pool.Get().(*evalActivation)
|
||||
a.vars = vars
|
||||
return a
|
||||
}
|
||||
|
||||
func (p *evalActivationPool) Put(value interface{}) {
|
||||
func (p *evalActivationPool) Put(value any) {
|
||||
a := value.(*evalActivation)
|
||||
for k := range a.lazyVars {
|
||||
delete(a.lazyVars, k)
|
||||
@@ -559,7 +582,7 @@ func (p *evalActivationPool) Put(value interface{}) {
|
||||
var (
|
||||
emptyEvalState = interpreter.NewEvalState()
|
||||
|
||||
// activationPool is an internally managed pool of Activation values that wrap map[string]interface{} inputs
|
||||
// activationPool is an internally managed pool of Activation values that wrap map[string]any inputs
|
||||
activationPool = newEvalActivationPool()
|
||||
|
||||
// ctxActivationPool is an internally managed pool of Activation values that expose a special #interrupted variable
|
||||
|
||||
Reference in New Issue
Block a user