Skip to content

Commit 7b966f9

Browse files
authored
Merge pull request #4053 from jiahuif-forks/kep-3488/composition
KEP-3488: Update for CEL Variable Composition
2 parents 3248ecc + 1b4f1a6 commit 7b966f9

File tree

1 file changed

+35
-32
lines changed
  • keps/sig-api-machinery/3488-cel-admission-control

1 file changed

+35
-32
lines changed

keps/sig-api-machinery/3488-cel-admission-control/README.md

Lines changed: 35 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1316,25 +1316,29 @@ Note that `matchConditions` and `validations` look similar, but `matchConditions
13161316

13171317
#### CEL Expression Composition
13181318

1319+
Expression Composition is a technique to define a set of variables each from
1320+
a given expression and allow validation expressions to refer the variables.
1321+
13191322
##### Use Cases
13201323

1324+
###### Reusing/memorizing an expensive computation and lazy evaluation
1325+
1326+
For a CEL expression that takes a significant time to evaluate, especially
1327+
these that cost O(N^2) time or worse, it would be nice to only run it once
1328+
and only when necessary. If multiple validation expressions used the same
1329+
expression, that expression could be refactored out into a variable.
1330+
Because of the evaluation of a composited variable is lazy, if the value of some variable
1331+
does not affect the result of an expression due to boolean short-circuit evaluation,
1332+
the variable can be omitted and does not incur runtime cost.
1333+
13211334
###### Code re-use for complicated expressions
13221335

13231336
A CEL expression may not be computationally expensive, but could still be
13241337
intricate enough that copy-pasting could prove to be a bad decision later on
1325-
in time. With the addition of the `messageExpression` field, more copy-pasting
1326-
is expected as well. If a sufficiently complex expression ended up copy-pasted everywhere,
1327-
and then needs to be updated somehow, it will need that update in every place
1328-
it was copy-pasted. A variable, on the other hand, will only need to be updated
1329-
in one place.
1330-
1331-
###### Reusing/memoizing an expensive computation
1332-
1333-
For a CEL expression that runs in O(n^2) time or worse (or otherwise
1334-
takes a significant amount of time to execute), it would be nice to only run
1335-
it when necessary. For instance, if multiple validation expressions used the
1336-
same expensive expression, that expression could be refactored out into a
1337-
variable.
1338+
in time. For example, a sub-expression is likely used both in the validation and
1339+
to format `messageExpression`. If a sufficiently complex expression ended up
1340+
copy-pasted everywhere, and then needs to be updated somehow, it will need that update in every place
1341+
it was copy-pasted. A variable, on the other hand, will only need to be updated in one place.
13381342

13391343
##### Variables
13401344

@@ -1343,18 +1347,17 @@ assignment. This can result in redundant code to traverse maps/arrays or
13431347
dereference particular fields.
13441348

13451349
We can support this in much the same way as cel-policy-template `terms`. These
1346-
can be lazily evaluated while the validation expressions are evaluated
1347-
(cel-policy-template does this).
1350+
can be lazily evaluated when they are resolved during the evaluation of
1351+
the main expression (cel-policy-template does this).
13481352

1349-
A policy can include an additional `variables` section. This is an array
1353+
The policy spec now has an additional `variables` section. This is an array
13501354
containing one or more `name` and `expression` pairs, which can be used/re-used by
13511355
the policy's validation expressions. These results are memoized on a
13521356
per-validation basis, so if multiple expressions use the same spec variables,
13531357
the expression that calculates the variable's value will only run once.
13541358

13551359
The variables can be accessed as members of `variables`, which is an object
1356-
that is exposed to CEL expressions (both validation expressions as well as
1357-
other variables).
1360+
that is exposed to CEL expressions (both validation expressions and other variables).
13581361

13591362
For example:
13601363

@@ -1369,16 +1372,16 @@ For example:
13691372
- expression: "variables.itemMetadataNames.exists(name, name == 'required')"
13701373
```
13711374

1372-
Variable names must be valid CEL names. What constitutes a
1373-
valid CEL name can be found at CEL's [language definition](https://github.com/google/cel-spec/blob/master/doc/langdef.md#syntax) under `IDENT`.
1374-
This validity is checked at write time.
1375+
Variable names must be valid CEL names and must be unique among all variables. What constitutes a
1376+
valid CEL name can be found at CEL[language definition](https://github.com/google/cel-spec/blob/master/doc/langdef.md#syntax)
1377+
under `IDENT`. This validity is checked when the policy is being created or updated.
13751378

13761379
For per-policy runtime cost limit purposes, variables count towards the runtime cost limit
13771380
once per policy. The cost of each variable is computed when it is first evaluated in an
13781381
expression, mirroring how the cost limit would be calculated if the variable's
13791382
expression was embedded verbatim. If the runtime cost limit is exceeded in the
13801383
process, then evaluation halts. No individual variable or expression will be listed as the
1381-
cause in the resulting message. Whether or not the request actually fails depends on the failure policy,
1384+
cause in the resulting message. Whether the request actually fails depends on the failure policy,
13821385
however. For subsequent uses, inclusion of the variable has zero effect on the runtime
13831386
cost limit. If the variable evaluates to an array or some other iterable, and some expression
13841387
iterates on it, that of course contributes to the cost limit, but simply including the variable does
@@ -1387,16 +1390,13 @@ not add the underlying expression's cost again.
13871390
Variables are also subject to the per-expression runtime cost limit. Exceeding the per-expression
13881391
runtime cost limit is always attributed to the variable, unlike the per-policy limit.
13891392

1390-
Variables can only reference other variables that
1391-
have been previously defined in the `variables` section, so circular references
1392-
are not allowed.
1393+
Variables can only reference other variables that have been previously defined in the `variables` section.
1394+
This will have a side effect of making the order of the variable definitions matter but prevents circular reference.
13931395

1394-
If an error ocurrs during variable evaluation, then the expression
1395-
that caused it to be evaluated (since variable are always
1396-
lazily-evaluated) also finishes with an error. Evaluation for that
1397-
variable is not attempted again during the same validation; if any other
1398-
expressions attempt to evaluate a variable that already failed an evaluation
1399-
attempt, they will also be considered to have failed.
1396+
Both the result and potential error of a variable evaluation are memorized.
1397+
If an error occurs during variable evaluation, then every validation expression
1398+
that caused it to be evaluated (since variable are always lazily-evaluated)
1399+
also finishes with an error, and the variable evaluation will not retry.
14001400

14011401
#### Secondary Authz
14021402

@@ -1658,8 +1658,11 @@ Goals:
16581658
- Parity with admission webhook metrics
16591659
- Should include counter of deny, warn and audit violations
16601660
- Label by {policy, policy binding, validation expression} identifiers
1661-
- Counters for number of policy defintions and policy bindings in cluster
1661+
- Counters for number of policy definitions and policy bindings in cluster
16621662
- Label by state (active vs. error), enforcement action (deny, warn)
1663+
- Counters for Variable Composition
1664+
- Should include counter of variable resolutions to measure time saved.
1665+
- Label by policy identifier
16631666

16641667
Granularity:
16651668

0 commit comments

Comments
 (0)