Skip to content

Commit d8ecc93

Browse files
trgeigerPer Goncalves da Silva
authored and
Per Goncalves da Silva
committed
Add CRD Upgrade Safety documentation (operator-framework#1090)
Signed-off-by: Tayler Geiger <[email protected]>
1 parent 0041c43 commit d8ecc93

File tree

3 files changed

+242
-1
lines changed

3 files changed

+242
-1
lines changed

docs/Tasks/installing-an-extension.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ After you add a catalog to your cluster, you can install an extension by creatin
4545
!!! warning
4646
Currently, the following limitations affect the installation of extensions:
4747

48-
* If mulitple catalogs are added to a cluster, you cannot specify a catalog when you install an extension.
48+
* If multiple catalogs are added to a cluster, you cannot specify a catalog when you install an extension.
4949
* OLM 1.0 requires that all of the extensions have unique bundle and package names for dependency resolution.
5050

5151
As a result, if two catalogs have an extension with the same name, the installation might fail or lead to an unintended outcome.

docs/refs/crd-upgrade-safety.md

+240
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
# Custom Resource Definition Upgrade Safety
2+
3+
When you update a Custom Resource Definition (CRD), OLM runs a CRD Upgrade Safety preflight
4+
check to ensure backwards compatibility with previous versions of that CRD. The CRD update
5+
must pass the validation checks before the change is allowed to progress on a cluster.
6+
7+
## Prohibited CRD Upgrade Changes
8+
9+
The following changes to an existing CRD will be caught by the CRD Upgrade
10+
Safety preflight check and prevent the upgrade:
11+
12+
- The scope changes from Cluster to Namespace or from Namespace to Cluster
13+
- An existing stored version of the CRD is removed
14+
- A new required field is added to an existing version of the CRD
15+
- An existing field is removed from an existing version of the CRD
16+
- An existing field type is changed in an existing version of the CRD
17+
- A new default value is added to a field that did not previously have a default value
18+
- The default value of a field is changed
19+
- An existing default value of a field is removed
20+
- New enum restrictions are added to an existing field which did not previously have enum restrictions
21+
- Existing enum values from an existing field are removed
22+
- The minimum value of an existing field is increased in an existing version
23+
- The maximum value of an existing field is decreased in an existing version
24+
- Minimum or maximum field constraints are added to a field that did not previously have constraints
25+
26+
!!! note
27+
The rules for changes to minimum and maximum values apply to `minimum`, `minLength`,
28+
`minProperties`, `minItems`, `maximum`, `maxLength`, `maxProperties`, and `maxItems` constraints.
29+
30+
If the CRD Upgrade Safety preflight check encounters one of the disallowed upgrade changes,
31+
it will log an error for each disallowed change detected in the CRD upgrade.
32+
33+
!!! tip
34+
In cases where a change to the CRD does not fall into one of the disallowed change categories
35+
but is also unable to be properly detected as allowed, the CRD Upgrade Safety preflight check
36+
will prevent the upgrade and log an error for an "unknown change."
37+
38+
If you identify any preflight checks that should be implemented to prevent issues during CRD upgrades, please [create a new issue](https://github.com/operator-framework/operator-controller/issues).
39+
40+
41+
## Allowed CRD Upgrade Changes
42+
43+
The following changes to an existing CRD are safe for backwards compatibility and will
44+
not cause the CRD Upgrade Safety preflight check to halt the upgrade:
45+
46+
- Adding new enum values to the list of allowed enum values in a field
47+
- An existing required field is changed to optional in an existing version
48+
- The minimum value of an existing field is decreased in an existing version
49+
- The maximum value of an existing field is increased in an existing version
50+
- A new version of the CRD is added with no modifications to existing versions
51+
52+
53+
## Disabling CRD Upgrade Safety
54+
55+
The CRD Upgrade Safety preflight check can be entirely disabled by adding the
56+
`preflight.crdUpgradeSafety.disabled` field with a value of "true" to the ClusterExtension of the CRD.
57+
58+
```yaml
59+
apiVersion: olm.operatorframework.io/v1alpha1
60+
kind: ClusterExtension
61+
metadata:
62+
name: clusterextension-sample
63+
spec:
64+
installNamespace: default
65+
packageName: argocd-operator
66+
version: 0.6.0
67+
preflight:
68+
crdUpgradeSafety:
69+
disabled: true
70+
```
71+
72+
You cannot disable individual field validators. If you disable the CRD Upgrade Safety preflight check, all field validators are disabled.
73+
74+
!!! warning
75+
Disabling the CRD Upgrade Safety preflight check could break backwards compatibility with stored
76+
versions of the CRD and cause other unintended consequences on the cluster.
77+
78+
79+
## Examples of Unsafe CRD Changes
80+
81+
Take the following CRD as our starting version:
82+
83+
```yaml
84+
---
85+
apiVersion: apiextensions.k8s.io/v1
86+
kind: CustomResourceDefinition
87+
metadata:
88+
annotations:
89+
controller-gen.kubebuilder.io/version: v0.13.0
90+
name: example.test.example.com
91+
spec:
92+
group: test.example.com
93+
names:
94+
kind: Sample
95+
listKind: SampleList
96+
plural: samples
97+
singular: sample
98+
scope: Namespaced
99+
versions:
100+
- name: v1alpha1
101+
schema:
102+
openAPIV3Schema:
103+
properties:
104+
apiVersion:
105+
type: string
106+
kind:
107+
type: string
108+
metadata:
109+
type: object
110+
spec:
111+
type: object
112+
status:
113+
type: object
114+
pollInterval:
115+
type: string
116+
type: object
117+
served: true
118+
storage: true
119+
subresources:
120+
status: {}
121+
```
122+
123+
The following examples will demonstrate specific changes to sections of the example CRD
124+
that would be caught by the CRD Upgrade Safety preflight check.
125+
126+
### Changing Scope
127+
128+
In this example, `scope` has been changed from `Namespaced` to `Cluster`.
129+
130+
??? example
131+
```yaml
132+
spec:
133+
group: test.example.com
134+
names:
135+
kind: Sample
136+
listKind: SampleList
137+
plural: samples
138+
singular: sample
139+
scope: Cluster
140+
versions:
141+
- name: v1alpha1
142+
```
143+
144+
??? failure "Error output"
145+
```
146+
validating upgrade for CRD "test.example.com" failed: CustomResourceDefinition test.example.com failed upgrade safety validation. "NoScopeChange" validation failed: scope changed from "Namespaced" to "Cluster"
147+
```
148+
149+
### Removing a stored version
150+
151+
In this example, the existing stored version, `v1alpha1`, has been removed:
152+
153+
??? example
154+
```yaml
155+
versions:
156+
- name: v1alpha2
157+
schema:
158+
openAPIV3Schema:
159+
properties:
160+
apiVersion:
161+
type: string
162+
kind:
163+
type: string
164+
metadata:
165+
type: object
166+
spec:
167+
type: object
168+
status:
169+
type: object
170+
pollInterval:
171+
type: string
172+
type: object
173+
```
174+
175+
??? failure "Error output"
176+
```
177+
validating upgrade for CRD "test.example.com" failed: CustomResourceDefinition test.example.com failed upgrade safety validation. "NoStoredVersionRemoved" validation failed: stored version "v1alpha1" removed
178+
```
179+
180+
### Removing an existing field
181+
182+
In this example, the `pollInterval` field has been removed from `v1alpha1`:
183+
184+
??? example
185+
```yaml
186+
versions:
187+
- name: v1alpha1
188+
schema:
189+
openAPIV3Schema:
190+
properties:
191+
apiVersion:
192+
type: string
193+
kind:
194+
type: string
195+
metadata:
196+
type: object
197+
spec:
198+
type: object
199+
status:
200+
type: object
201+
type: object
202+
```
203+
204+
??? failure "Error output"
205+
```
206+
validating upgrade for CRD "test.example.com" failed: CustomResourceDefinition test.example.com failed upgrade safety validation. "NoExistingFieldRemoved" validation failed: crd/test.example.com version/v1alpha1 field/^.spec.pollInterval may not be removed
207+
```
208+
209+
### Adding a required field
210+
211+
In this example, `pollInterval` has been changed to a required field:
212+
213+
??? example
214+
```yaml
215+
versions:
216+
- name: v1alpha2
217+
schema:
218+
openAPIV3Schema:
219+
properties:
220+
apiVersion:
221+
type: string
222+
kind:
223+
type: string
224+
metadata:
225+
type: object
226+
spec:
227+
type: object
228+
status:
229+
type: object
230+
pollInterval:
231+
type: string
232+
type: object
233+
required:
234+
- pollInterval
235+
```
236+
237+
??? failure "Error output"
238+
```
239+
validating upgrade for CRD "test.example.com" failed: CustomResourceDefinition test.example.com failed upgrade safety validation. "ChangeValidator" validation failed: version "v1alpha1", field "^": new required fields added: [pollInterval]
240+
```

mkdocs.yml

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ nav:
1818
- Deleting an extension: 'Tasks/uninstall-an-extension.md'
1919
- References:
2020
- Catalog queries: 'refs/catalog-queries.md'
21+
- CRD Upgrade Safety: 'refs/crd-upgrade-safety.md'
2122

2223
markdown_extensions:
2324
- pymdownx.highlight:

0 commit comments

Comments
 (0)