@@ -465,105 +465,7 @@ Optimizations like caching or lazy sub-schema resolution can be candidates of be
465
465
# ### Unsetting values
466
466
467
467
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.
567
469
568
470
# #### Safety
569
471
@@ -840,11 +742,9 @@ Object{
840
742
# ### Use case: Remove an annotation
841
743
842
744
` ` ` 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"
848
748
}
849
749
` ` `
850
750
0 commit comments