You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
best match the intent of the client, despite the client potentially having
133
133
incomplete information
134
134
135
+
Another goal is to migrate at least one existing union to the new semantics in
136
+
order to verify that migration is possible.
137
+
135
138
### Non-Goals
136
139
137
-
The focus of this KEP is on providing unified validation and normalization of
138
-
new union types. Migrating existing unions away from their bespoke validation
140
+
Migrating all existing unions away from their bespoke validation
139
141
logic (e.g validation functions), is an explicit non-goal and will be pursued in
140
142
a separate KEP or later release.
141
143
@@ -248,7 +250,7 @@ kubebuilder types):
248
250
-`// +unionMember=<memberName>,discriminatedBy=<discriminatorName>` before a field means that this
249
251
field is a member of a union. The `<memberName>` is the name of the field that must be set as the discriminator value. It defaults to the json representation of the field name if not specified. The `<discriminatorName>` is optional if there
250
252
is only union in a struct and required if there are multiple unions per
251
-
struct. It should be the json representation of the field tagged with
253
+
struct. It should be the go representation of the field tagged with
252
254
`unionDiscriminator`.
253
255
254
256
Note unions can't span across multiple go structures (all the fields that are part of a union has to be together in the
@@ -349,7 +351,13 @@ discriminator.
349
351
350
352
This means two things:
351
353
1. when the server receives a request with a discriminator set to a
352
-
given field, it should clear out any other fields that are set.
354
+
given field, and multiple member fields are set it should:
355
+
a. If the discriminator has been modified from the one set in the old object,
356
+
the server should clear all fields except the one pointed to by the discriminator.
357
+
b. If the discriminator is unchanged but a new member field has been set (in
358
+
addition to the existing one that has not been cleared), it should error
359
+
loudly that the client must change the discriminator if it changes any union
360
+
member fields.
353
361
2. when the server receives a request with a discriminator set to a given field,
354
362
but that given field is empty, the server should fail with a clear error
355
363
message.
@@ -371,19 +379,36 @@ Objects must be validated AFTER the normalization process.
371
379
A few open questions exist with the design that need to be resolved with SIG API
372
380
Machinery before moving forward.
373
381
374
-
1. When a server receives an update request with empty data in the member fields
375
-
but a validly set discriminator pointing to the object's union member field
376
-
that was previously set, should the server error and inform the client that
377
-
the field pointed to by the discriminator is currently empty, or should the
378
-
server retain the previous value it knows was set to the field being pointed
379
-
to by the discriminator?
382
+
1. What do we do when the discriminator is set (to the previously set value),
383
+
but all union member fields are null? This likely implies that the client cleared
384
+
the union member unintentionally, given that the discriminator value remains.
385
+
Should the server:
386
+
a. Error loudly and inform the client that the field pointed to by the
387
+
discriminator is null?
388
+
b. Retain the previously set member field, present on the old object, absent
389
+
from the new object, but pointed to by the discriminator?
380
390
2. What should the value of the discriminator be when no field in the union is
381
-
to be set. A couple options inclued an empty string, an field common to all
382
-
union (e.g. "NONE"), or a field specified on a per union basis.
391
+
to be set (i.e for optional unions).
392
+
a. mandate that the discriminator is the empty string for all optional unions?
393
+
b. make the field specified on a per union basis (defined in the go markers)?
394
+
c. mandate that the discriminator be unset (thus make the discriminator an
395
+
optional field for optional unios)?
383
396
3. How should a server behave when it receives a union with multiple fields set
384
-
and the discriminator pointing to one of them? Reject the request, accept the
385
-
request but don't clear the fields, or automatically clear the fields not
386
-
specified by the discriminator.
397
+
and the discriminator modified to point to the newly set member field?
398
+
a. reject the request,
399
+
b. accept the request but don't clear any fields
400
+
c. accept the request and clear all the fields except the one chosen by the
401
+
discriminator
402
+
4. Given that we want to migrate at least one existing union to use the new
403
+
semantics, which union should we do? Must we upgrade both a discriminated and
404
+
non-discriminated union for alpha or is only upgrading an existing
405
+
discriminated union sufficient?
406
+
5. What should we default the discriminator value of a member field to if not
407
+
specified in the go markers?
408
+
a. the json representation of the field name
409
+
b. the go representation of the field name
410
+
Should we even give users the ability to define it or just stick to whatever
411
+
we decide the default is?
387
412
388
413
### Test Plan
389
414
@@ -480,7 +505,7 @@ We expect no non-infra related flakes in the last month as a GA graduation crite
480
505
481
506
- CRDs can be created with union fields and are properly validated when
482
507
created/updated.
483
-
-Existing unions that have discriminators, are properly tagged and validated via
508
+
-At least one existing unions that has discriminators, is properly tagged and validated via
484
509
union validation
485
510
- Existing unions that don't have discriminators do not break when upgraded.
486
511
@@ -498,8 +523,11 @@ enhancement:
498
523
cluster required to make on upgrade, in order to make use of the enhancement?
499
524
-->
500
525
501
-
At first, Only new union types will follow the prescribed guinance, so no upgrades/downgrades are possible for types
502
-
that don't exist yet.
526
+
Turning the flag on for alpha just enables different runtime codepaths (i.e.
527
+
performing the unified union validation and normalization)
528
+
529
+
Any schema markers (added by CRD authors or propagated from tags on built-in
530
+
types) will appear in the schema, but not do anything if the flag is off.
503
531
504
532
### Version Skew Strategy
505
533
@@ -520,6 +548,13 @@ See test matrix and commentary about discriminators. It clearly documents how
520
548
the server will use the discriminator to understand the client's intention even
521
549
if the client is not aware of all union fields because of version skew.
522
550
551
+
Skew with alpha flag on/off shouldn't make much of a difference.
552
+
* Objects created with the union semantics, but applied to a cluster with the
553
+
alpha flag off will simply not perform union validation and normalization.
554
+
* Objects created without union semantics will simply not trigger union
555
+
validation and normalization (regardless of whether the server has the alpha
556
+
enabled or disabled).
557
+
523
558
## Production Readiness Review Questionnaire
524
559
525
560
<!--
@@ -565,15 +600,15 @@ well as the [existing list] of feature gates.
565
600
-[x] Feature gate (also fill in values in `kep.yaml`)
566
601
- Feature gate name: APIUnions
567
602
- Components depending on the feature gate: kube-apiserver
568
-
603
+
569
604
Request handlers in the api server will call into union validation and
570
605
normalization function from the structured-merge-diff repo when feature is
571
606
enabled.
572
607
573
608
574
609
###### Does enabling the feature change any default behavior?
575
610
576
-
No
611
+
No, since all built in unions are currently validated in other ways.
577
612
578
613
<!--
579
614
Any change of default behavior may be surprising to users or break existing
@@ -597,7 +632,8 @@ Yes, requests will simply skip union validation and normalization.
597
632
598
633
###### What happens if we reenable the feature if it was previously rolled back?
599
634
600
-
Requests will resume perform union validation and normalization
635
+
Requests will resume performing union validation and normalization; there is no
636
+
persistent state behind this feature.
601
637
602
638
###### Are there any tests for feature enablement/disablement?
603
639
@@ -669,7 +705,13 @@ previous answers based on experience in the field.
669
705
670
706
###### How can an operator determine if the feature is in use by workloads?
671
707
672
-
Simply creating and updating objects with union fields.
708
+
For builtins in alpha, it won't be possible to break clients since turning on vs
709
+
off will validate the same thing via different code paths.
710
+
711
+
For CRDs, you can see if they have the new union markers. If the CRD has no
712
+
other validation mechanism, turning off the flag may result in CRs accepting
713
+
invalid input.
714
+
673
715
<!--
674
716
Ideally, this should be a metric. Operations against the Kubernetes API (e.g.,
675
717
checking if there are objects with field X set) may be a last resort. Avoid
@@ -678,10 +720,13 @@ logs or events for this purpose.
678
720
679
721
###### How can someone using this feature know that it is working for their instance?
680
722
681
-
1. Create a new CRD with a union field
723
+
1. Create a new CRD with a union field (and no other validation mechanism)
682
724
2. Apply the CRD
683
725
3. Create a CR with an invalid union (multiple fields set, no discriminator
684
726
set), see if the CR is rejected via union validation
727
+
728
+
When we write the e2e test, a standard union CRD and test CR will be obtainable
729
+
for users to test on their instance.
685
730
<!--
686
731
For instance, if this is a pod-related feature, it should be possible to determine if the feature is functioning properly
687
732
for each individual pod.
@@ -827,7 +872,9 @@ Describe them, providing:
827
872
828
873
###### Will enabling / using this feature result in increasing time taken by any operations covered by existing SLIs/SLOs?
829
874
830
-
No
875
+
In GA (maybe beta), we might expect resource reduction/reliability improvement,
876
+
since this removes a need for webhooks.
877
+
831
878
<!--
832
879
Look at the [existing SLIs/SLOs].
833
880
@@ -839,7 +886,11 @@ Think about adding additional work or introducing new steps in between
839
886
840
887
###### Will enabling / using this feature result in non-negligible increase of resource usage (CPU, RAM, disk, IO, ...) in any components?
841
888
842
-
No
889
+
New validation and normalization logic should be negligible given that the
890
+
functions will be in the same SMD path currently used by SSA code.
891
+
892
+
We will have benchmarking to validate this assumption.
893
+
843
894
<!--
844
895
Things to keep in mind include: additional in-memory state, additional
845
896
non-trivial computations, excessive access to disks (including increased log
0 commit comments