Skip to content

Commit 46d35e2

Browse files
committed
Adding doc for transition rules, func library and resource constraints.
1 parent 9f50755 commit 46d35e2

File tree

1 file changed

+70
-0
lines changed

1 file changed

+70
-0
lines changed

content/en/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions.md

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -716,6 +716,8 @@ CustomResourceDefinition schemas using the `x-kubernetes-validations` extension.
716716
The Rule is scoped to the location of the `x-kubernetes-validations` extension in the schema.
717717
And `self` variable in the CEL expression is bound to the scoped value.
718718

719+
Note all the validation rules are scoped to the current object, no cross-object or stateful validation rules are supported.
720+
719721
For example:
720722

721723
```yaml
@@ -994,7 +996,75 @@ Here is the declarations type mapping between OpenAPIv3 and CEL type:
994996
xref: [CEL types](https://github.com/google/cel-spec/blob/v0.6.0/doc/langdef.md#values), [OpenAPI
995997
types](https://swagger.io/specification/#data-types), [Kubernetes Structural Schemas](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#specifying-a-structural-schema).
996998

999+
#### Function Library
1000+
1001+
Functions available include:
1002+
- CEL standard functions, defined in the[list of standard definitions](https://github.com/google/cel-spec/blob/v0.7.0/doc/langdef.md#list-of-standard-definitions)
1003+
- CEL standard [macros](https://github.com/google/cel-spec/blob/v0.7.0/doc/langdef.md#macros)
1004+
- CEL [extended string function library](https://pkg.go.dev/github.com/google/[email protected]/ext#Strings)
1005+
- Kubernetes [CEL extension library](https://pkg.go.dev/k8s.io/[email protected]/pkg/apiserver/schema/cel/library#pkg-functions)
1006+
1007+
#### Transition Rules
1008+
1009+
A rule that contains an expression referencing the identifier `oldSelf` is implicitly considered a
1010+
"transition rule". Transition rules allow schema authors to prevent certain transitions between two
1011+
otherwise valid states. For example:
1012+
1013+
```yaml
1014+
type: string
1015+
enum: ["low", "medium", "high"]
1016+
x-kubernetes-validations:
1017+
- rule: "!(self == 'high' && oldSelf == 'low') && !(self == 'low' && oldSelf == 'high')"
1018+
message: cannot transition directly between 'low' and 'high'
1019+
```
1020+
1021+
Unlike other rules, transition rules apply only to operations meeting the following criteria:
1022+
1023+
- The operation updates an existing object. Transition rules never apply to create operations.
1024+
1025+
- Both an old and a new value exist. It remains possible to check if a value has been added or
1026+
removed by placing a transition rule on the parent node. Transition rules are never applied to
1027+
custom resource creation. When placed on an optional field, a transition rule will not apply to
1028+
update operations that set or unset the field.
1029+
1030+
- The path to the schema node being validated by a transition rule must resolve to a node that is
1031+
comparable between the old object and the new object. For example, list items and their
1032+
descendants (`spec.foo[10].bar`) can't necessarily be correlated between an existing object and a
1033+
later update to the same object.
1034+
1035+
Errors will be generated on CRD writes if a schema node contains a transition rule that can never be
1036+
applied, e.g. "*path*: update rule *rule* cannot be set on schema because the schema or its parent
1037+
schema is not mergeable".
1038+
1039+
Transition rules are only allowed on "correlatable" portions of a schema.
1040+
A portion of the schema is correlatable if all `array` parent schemas are of type `x-kubernetes-list-type=map`; any `set`or `atomic`array parent schemas make it impossible to unambiguously correlate a `self` with `oldSelf`.
1041+
1042+
##### Use Cases
1043+
1044+
| Use Case | Rule
1045+
| -------- | --------
1046+
| Immutability | `self.foo == oldSelf.foo`
1047+
| Prevent modification/removal once assigned | `oldSelf != 'bar' \|\| self == 'bar'` or `!has(oldSelf.field) \|\| has(self.field)`
1048+
| Append-only set | `self.all(element, element in oldSelf)`
1049+
| If previous value was X, new value can only be A or B, not Y or Z | `oldSelf != 'X' \|\| self in ['A', 'B']`
1050+
| Nondecreasing counters | `self >= oldSelf`
1051+
1052+
#### Resource Constraints
1053+
1054+
CEL expressions have the potential to consume unacceptable amounts of API server resources. We constrain the resource utilization in following ways:
1055+
- Validation of CEL expression's "cost" when a CEL expression is written to a field in a CRD (at CRD creation/update time)
1056+
- Runtime cost budget during CEL evaluation
1057+
- CEL validation might fail due to runtime cost budget exceed with error message `validation failed due to running out of cost budget, no further validation rules will be run`
1058+
- CEL validation might fail due to cost limit exceed per expression with message `operation cancelled: actual cost limit exceeded: no further validation rules will be run due to call cost exceeds limit for rule:{$rule}`
1059+
- Go context cancellation to bound CEL expression evaluation to the request lifetime
1060+
1061+
Guidelines for working with estimated limits:
1062+
- Adding MaxItems, MaxProperties and MaxLength limits on all data accessed by CEL rules is the best practice.
1063+
- O(n) - For simple rules, it is possible to iterate across a single map/list/string without exceeding the limit, but adding limits on all data accessed by CEL rules is the best practice
1064+
- O(n^2)+ the product of the max lengths usually needs to be <1,000,000. E.g. 1000 for 2 levels of nesting, 100 for 3 levels of nesting
1065+
- O(n^3) - should generally be avoided
9971066

1067+
// TODO: edit info for cost estimation
9981068

9991069
### Defaulting
10001070

0 commit comments

Comments
 (0)