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
* Validation - ensuring only one member field is set (or at most one if
127
130
desired).
@@ -151,7 +154,7 @@ bogged down.
151
154
152
155
#### Story 1
153
156
154
-
As a CRD owner, I can use simple semantics (such as go tags), to express the
157
+
As a CRD owner, I can use simple semantics (such as openapi tags/go markers), to express the
155
158
desired validation of a oneOf (at most one or exactly one field may be set), and
156
159
the API server will perform this validation automatically.
157
160
@@ -206,16 +209,17 @@ added field to the union (due to version skew).
206
209
We present a [guide doc](https://docs.google.com/document/d/1Wruosjo0ELLl1yxauzpsUjgH2fK9KdgXDmOdJ5sG7Kg/edit?resourcekey=0-8Pwzx6EvsFR7VQoXzCTY4Q) on how to interpret the test matrix, but the major
207
210
conclusions are as follows (along with the test case number from the test matrix):
208
211
209
-
* (Case #22 and #27) If an unstructured client is unaware of field on the union, but wants to clear
212
+
* (Case #22 and #27) If an unstructured client (i.e. a client that represents data as raw json maps with no knowledge of the schema)
213
+
is unaware of field on the union, but wants to clear
210
214
the union entirely (assuming the union is optional), it will have no way of doing
211
215
so without a discriminator. With a discriminator, the client can express its
212
216
intention by setting the discriminator to the empty value and the server can
213
-
respects it intentions and clear any fields the client is unaware of.
217
+
respect its intentions and clear any fields the client is unaware of.
214
218
* (Case #12 and #16) If a structured client is unaware of a field in the union that is set and it
215
219
just wants to echo back the union it received in a get request (such as when
216
220
updating other parts of the object), a client without a discriminator will
217
221
silently drop the currently set field, while a client with the discriminator
218
-
will not change the discriminator value, indicating to the client that no
222
+
will not change the discriminator value, indicating to the server that no
219
223
changes are desired in the union.
220
224
* (Case #34 and #39) If a client sets a union field that the server is not aware of, the server
221
225
will silently drop it and attempt to clear the object of the union field. With
@@ -227,7 +231,7 @@ conclusions are as follows (along with the test case number from the test matrix
227
231
logic to detect that the previously set field has not been modified and that
228
232
only one of the other union fields has been.
229
233
230
-
### Go tags
234
+
### Go Markers
231
235
232
236
We're proposing a new type of tags for go types (in-tree types, and also
233
237
kubebuilder types):
@@ -236,15 +240,16 @@ kubebuilder types):
236
240
-`// +unionDiscriminator` before a field means that this field is the
237
241
discriminator for the union. This field MUST be a string. This field MUST be
238
242
required.
239
-
-`// +unionAllowEmpty` before a discriminator field means that by setting the
243
+
-`// +unionOptional` before a discriminator field means that by setting the
240
244
discriminator to an empty string, none of the union fields are persisted
241
245
(meaning at most one member of the union must be set). If not present on the
242
246
discriminator, exactly one of the union members must be set in order to be
243
247
valid.
244
-
-`// +unionMember=<discriminatorName>` before a field means that this
245
-
field is a member of a union. The `<discriminatorName>` is optional if there
248
+
-`// +unionMember=<memberName>,discriminatedBy=<discriminatorName>` before a field means that this
249
+
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
246
250
is only union in a struct and required if there are multiple unions per
247
-
struct.
251
+
struct. It should be the json representation of the field tagged with
252
+
`unionDiscriminator`.
248
253
249
254
Note unions can't span across multiple go structures (all the fields that are part of a union has to be together in the
250
255
same structure), examples of what is allowed:
@@ -272,15 +277,17 @@ type Union struct {
272
277
FieldB int `json:"fieldB"`
273
278
}
274
279
275
-
// This generates two unions, each with two fields and a discriminator. The
280
+
// This will generate one union that can be embedded because the members explicitly define their discriminator.
281
+
// Also, the unionMember markers here demonstrate how to customize the names used for
282
+
each field in the discriminator.
276
283
type Union2 struct {
277
284
// +unionDiscriminator
278
285
// +required
279
286
Type string `json:"type"`
280
-
// +unionMember=type
287
+
// +unionMember=ALPHA,discriminatedBy=type
281
288
// +optional
282
289
Alpha int `json:"alpha"`
283
-
// +unionMember=type
290
+
// +unionMember=BETA,discriminatedBy=type
284
291
// +optional
285
292
Beta int `json:"beta"`
286
293
}
@@ -294,10 +301,10 @@ type InlinedUnion struct {
294
301
// +unionAllowEmpty
295
302
// +required
296
303
FieldType string `json:"fieldType"`
297
-
// +unionMember=fieldType
304
+
// +unionMember,discriminatedBy=fieldType
298
305
// +optional
299
306
Field1 *int `json:"field1,omitempty"`
300
-
// +unionMember=fieldType
307
+
// +unionMember,discriminatedBy=fieldType
301
308
// +optional
302
309
Field2 *int `json:"field2,omitempty"`
303
310
@@ -337,16 +344,15 @@ Issues primarily arise here because of version skew between a client and a serve
337
344
such as when a client is unaware of new fields added to a union and thus doesn't
338
345
know how to clear these new fields when trying to set a different field.
339
346
340
-
For unions with a discriminator (all newly created unions and some existing
341
-
unions), normalization is simple: the server should always respect the
347
+
For unions with a discriminator, normalization is simple: the server should always respect the
342
348
discriminator.
343
349
344
350
This means two things:
345
351
1. when the server receives a request with a discriminator set to a
346
352
given field, it should clear out any other fields that are set.
347
353
2. when the server receives a request with a discriminator set to a given field,
348
-
but that given field is empty, it should maintain the value of the field that
349
-
currently exists.
354
+
but that given field is empty, the server should fail with a clear error
355
+
message.
350
356
351
357
For situations where a typed client is unaware of a new field (that is currently
352
358
set) and drops the set field such that no fields are now set, the server will
0 commit comments