Skip to content

Commit 36f6049

Browse files
committed
Document Unions, conventions for adding to Unions.
1 parent 0dc25f5 commit 36f6049

File tree

2 files changed

+123
-4
lines changed

2 files changed

+123
-4
lines changed

docs/devel/api-conventions.md

+10
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ using resources with kubectl can be found in [Working with resources](../user-gu
5353
- [Lists of named subobjects preferred over maps](#lists-of-named-subobjects-preferred-over-maps)
5454
- [Primitive types](#primitive-types)
5555
- [Constants](#constants)
56+
- [Unions](#unions)
5657
- [Lists and Simple kinds](#lists-and-simple-kinds)
5758
- [Differing Representations](#differing-representations)
5859
- [Verbs on Resources](#verbs-on-resources)
@@ -263,6 +264,15 @@ This rule maintains the invariant that all JSON/YAML keys are fields in API obje
263264

264265
Some fields will have a list of allowed values (enumerations). These values will be strings, and they will be in CamelCase, with an initial uppercase letter. Examples: "ClusterFirst", "Pending", "ClientIP".
265266

267+
#### Unions
268+
269+
Sometimes, at most one of a set of fields can be set. For example, the [volumes] field of a PodSpec has 17 different volume type-specific
270+
fields, such as `nfs` and `iscsi`. All fields in the set should be [Optional](#optional-vs-required).
271+
272+
Sometimes, when a new type is created, the api designer may anticipate that a union will be needed in the future, even if only one field is
273+
allowed initially. In this case, be sure to make the field [Optional](#optional-vs-required) optional. In the validation, you may
274+
still return an error if the sole field is unset. Do not set a default value for that field.
275+
266276
### Lists and Simple kinds
267277

268278
Every list or simple kind SHOULD have the following metadata in a nested object field called "metadata":

docs/devel/api_changes.md

+113-4
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,38 @@ Documentation for other releases can be found at
3232

3333
<!-- END MUNGE: UNVERSIONED_WARNING -->
3434

35+
*This document is oriented at developers who want to change existing APIs.
36+
A set of API conventions, which applies to new APIs and to changes, can be
37+
found at [API Conventions](api-conventions.md).
38+
39+
**Table of Contents**
40+
<!-- BEGIN MUNGE: GENERATED_TOC -->
41+
42+
- [So you want to change the API?](#so-you-want-to-change-the-api)
43+
- [Operational overview](#operational-overview)
44+
- [On compatibility](#on-compatibility)
45+
- [Incompatible API changes](#incompatible-api-changes)
46+
- [Changing versioned APIs](#changing-versioned-apis)
47+
- [Edit types.go](#edit-typesgo)
48+
- [Edit defaults.go](#edit-defaultsgo)
49+
- [Edit conversion.go](#edit-conversiongo)
50+
- [Changing the internal structures](#changing-the-internal-structures)
51+
- [Edit types.go](#edit-typesgo)
52+
- [Edit validation.go](#edit-validationgo)
53+
- [Edit version conversions](#edit-version-conversions)
54+
- [Edit deep copy files](#edit-deep-copy-files)
55+
- [Edit json (un)marshaling code](#edit-json-unmarshaling-code)
56+
- [Making a new API Group](#making-a-new-api-group)
57+
- [Update the fuzzer](#update-the-fuzzer)
58+
- [Update the semantic comparisons](#update-the-semantic-comparisons)
59+
- [Implement your change](#implement-your-change)
60+
- [Write end-to-end tests](#write-end-to-end-tests)
61+
- [Examples and docs](#examples-and-docs)
62+
- [Alpha, Beta, and Stable Versions](#alpha-beta-and-stable-versions)
63+
- [Adding Unstable Features to Stable Versions](#adding-unstable-features-to-stable-versions)
64+
65+
<!-- END MUNGE: GENERATED_TOC -->
66+
3567
# So you want to change the API?
3668

3769
Before attempting a change to the API, you should familiarize yourself
@@ -273,6 +305,11 @@ enumerated set *can* be a compatible change, if handled properly (treat the
273305
removed value as deprecated but allowed). This is actually a special case of
274306
a new representation, discussed above.
275307

308+
For [Unions](api-conventions.md), sets of fields where at most one should be set,
309+
it is acceptible to add a new option to the union if the [appropriate conventions]
310+
were followed in the original object. Removing an option requires following
311+
the deprecation process.
312+
276313
## Incompatible API changes
277314

278315
There are times when this might be OK, but mostly we want changes that
@@ -549,10 +586,6 @@ hack/update-swagger-spec.sh
549586

550587
The API spec changes should be in a commit separate from your other changes.
551588

552-
## Adding new REST objects
553-
554-
TODO(smarterclayton): write this.
555-
556589
## Alpha, Beta, and Stable Versions
557590

558591
New feature development proceeds through a series of stages of increasing maturity:
@@ -617,6 +650,82 @@ New feature development proceeds through a series of stages of increasing maturi
617650
- Support: API version will continue to be present for many subsequent software releases;
618651
- Recommended Use Cases: any
619652

653+
### Adding Unstable Features to Stable Versions
654+
655+
When adding a feature to an object which is already Stable, the new fields and new behaviors
656+
need to meet the Stable level requirements. If these cannot be met, then the new
657+
field cannot be added to the object.
658+
659+
For example, consider the following object:
660+
661+
```go
662+
// API v6.
663+
type Frobber struct {
664+
Height int `json:"height"`
665+
Param string `json:"param"`
666+
}
667+
```
668+
669+
A developer is considering adding a new `Width` parameter, like this:
670+
671+
```go
672+
// API v6.
673+
type Frobber struct {
674+
Height int `json:"height"`
675+
Width int `json:"height"`
676+
Param string `json:"param"`
677+
}
678+
```
679+
680+
However, the new feature is not stable enough to be used in a stable version (`v6`).
681+
Some reasons for this might include:
682+
683+
- the final representation is undecided (e.g. should it be called `Width` or `Breadth`?)
684+
- the implementation is not stable enough for general use (e.g. the `Area()` routine sometimes overflows.)
685+
686+
The developer cannot add the new field until stability is met. However, sometimes stability
687+
cannot be met until some users try the new feature, and some users are only able or willing
688+
to accept a released version of Kubernetes. In that case, the developer has a few options,
689+
both of which require staging work over several releases.
690+
691+
692+
A preferred option is to first make a release where the new value (`Width` in this example)
693+
is specified via an annotation, like this:
694+
695+
```go
696+
kind: frobber
697+
version: v6
698+
metadata:
699+
name: myfrobber
700+
annotations:
701+
frobbing.alpha.kubernetes.io/width: 2
702+
height: 4
703+
param: "green and blue"
704+
```
705+
706+
This format allows users to specify the new field, but makes it clear
707+
that they are using a Alpha feature when they do, since the word `alpha`
708+
is in the annotation key.
709+
710+
Another option is to introduce a new type with an new `alpha` or `beta` version
711+
designator, like this:
712+
713+
```
714+
// API v6alpha2
715+
type Frobber struct {
716+
Height int `json:"height"`
717+
Width int `json:"height"`
718+
Param string `json:"param"`
719+
}
720+
```
721+
722+
The latter requires that all objects in the same API group as `Frobber` to be replicated in
723+
the new version, `v6alpha2`. This also requires user to use a new client which uses the
724+
other version. Therefore, this is not a preferred option.
725+
726+
A releated issue is how a cluster manager can roll back from a new version
727+
with a new feature, that is already being used by users. See https://github.com/kubernetes/kubernetes/issues/4855.
728+
620729
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
621730
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/devel/api_changes.md?pixel)]()
622731
<!-- END MUNGE: GENERATED_ANALYTICS -->

0 commit comments

Comments
 (0)