Documentation
¶
Overview ¶
Copyright 2026 The KubeVela Authors.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
Package cel evaluates CEL expressions embedded in properties with $( ).
It knows no roots by name. A host declares the roots its expressions may read and supplies a resolver for each, which answers every read before anything is evaluated, so no expression performs I/O.
A tree is parsed once into a Plan, which serves each stage that needs it: Reads for dependencies and status, Check for admission, and Eval to resolve and evaluate.
Copyright 2026 The KubeVela Authors.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
Copyright 2026 The KubeVela Authors.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
Copyright 2026 The KubeVela Authors.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
Index ¶
- Constants
- Variables
- func DeclType(v cue.Value, name string) *apiservercel.DeclType
- func ElementsCompatible(src *cel.Type, dst cue.Value) (bool, string, string)
- func KindFits(src, dst cue.Kind) bool
- func OptionalPath(v cue.Value, path []string) (bool, error)
- func Typed(v interface{}) interface{}
- type CheckError
- type CheckErrors
- type Checker
- type CheckerFunc
- type Engine
- func (e *Engine) DynEnv() *cel.Env
- func (e *Engine) Eval(env *cel.Env, expr string, in map[string]interface{}) (interface{}, error)
- func (e *Engine) EvalProperty(env *cel.Env, raw string, in map[string]interface{}) (interface{}, error)
- func (e *Engine) EvalTree(ctx context.Context, tree interface{}, resolvers map[string]Resolver, ...) (interface{}, error)
- func (e *Engine) OutputType(env *cel.Env, expr string) (*cel.Type, error)
- func (e *Engine) Plan(tree interface{}) (*Plan, error)
- func (e *Engine) PlanJSON(doc []byte) (*Plan, error)
- func (e *Engine) PropertyReferences(expr string) ([]template.Reference, error)
- func (e *Engine) References(env *cel.Env, expr string) ([]template.Reference, error)
- func (e *Engine) TypedEnv(key string, decls func() (map[string]*apiservercel.DeclType, error)) (*cel.Env, error)
- type Expression
- type MayBeAbsent
- type Plan
- func (p *Plan) Check(permitted []string, checkers map[string]Checker) []CheckError
- func (p *Plan) CheckTypes(env *cel.Env, target Target, opts TypeOptions) []CheckError
- func (p *Plan) Eval(ctx context.Context, resolvers map[string]Resolver, opts TreeOptions) (interface{}, error)
- func (p *Plan) Expressions() []Expression
- func (p *Plan) Reads(root string) []Read
- type Qualifier
- type Read
- type Resolver
- type ResolverFunc
- type Root
- type Target
- type TargetFunc
- type TreeOptions
- type TypeMismatch
- type TypeOptions
Constants ¶
const QualifiedKey = "$q"
QualifiedKey holds, inside a delivered value, what each qualifier call on it returns, keyed by template.Call. A chained call nests the same way: at("a").in("b") is the "in:b" entry inside the "at:a" entry.
Variables ¶
var ErrNotReady = errors.New("not ready")
ErrNotReady marks a resolver's error as waiting rather than failing: what a read names does not exist yet. A resolver wraps it; a host checks it with errors.Is and tries again later rather than reporting a fault.
var Unknown interface{} = unknownValue{}
Unknown is what a resolver answers when its root has no value in this evaluation, as in a dry run. TreeOptions.Unknown renders reads of it.
Functions ¶
func DeclType ¶
func DeclType(v cue.Value, name string) *apiservercel.DeclType
DeclType translates a CUE schema into a CEL declared type, named name.
The name must be unique across everything declared in one environment: the type provider keeps the first type registered under a name, so a second schema sharing it would have its fields reported as undefined.
func ElementsCompatible ¶
ElementsCompatible reports whether a collection-valued expression can feed a collection-valued parameter.
A CUE kind says only "list", so a kind check cannot tell list(string) from a `[...int]` parameter. CEL carries the element type, so the elements are compared here.
It judges collections only, and only where both sides are concrete. A struct, an untyped region and a `dyn` all fail open, because that is where a legitimate widening is most likely and a false rejection is unfixable by the expression's author. The outer kind check has already run; this only narrows within a matching kind.
Returns the target and expression types when they cannot agree, for the message.
func KindFits ¶
KindFits reports whether a value of kind src fits a target of kind dst. Kinds that share a member fit, so a number fits an int, since it may hold one; an integer fits a number; a float does not fit an int, since it may carry a fraction. Bottom, meaning unknown, fits anything.
func OptionalPath ¶
OptionalPath reports whether any segment of a path may be absent at render.
Any segment, not just the last: if `network?: {vpcId: string}` then network.vpcId is absent whenever network is, however required vpcId looks inside it.
A key read out of an open map counts too: `labels: [string]: string` declares the map, never a key, so `labels["team"]` may find nothing.
Types ¶
type CheckError ¶
type CheckError struct {
Property string
// Expr is the expression at fault, when the fault is not about one read.
Expr string
// Read is the read at fault, when there is one.
Read Read
Err error
}
A CheckError is one fault in a tree, and where it is.
func (CheckError) Error ¶
func (c CheckError) Error() string
type CheckErrors ¶
type CheckErrors []CheckError
CheckErrors is every fault found in one pass.
func (CheckErrors) Error ¶
func (c CheckErrors) Error() string
func (CheckErrors) Unwrap ¶
func (c CheckErrors) Unwrap() []error
Unwrap exposes each fault, so errors.Is and errors.As see through the list.
type Checker ¶
type Checker interface {
Check(reads []Read) []CheckError
}
A Checker validates every read of one root in a plan against what the host knows, such as the resource being admitted and the definitions it names. It judges reads without their values: resolving them is a Resolver's job.
type CheckerFunc ¶
type CheckerFunc func(reads []Read) []CheckError
CheckerFunc adapts a function to a Checker.
type Engine ¶
type Engine struct {
// contains filtered or unexported fields
}
An Engine compiles and evaluates expressions over a fixed set of roots.
It is immutable once built and safe for concurrent use; lru.Cache locks internally.
func NewEngine ¶
NewEngine builds an engine for the roots given.
A qualifier compiles on any receiver, since a read below a root is dyn, so References refuses one called on anything but a read of a root declaring it. Two roots may declare the same qualifier only with the same result type.
func (*Engine) DynEnv ¶
DynEnv is the environment for evaluation, where every root is an open map.
Static typing is an admission concern: by the time a render happens the values exist, and admission has already refused anything that would not type. CEL selects a map key with `.`, so an expression reads the same here as against a declared object.
func (*Engine) EvalProperty ¶
func (e *Engine) EvalProperty(env *cel.Env, raw string, in map[string]interface{}) (interface{}, error)
EvalProperty evaluates a whole property value, interpolation included.
template.Parse splits the value into text and expression fragments:
'https://$(source.registry.host)/health' -> "https://" + host + "/health"
A value that is a single expression keeps its type - an int stays an int - and one embedded in text yields a string, because concatenating with text is what that means.
func (*Engine) EvalTree ¶
func (e *Engine) EvalTree(ctx context.Context, tree interface{}, resolvers map[string]Resolver, opts TreeOptions) (interface{}, error)
EvalTree is Plan followed by Eval, for a tree evaluated once.
func (*Engine) OutputType ¶
OutputType compiles an expression and reports the type it produces, from the AST alone, before any data exists.
func (*Engine) Plan ¶
Plan parses every expression in a tree and collects what each reads.
Every expression that does not parse or compile is reported, each with its property, as CheckErrors.
func (*Engine) PlanJSON ¶
PlanJSON plans a JSON document, such as a resource's properties, and keeps the plan for the document's bytes: the same properties reach admission and every render, and a plan is only ever read once built. A document that is not JSON, or holds an expression that will not compile, is not kept.
func (*Engine) PropertyReferences ¶
PropertyReferences returns every read an expression makes, against the shared permissive environment.
The environment is the same for every caller resolving or scanning an expression, so building one per call site only invites them to differ.
func (*Engine) References ¶
References returns every read an expression makes.
Walking the checked AST rather than the source text is what makes this exact: `source.cfg.data["image"]` and `source["cfg"].data.image` are the same read spelled two ways, and the parser has already normalised both into a select chain over an index.
Reads inside a comprehension are included. A source read only in the untaken arm of a ternary is included too, deliberately: it still has to be resolved before the expression can be evaluated, and a value that might be substituted must count as sensitive whether or not this particular render reaches it.
func (*Engine) TypedEnv ¶
func (e *Engine) TypedEnv(key string, decls func() (map[string]*apiservercel.DeclType, error)) (*cel.Env, error)
TypedEnv is an environment where the roots in decls carry those types and the rest stay open maps. It is kept under key, and decls is only called on a miss; an empty key is never kept.
The key must capture everything decls depends on: two callers sharing a key with different schemas would each type-check against the other's.
type Expression ¶
type Expression struct {
// Property is where it sits, as template.Walk names it.
Property string
// Expr is the text inside $( ).
Expr string
// Whole reports that it is the property's entire value, so it keeps its type.
Whole bool
Reads []Read
}
An Expression is one $( ) expression in a tree.
type MayBeAbsent ¶
type MayBeAbsent struct{ Read Read }
A MayBeAbsent is an unguarded read that may be missing at render, feeding a required property.
func (*MayBeAbsent) Error ¶
func (m *MayBeAbsent) Error() string
type Plan ¶
type Plan struct {
// contains filtered or unexported fields
}
A Plan is a properties tree parsed once: every expression in it and every read each one makes. Building one calls no resolver and evaluates nothing, so the same plan serves admission, dependency planning and evaluation.
func (*Plan) Check ¶
func (p *Plan) Check(permitted []string, checkers map[string]Checker) []CheckError
Check is admission for the tree: every read's root must be one of permitted, and each read root with a Checker has it called once with all of its reads. Every fault is reported, reads of roots outside permitted first.
func (*Plan) CheckTypes ¶
func (p *Plan) CheckTypes(env *cel.Env, target Target, opts TypeOptions) []CheckError
CheckTypes compiles each property's expressions against env, whose roots carry the types of what they read, and asserts the result fits the target at that property. It reports at most one fault per property, in this order: an expression that does not compile there; a collection embedded in text; a result whose kind, or whose elements, do not fit; an unguarded read that may be missing feeding a required property.
A dyn result, a read below an untyped region or of a value with no schema, has no type to compare and fits anything; a property the target does not declare is not judged. With no target, only what env refuses is reported.
func (*Plan) Eval ¶
func (p *Plan) Eval(ctx context.Context, resolvers map[string]Resolver, opts TreeOptions) (interface{}, error)
Eval resolves and evaluates the tree.
Each read root's resolver is called once with all of its reads, in the order the roots were declared; a root nothing reads is not resolved. The first resolver error ends the evaluation, so a host declares its cheapest roots, and those most likely to wait, first. Only then is every expression evaluated, against the permissive environment. A leaf with no expression is returned byte-identical, and the tree is left alone.
func (*Plan) Expressions ¶
func (p *Plan) Expressions() []Expression
Expressions returns every expression, sorted by property.
type Qualifier ¶
A Qualifier is a member call taking one literal string, answered by looking up what the caller delivered under QualifiedKey. Which value it names is settled before evaluation, so the call performs no I/O.
type Read ¶
type Read struct {
template.Reference
// Property is where the expression sits in the tree, as template.Walk names it.
Property string
}
A Read is one reference an expression makes, and the property it feeds.
type Resolver ¶
A Resolver answers every read of one root in one tree, before any expression is evaluated. Whatever I/O a root needs happens here, never inside an expression.
Its value is JSON-shaped, as a decoded document is: map[string]interface{}, []interface{} and scalars. Numbers are normalised for CEL only within those containers.
type ResolverFunc ¶
ResolverFunc adapts a function to a Resolver.
type Root ¶
type Root struct {
Name string
// Qualifiers are the member calls a read of this root may make to select
// among values delivered with it, such as peer.db.at("east").
Qualifiers []Qualifier
// QualifiedAt is how many path segments a qualifier call follows: 1 puts it
// straight after an entry's name, as peer.db.at("east"). Further qualifiers
// may follow it directly.
QualifiedAt int
}
A Root is a top-level name an expression may read. Everything an expression reads hangs off a declared root, so the sandbox is "these names and nothing else" rather than a denylist.
type Target ¶
type Target interface {
// At is the schema at property, whether the property is required, and
// whether the target declares it at all; an open struct may not.
At(property string) (schema cue.Value, required, declared bool)
}
A Target is the schema a tree's values land in: the parameter block of whatever the properties feed.
type TargetFunc ¶
TargetFunc adapts a function to a Target.
type TreeOptions ¶
type TreeOptions struct {
// Unknown renders an expression that reads a root answered Unknown. whole
// reports whether the expression is the property's entire value; otherwise
// the result is joined into the surrounding text. Without it, such a read is
// an error.
Unknown func(expr string, whole bool) (interface{}, error)
// OnEvalError is given each evaluation error with the roots the expression
// reads, each once, and returns the error to report; nil keeps the original. A host uses it to treat a value
// missing below a read it would wait on, such as an element a status fills
// in later, as a wait.
OnEvalError func(expr string, roots []string, err error) error
}
TreeOptions adjusts Plan.Eval and EvalTree.
type TypeMismatch ¶
type TypeMismatch struct {
// Got and Want are kind names, or element types when Elements is set.
Got, Want string
// Elements reports that the kinds agree, both lists or both maps, but
// their element types do not.
Elements bool
}
A TypeMismatch is an expression whose result does not fit its target.
func (*TypeMismatch) Error ¶
func (m *TypeMismatch) Error() string
type TypeOptions ¶
type TypeOptions struct {
// Optional reports a read that may be missing at render. Such a read,
// unguarded, is refused where it feeds a required property.
Optional func(Read) bool
// DeclaredKind is the kind the host's schema declares for a read, when it
// knows one. CEL types CUE's number as double, so an expression that is
// exactly one read is judged by this kind instead; a computed result keeps
// CEL's type.
DeclaredKind func(Read) (cue.Kind, bool)
}
TypeOptions adjusts CheckTypes.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package template splits a property value into literal text and $( ) expressions, and walks a properties tree to reach every such value.
|
Package template splits a property value into literal text and $( ) expressions, and walks a properties tree to reach every such value. |