Skip to content

Commit 49b2773

Browse files
authored
Merge pull request #5182 from jpbetz/mutating-admission-unsetting-plan
MutatingAdmissionPolicy KEP: Drop dependency on SSA unsetting fields
2 parents da64cb4 + 5d24d39 commit 49b2773

File tree

1 file changed

+4
-104
lines changed
  • keps/sig-api-machinery/3962-mutating-admission-policies

1 file changed

+4
-104
lines changed

keps/sig-api-machinery/3962-mutating-admission-policies/README.md

Lines changed: 4 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -465,105 +465,7 @@ Optimizations like caching or lazy sub-schema resolution can be candidates of be
465465
#### Unsetting values
466466

467467
Since there is no field manager used for the merge, the server side apply merge
468-
algorithm will only add and replace values. This is because server side apply is
469-
designed to only unset values that were previously owned by the field manager
470-
but excluded from the apply configuration.
471-
472-
To work around this limitation, we will take advantage of CEL's optional type
473-
feature to make it possible to express that a value should be unset. For example:
474-
475-
```cel
476-
Object{
477-
spec: Object.spec{
478-
?fieldToRemoveIfPresent: optional.none()
479-
}
480-
}
481-
```
482-
The policy declaratively describes that, in the final object, if fieldToRemoveIfPresent presents it should be removed or no-op otherwise.
483-
484-
The optional.none() function creates a CEL object defined as optional(T) where T is the type of the receiving field.
485-
In conjunction with standard CEL macros, simple expressions can perform more complicated and precise operations.
486-
487-
For example, to remove the env of a sidecar container, filter by its name.
488-
489-
```yaml
490-
mutations:
491-
- patchType: "ApplyConfiguration"
492-
expression: >
493-
Object{
494-
spec: Object.spec{
495-
containers: object.spec.containers{
496-
object.spec.containers.filter(c, c.name == "sidecar")
497-
.map(c, Object.spec.containers.item{
498-
?env: optional.none()
499-
})
500-
}
501-
}
502-
}
503-
504-
```
505-
506-
We will track which fields are unset in this way and remove them after the
507-
server side apply merge algorithm is run.
508-
509-
This solves the vast majority of value removal needs. Specifically:
510-
511-
| Schema type | Merge type | Example of how to unset a value |
512-
|-------------| -----------|----------------------------------------------------------------------------------|
513-
| struct | atomic | ```Object{ spec: Object.spec{ structField: {?fieldToRemove: optional.none()}}}``` |
514-
| struct | granular | `?fieldToRemove: optional.none()` |
515-
| map | atomic | `mapField: object.spec.mapField.filter(k, k != "keyToRemove")` |
516-
| map | granular | `mapField: {?"keyToRemove": optional.none()}` |
517-
| list | atomic | Use `JSONPatch` |
518-
| list | set | `setField: object.spec.setField.filter(e, e != "itemToRemove")` |
519-
| list | map | See below |
520-
| list | granular | See below |
521-
522-
523-
List with "map" merge type:
524-
- Filter `objects.filter(<list>, <keys-to-remove>)` could be used for the deletion
525-
- For associatedList with multiple keys like example above, a directive field added could be used to indicate the deletion.
526-
```yaml
527-
mutations:
528-
- patchType: "ApplyConfiguration"
529-
expression: >
530-
Object{
531-
spec: Object.spec{
532-
assocListField: [Object.spec.assocListField{
533-
keyField1: "key1",
534-
keyField2: "key2",
535-
_: optional.none()
536-
}]
537-
}
538-
}
539-
540-
```
541-
542-
For examples of removing item from List with Map filtered by a subfield:
543-
```yaml
544-
mutations:
545-
- patchType: "ApplyConfiguration"
546-
expression: >
547-
Object{
548-
spec: Object.spec{
549-
containers: object.spec.containers.filter(c, c.envvar != "remove-this-container")
550-
}
551-
}
552-
}
553-
554-
```
555-
556-
For granular list removal, a use case would be removing an item with a sub field named `remove-this-item`.
557-
```yaml
558-
mutations:
559-
- patchType: "ApplyConfiguration"
560-
expression: >
561-
Object{
562-
spec: Object.spec{
563-
granularList: object.spec.granularList.filter(c, c.subField != "remove-this-item")
564-
}
565-
}
566-
```
468+
algorithm will only add and replace values. To unset values, JSON Patch mutations must be used.
567469

568470
##### Safety
569471

@@ -840,11 +742,9 @@ Object{
840742
#### Use case: Remove an annotation
841743

842744
```cel
843-
Object{
844-
metadata: Object.metadata{
845-
annotations:
846-
?"annotation-to-unset": optional.none()
847-
}
745+
JSONPatch{
746+
op: "remove",
747+
path: "/metadata/annotations/annotation-to-unset"
848748
}
849749
```
850750

0 commit comments

Comments
 (0)