const ScopedVarName … const OldScopedVarName … type CompilationResult … type EnvLoader … // NewExpressionsEnvLoader creates an EnvLoader that always uses the NewExpressions environment type. func NewExpressionsEnvLoader() EnvLoader { … } // StoredExpressionsEnvLoader creates an EnvLoader that always uses the StoredExpressions environment type. func StoredExpressionsEnvLoader() EnvLoader { … } type alwaysNewEnvLoader … func (pe alwaysNewEnvLoader) RuleEnv(envSet *environment.EnvSet, _ string) *cel.Env { … } func (pe alwaysNewEnvLoader) MessageExpressionEnv(envSet *environment.EnvSet, _ string) *cel.Env { … } // Compile compiles all the XValidations rules (without recursing into the schema) and returns a slice containing a // CompilationResult for each ValidationRule, or an error. declType is expected to be a CEL DeclType corresponding // to the structural schema. // Each CompilationResult may contain: // - non-nil Program, nil Error: The program was compiled successfully // - 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 from k8s.io/apiserver/pkg/apis/cel/config.go as input. // baseEnv is used as the base CEL environment, see common.BaseEnvironment. func Compile(s *schema.Structural, declType *apiservercel.DeclType, perCallLimit uint64, baseEnvSet *environment.EnvSet, envLoader EnvLoader) ([]CompilationResult, error) { … } func prepareEnvSet(baseEnvSet *environment.EnvSet, declType *apiservercel.DeclType) (oldSelfEnvSet *environment.EnvSet, optionalOldSelfEnvSet *environment.EnvSet, err error) { … } func compileRule(s *schema.Structural, rule apiextensions.ValidationRule, envSet *environment.EnvSet, envLoader EnvLoader, estimator *library.CostEstimator, maxCardinality uint64, perCallLimit uint64) (compilationResult CompilationResult) { … } // generateUniqueSelfTypeName creates a placeholder type name to use in a CEL programs for cases // where we do not wish to expose a stable type name to CEL validator rule authors. For this to effectively prevent // developers from depending on the generated name (i.e. using it in CEL programs), it must be changed each time a // CRD is created or updated. func generateUniqueSelfTypeName() string { … } func newCostEstimator(root *apiservercel.DeclType) *library.CostEstimator { … } type sizeEstimator … func (c *sizeEstimator) EstimateSize(element checker.AstNode) *checker.SizeEstimate { … } func (c *sizeEstimator) EstimateCallCost(function, overloadID string, target *checker.AstNode, args []checker.AstNode) *checker.CallEstimate { … } // maxCardinality returns the maximum number of times data conforming to the minimum size given could possibly exist in // an object serialized to JSON. For cases where a schema is contained under map or array schemas of unbounded // size, this can be used as an estimate as the worst case number of times data matching the schema could be repeated. // Note that this only assumes a single comma between data elements, so if the schema is contained under only maps, // this estimates a higher cardinality that would be possible. DeclType.MinSerializedSize is meant to be passed to // this function. func maxCardinality(minSize int64) uint64 { … }