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
- Generates into staging/vendor/k8s.io/client-go/applyconfigurations/
308
+
- Only generate builders for struct types reachable from the types that have the +clientgen annotation
309
+
- Don't generate builders for MarshalJSON types (Quantity, IntOrString)
310
+
- Don't generate builders for RawExtension or Unknown
311
+
312
+
##### client-gen changes
307
313
308
314
Since client-gen is available for use with 3rd party project, we must ensure all
309
315
changes to it are backward compatible. The Apply functions will only be generated
@@ -346,7 +352,7 @@ it is correct using the existing e2e tests, expanding coverage as needed.
346
352
### Graduation Criteria
347
353
348
354
This enhancement will graduate to GA as part of Server Side Apply. It does
349
-
not make sense to graduate it independantly.
355
+
not make sense to graduate it independently.
350
356
351
357
### Upgrade / Downgrade Strategy
352
358
@@ -456,4 +462,78 @@ Major milestones might include:
456
462
457
463
## Alternatives
458
464
459
-
TODO(jpbetz): Fill this out
465
+
### Alternative: Use YAML directly
466
+
467
+
For fields that need to be set programmatically, use templating.
468
+
469
+
Limitations:
470
+
471
+
- Not typesafe, so arguably should be part of a dynamic client only (which can already do apply)
472
+
- Templating doesn't work well for some cases. E.g. a variable number of containers
473
+
474
+
475
+
### Alternative: Combine go structs with fieldset mask
476
+
477
+
User directly provides the go structs as they exist today and also provides a fieldset "mask" that enumerates all the fields included in the apply configuration. A custom serializer would be required to combine the object and the mask together.
478
+
479
+
```
480
+
obj := &appsv1.Deployment{ …}
481
+
mask := TODO
482
+
tombstoned := TODO: is another fieldset required for tombstones?
483
+
Apply(..., obj, mask, tombstoned, …)
484
+
```
485
+
486
+
Limitations:
487
+
488
+
- Error prone. No way to ensure that the mask and the object have the same set of fields directly set by the caller (e.g. if the user directly sets a field to its zero value, there is no way to warn them that they forgot to add it to the mask)
489
+
- Even if there was some typesafe way to define masks and tombstones, constructing them is going to add to the work required by client-go apply users.
490
+
491
+
### Alternative: Use varadic function based builders
492
+
493
+
```
494
+
appsv1apply.Deployment(
495
+
metav1apply.ObjectMeta(
496
+
appsv1apply.Name("nginx-deployment"),
497
+
),
498
+
appsv1apply.DeploymentSpec(
499
+
appsv1apply.Replicas(0),
500
+
appsv1apply.PodTemplate(
501
+
appsv1apply.PodSpec(
502
+
appsv1apply.TombStoned("hostname"),
503
+
appsv1apply.PodContainer(
504
+
appsv1apply.Name("nginx"),
505
+
appsv1apply.Image("nginx:1.14.2"),
506
+
),
507
+
appsv1apply.TombStoned(
508
+
appsv1apply.PodContainer(
509
+
appsv1apply.Name("sidecar"),
510
+
),
511
+
),
512
+
),
513
+
),
514
+
),
515
+
)
516
+
517
+
```
518
+
519
+
This could be implemented by generating varadic functions, e.g.:
520
+
521
+
```
522
+
func Deployment(fields ...DeploymentField{}) {
523
+
var object map[string]interface{} // This is the underlying data structure
524
+
for field := range fields {
525
+
switch f := fields.(type) {
526
+
case NameField:
527
+
object["name"] = f.value
528
+
// other types
529
+
}
530
+
}
531
+
}
532
+
533
+
func Name(value string) DeploymentField { … }
534
+
```
535
+
536
+
Limitations:
537
+
538
+
- Lots of identifier collision issues to deal with. For example, we can't have multiple "Name" functions in the same package. This can probably be mitigated by either generating more unique names or by allowing a common field like Name, which is typically a string, to be shared across multiple structs that have name fields.
0 commit comments