Skip to content

Commit 21ee92f

Browse files
authored
Merge pull request kubernetes#3019 from jpbetz/type-integration
Explain type integraiton between OpenAPIv3 and CEL
2 parents 5ad73f1 + 1815d02 commit 21ee92f

File tree

1 file changed

+59
-0
lines changed
  • keps/sig-api-machinery/2876-crd-validation-expression-language

1 file changed

+59
-0
lines changed

keps/sig-api-machinery/2876-crd-validation-expression-language/README.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
- [Other expression languages](#other-expression-languages)
2626
- [Design Details](#design-details)
2727
- [Type Checking](#type-checking)
28+
- [Type System Integration](#type-system-integration)
29+
- [Why not represent associative lists as maps in CEL?](#why-not-represent-associative-lists-as-maps-in-cel)
2830
- [Test Plan](#test-plan)
2931
- [Graduation Criteria](#graduation-criteria)
3032
- [Alpha](#alpha)
@@ -445,6 +447,63 @@ coverage of interactions in these dimensions:
445447

446448
(Thanks to @liggitt for pointing this out)
447449

450+
### Type System Integration
451+
452+
Types:
453+
454+
| OpenAPIv3 type | CEL type |
455+
| --------------------------------------- | ------------------------------ |
456+
| 'object' with Properties | object / "message type" |
457+
| 'object' with AdditionalProperties | map |
458+
| 'array | list |
459+
| 'array' with x-kubernetes-list-type=map | list with map based Equality & unique key guarantees |
460+
| 'array' with x-kubernetes-list-type=set | list with set based Equality & unique entry guarantees |
461+
| 'boolean' | boolean |
462+
| 'number' (all formats) | double |
463+
| 'integer' (all formats) | int (64) |
464+
| 'null' | null |
465+
| 'string' | string |
466+
| 'string' with format=byte | bytes |
467+
| 'string' with format=binary | bytes |
468+
| 'string' with format=date | timestamp (protobuf.Timestamp) |
469+
| 'string' with format=datetime | timestamp (protobuf.Timestamp) |
470+
471+
xref: [CEL types](https://github.com/google/cel-spec/blob/master/doc/langdef.md#values), [OpenAPI types](https://swagger.io/specification/#data-types).
472+
473+
Implementation:
474+
475+
Type integration will be added by implementing CEL's
476+
[ref.Val](https://github.com/google/cel-go/blob/8e5d9877f0ab106269dee64e5bf10c5315281830/common/types/ref/reference.go#L40)
477+
and related [trait interfaces](https://github.com/google/cel-go/tree/master/common/types/traits).
478+
479+
The initial changes made in the type integration will be:
480+
481+
- `Equals` for lists with type "map" and "set" will be map and set based instead of list based (order will be ignored)
482+
- `Add` for lists with type "map" will overwrite existing entries with the same key, but with the position of existing entries in the list retained. New entries will be appended.
483+
- `Add` for lists with type "set" will perform a union. The positions of existing set entries in the list will be retained and new set entries will be appended.
484+
485+
#### Why not represent associative lists as maps in CEL?
486+
487+
- CEL maps must be keyed by a single scalar type, "associative lists" may be keyed by 1+ scalar key fields
488+
- While it would be possible to use a string representation of mult-field maps, there are problems:
489+
- Developers [sometimes care](https://github.com/kubernetes/kubernetes/issues/104641) about associative list order, and if allow the associative lists to be treated as a map in a way that results in order being discarded, we would break them.
490+
- We couldn't statically type check the key string literals being used as multi part keys
491+
- We couldn't have both: (a) equality of string keys, which implies a canonical ordering of key fields, and (b) ability for developers to successfully lookup a map entry regardless of how they order the keys in the string representation
492+
493+
494+
So instead of treating "associative lists" as maps in CEL, we will continue to treat them as lists, but override equality to ignore object order (i.e. use map equality semantics) and introduce utility functions to make the list representation easy to use in CEL. E.g. instead of:
495+
496+
```
497+
associativeList.filter(e, e.key1 == 'a' && e.key2 == 'b').all(e, e.val == 100)
498+
```
499+
500+
We plan to add a `get()` builtin function (exact name and semantics TBD) that allows for lookup of a single map entry:
501+
502+
```
503+
associativeList.get(e, e.key1 == 'a' && e.key2 == 'b').val == 100
504+
```
505+
506+
448507
### Test Plan
449508

450509
We will extend both the unit test suite and the integration test suite to cover the CRD validation rule described in this KEP.

0 commit comments

Comments
 (0)