@@ -12,20 +12,23 @@ import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
12
12
// +kubebuilder:object:root=true
13
13
// +kubebuilder:subresource:status
14
14
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
15
- // +kubebuilder:resource:path=updatestatuses,scope=Namespaced
15
+ // +kubebuilder:resource:path=updatestatuses,scope=Cluster
16
16
// +openshift:api-approved.openshift.io=https://github.com/openshift/api/pull/2012
17
17
// +openshift:file-pattern=cvoRunLevel=0000_00,operatorName=cluster-version-operator,operatorOrdering=02
18
18
// +openshift:enable:FeatureGate=UpgradeStatus
19
19
// +kubebuilder:metadata:annotations="description=Provides health and status information about OpenShift cluster updates."
20
20
// +kubebuilder:metadata:annotations="displayName=UpdateStatuses"
21
21
type UpdateStatus struct {
22
- metav1.TypeMeta `json:",inline"`
22
+ metav1.TypeMeta `json:",inline"`
23
+
24
+ // +optional
23
25
metav1.ObjectMeta `json:"metadata,omitempty"`
24
26
25
27
// spec is empty for now, UpdateStatus is purely status-reporting API. In the future spec may be used to hold
26
28
// configuration to drive what information is surfaced and how
27
- // +kubebuilder:validation:Required
29
+ // +required
28
30
Spec UpdateStatusSpec `json:"spec"`
31
+ // status exposes the health and status of the ongoing cluster update
29
32
// +optional
30
33
Status UpdateStatusStatus `json:"status"`
31
34
}
@@ -40,33 +43,48 @@ type UpdateStatusSpec struct {
40
43
// UpdateStatusStatus is the API about in-progress updates. It aggregates and summarizes UpdateInsights produced by
41
44
// update informers
42
45
type UpdateStatusStatus struct {
46
+ // conditions provide details about the controller operational matters
47
+ // +listType=map
48
+ // +listMapKey=type
49
+ // +patchStrategy=merge
50
+ // +patchMergeKey=type
51
+ // +optional
52
+ // +kubebuilder:validation:MaxItems=10
53
+ Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
54
+
43
55
// controlPlane contains a summary and insights related to the control plane update
44
- // +kubebuilder:validation:Required
56
+ // +required
45
57
ControlPlane ControlPlane `json:"controlPlane"`
46
58
47
59
// workerPools contains summaries and insights related to the worker pools update
48
60
// +listType=map
49
61
// +listMapKey=name
62
+ // +patchStrategy=merge
63
+ // +patchMergeKey=name
50
64
// +optional
51
- WorkerPools []Pool `json:"workerPools,omitempty"`
65
+ // +kubebuilder:validation:MaxItems=32
66
+ WorkerPools []Pool `json:"workerPools,omitempty" patchStrategy:"merge" patchMergeKey:"name"`
67
+ }
52
68
53
- // conditions provide details about the controller operational matters
69
+ // ControlPlane contains a summary and insights related to the control plane update
70
+ type ControlPlane struct {
71
+ // conditions provides details about the control plane update
54
72
// +listType=map
55
73
// +listMapKey=type
74
+ // +patchStrategy=merge
75
+ // +patchMergeKey=type
56
76
// +optional
57
- Conditions []metav1. Condition `json:"conditions,omitempty"`
58
- }
77
+ // +kubebuilder:validation:MaxItems=10
78
+ Conditions []metav1. Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
59
79
60
- // ControlPlane contains a summary and insights related to the control plane update
61
- type ControlPlane struct {
62
80
// resource is the resource that represents the control plane. It will typically be a ClusterVersion resource
63
81
// in standalone OpenShift and HostedCluster in Hosted Control Planes.
64
82
//
65
83
// Note: By OpenShift API conventions, in isolation this should probably be a specialized reference type that allows
66
84
// only the "correct" resource types to be referenced (here, ClusterVersion and HostedCluster). However, because we
67
85
// use resource references in many places and this API is intended to be consumed by clients, not produced, consistency
68
86
// seems to be more valuable than type safety for producers.
69
- // +kubebuilder:validation:Required
87
+ // +required
70
88
Resource ResourceRef `json:"resource"`
71
89
72
90
// poolResource is the resource that represents control plane node pool, typically a MachineConfigPool. This field
@@ -82,14 +100,11 @@ type ControlPlane struct {
82
100
// informers is a list of insight producers, each carries a list of insights relevant for control plane
83
101
// +listType=map
84
102
// +listMapKey=name
103
+ // +patchStrategy=merge
104
+ // +patchMergeKey=name
85
105
// +optional
86
- Informers []Informer `json:"informers,omitempty"`
87
-
88
- // conditions provides details about the control plane update
89
- // +listType=map
90
- // +listMapKey=type
91
- // +optional
92
- Conditions []metav1.Condition `json:"conditions,omitempty"`
106
+ // +kubebuilder:validation:MaxItems=16
107
+ Informers []ControlPlaneInformer `json:"informers,omitempty" patchStrategy:"merge" patchMergeKey:"name"`
93
108
}
94
109
95
110
// ControlPlaneConditionType are types of conditions that can be reported on control plane level
@@ -107,20 +122,33 @@ type ControlPlaneUpdatingReason string
107
122
const (
108
123
// ClusterVersionProgressing is used for Updating=True set because we observed a ClusterVersion resource to
109
124
// have Progressing=True condition
110
- ReasonClusterVersionProgressing ControlPlaneUpdatingReason = "ClusterVersionProgressing"
125
+ ControlPlaneClusterVersionProgressing ControlPlaneUpdatingReason = "ClusterVersionProgressing"
111
126
// ClusterVersionNotProgressing is used for Updating=False set because we observed a ClusterVersion resource to
112
127
// have Progressing=False condition
113
- ReasonClusterVersionNotProgressing ControlPlaneUpdatingReason = "ClusterVersionNotProgressing"
128
+ ControlPlaneClusterVersionNotProgressing ControlPlaneUpdatingReason = "ClusterVersionNotProgressing"
114
129
// CannotDetermineUpdating is used with Updating=Unknown. This covers many different actual reasons such as
115
130
// missing or Unknown Progressing condition on ClusterVersion, but it does not seem useful to track the individual
116
131
// reasons to that granularity for Updating=Unknown
117
- ReasonClusterVersionCannotDetermine ControlPlaneUpdatingReason = "CannotDetermineUpdating"
132
+ ControlPlaneCannotDetermineUpdating ControlPlaneUpdatingReason = "CannotDetermineUpdating"
118
133
)
119
134
120
135
// Pool contains a summary and insights related to a node pool update
121
136
type Pool struct {
137
+ // conditions provide details about the pool
138
+ // +listType=map
139
+ // +listMapKey=type
140
+ // +patchStrategy=merge
141
+ // +patchMergeKey=type
142
+ // +optional
143
+ // +kubebuilder:validation:MaxItems=10
144
+ Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
145
+
122
146
// name is the name of the pool
123
- // +kubebuilder:validation:Required
147
+ // +required
148
+ // +kubebuilder:validation:Type=string
149
+ // +kubebuilder:validation:MinLength=1
150
+ // +kubebuilder:validation:MaxLength=63
151
+ // +kubebuilder:validation:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?$`
124
152
Name string `json:"name"`
125
153
126
154
// resource is the resource that represents the pool
@@ -129,56 +157,103 @@ type Pool struct {
129
157
// only the "correct" resource types to be referenced (here, MachineConfigPool or NodePool). However, because we use
130
158
// resource references in many places and this API is intended to be consumed by clients, not produced, consistency
131
159
// seems to be more valuable than type safety for producers.
132
- // +kubebuilder:validation:Required
160
+ // +required
133
161
Resource PoolResourceRef `json:"resource"`
134
162
135
163
// informers is a list of insight producers, each carries a list of insights
136
164
// +listType=map
137
165
// +listMapKey=name
166
+ // +patchStrategy=merge
167
+ // +patchMergeKey=name
138
168
// +optional
139
- Informers []Informer `json:"informers,omitempty"`
169
+ // +kubebuilder:validation:MaxItems=16
170
+ Informers []WorkerPoolInformer `json:"informers,omitempty" patchStrategy:"merge" patchMergeKey:"name"`
171
+ }
140
172
141
- // conditions provide details about the pool
173
+ // ControlPlaneInformer is an insight producer identified by a name, carrying a list of insights it produced
174
+ type ControlPlaneInformer struct {
175
+ // name is the name of the insight producer
176
+ // +required
177
+ // +kubebuilder:validation:Type=string
178
+ // +kubebuilder:validation:MinLength=1
179
+ // +kubebuilder:validation:MaxLength=63
180
+ // +kubebuilder:validation:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?$`
181
+ Name string `json:"name"`
182
+
183
+ // insights is a list of insights produced by this producer
142
184
// +listType=map
143
- // +listMapKey=type
185
+ // +listMapKey=uid
186
+ // +patchStrategy=merge
187
+ // +patchMergeKey=uid
144
188
// +optional
145
- Conditions []metav1.Condition `json:"conditions,omitempty"`
189
+ // +kubebuilder:validation:MaxItems=128
190
+ Insights []ControlPlaneInsight `json:"insights,omitempty" patchStrategy:"merge" patchMergeKey:"uid"`
146
191
}
147
192
148
- // Informer is an insight producer identified by a name, carrying a list of insights it produced
149
- type Informer struct {
193
+ // WorkerPoolInformer is an insight producer identified by a name, carrying a list of insights it produced
194
+ type WorkerPoolInformer struct {
150
195
// name is the name of the insight producer
151
- // +kubebuilder:validation:Required
196
+ // +required
197
+ // +kubebuilder:validation:Type=string
198
+ // +kubebuilder:validation:MinLength=1
199
+ // +kubebuilder:validation:MaxLength=63
200
+ // +kubebuilder:validation:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?$`
152
201
Name string `json:"name"`
153
202
154
203
// insights is a list of insights produced by this producer
155
- // +optional
156
204
// +listType=map
157
205
// +listMapKey=uid
158
- Insights []Insight `json:"insights,omitempty"`
206
+ // +patchStrategy=merge
207
+ // +patchMergeKey=uid
208
+ // +optional
209
+ // +kubebuilder:validation:MaxItems=1024
210
+ Insights []WorkerPoolInsight `json:"insights,omitempty" patchStrategy:"merge" patchMergeKey:"uid"`
159
211
}
160
212
161
- // Insight is a unique piece of either status/progress or update health information produced by update informer
162
- type Insight struct {
213
+ // ControlPlaneInsight is a unique piece of either status/progress or update health information produced by update informer
214
+ type ControlPlaneInsight struct {
163
215
// uid identifies the insight over time
164
- // +kubebuilder:validation:Required
216
+ // +required
165
217
// +kubebuilder:validation:Type=string
218
+ // +kubebuilder:validation:MinLength=1
219
+ // +kubebuilder:validation:MaxLength=63
220
+ // +kubebuilder:validation:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?$`
166
221
UID string `json:"uid"`
167
222
168
223
// acquiredAt is the time when the data was acquired by the producer
169
- // +kubebuilder:validation:Required
224
+ // +required
170
225
// +kubebuilder:validation:Type=string
171
226
// +kubebuilder:validation:Format=date-time
172
227
AcquiredAt metav1.Time `json:"acquiredAt"`
173
228
174
- InsightUnion `json:",inline"`
229
+ ControlPlaneInsightUnion `json:",inline"`
175
230
}
176
231
177
- // InsightUnion is the discriminated union of all insights types, identified by type field
178
- type InsightUnion struct {
232
+ // WorkerPoolInsight is a unique piece of either status/progress or update health information produced by update informer
233
+ type WorkerPoolInsight struct {
234
+ // uid identifies the insight over time
235
+ // +required
236
+ // +kubebuilder:validation:Type=string
237
+ // +kubebuilder:validation:MinLength=1
238
+ // +kubebuilder:validation:MaxLength=63
239
+ // +kubebuilder:validation:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?$`
240
+ UID string `json:"uid"`
241
+
242
+ // acquiredAt is the time when the data was acquired by the producer
243
+ // +required
244
+ // +kubebuilder:validation:Type=string
245
+ // +kubebuilder:validation:Format=date-time
246
+ AcquiredAt metav1.Time `json:"acquiredAt"`
247
+
248
+ WorkerPoolInsightUnion `json:",inline"`
249
+ }
250
+
251
+ // ControlPlaneInsightUnion is the discriminated union of all insights types that can be reported for the control plane,
252
+ // identified by type field
253
+ type ControlPlaneInsightUnion struct {
179
254
// type identifies the type of the update insight
180
255
// +unionDiscriminator
181
- // +kubebuilder:validation:Required
256
+ // +required
182
257
// +kubebuilder:validation:Enum=ClusterVersion;ClusterOperator;MachineConfigPool;Node;Health
183
258
Type InsightType `json:"type"`
184
259
@@ -213,9 +288,36 @@ type InsightUnion struct {
213
288
HealthInsight * HealthInsight `json:"health,omitempty"`
214
289
}
215
290
291
+ // WorkerPoolInsightUnion is the discriminated union of insights types that can be reported for a worker pool,
292
+ // identified by type field
293
+ type WorkerPoolInsightUnion struct {
294
+ // type identifies the type of the update insight
295
+ // +unionDiscriminator
296
+ // +required
297
+ // +kubebuilder:validation:Enum=MachineConfigPool;Node;Health
298
+ Type InsightType `json:"type"`
299
+
300
+ // machineConfigPool is a status insight about the state of a worker pool update, where the worker pool
301
+ // is represented by a MachineConfigPool resource
302
+ // +optional
303
+ // +unionMember
304
+ MachineConfigPoolStatusInsight * MachineConfigPoolStatusInsight `json:"machineConfigPool,omitempty"`
305
+
306
+ // node is a status insight about the state of a worker node update, where the worker node is represented
307
+ // by a Node resource
308
+ // +optional
309
+ // +unionMember
310
+ NodeStatusInsight * NodeStatusInsight `json:"node,omitempty"`
311
+
312
+ // health is a generic health insight about the update. It does not represent a status of any specific
313
+ // resource but surfaces actionable information about the health of the cluster or an update
314
+ // +optional
315
+ // +unionMember
316
+ HealthInsight * HealthInsight `json:"health,omitempty"`
317
+ }
318
+
216
319
// InsightType identifies the type of the update insight as either one of the resource-specific status insight,
217
320
// or a generic health insight
218
- // +kubebuilder:validation:Enum=ClusterVersion;ClusterOperator;MachineConfigPool;Node;Health
219
321
type InsightType string
220
322
221
323
const (
@@ -243,18 +345,29 @@ const (
243
345
type ResourceRef struct {
244
346
// group of the object being referenced, if any
245
347
// +optional
348
+ // +kubebuilder:validation:Type=string
349
+ // +kubebuilder:validation:MaxLength=253
246
350
Group string `json:"group,omitempty"`
247
351
248
352
// resource of object being referenced
249
- // +kubebuilder:validation:Required
353
+ // +required
354
+ // +kubebuilder:validation:Type=string
355
+ // +kubebuilder:validation:MaxLength=253
356
+ // +kubebuilder:validation:MinLength=1
250
357
Resource string `json:"resource"`
251
358
252
359
// name of the object being referenced
253
- // +kubebuilder:validation:Required
360
+ // +required
361
+ // +kubebuilder:validation:Type=string
362
+ // +kubebuilder:validation:MaxLength=253
363
+ // +kubebuilder:validation:MinLength=1
254
364
Name string `json:"name"`
255
365
256
366
// namespace of the object being referenced, if any
257
367
// +optional
368
+ // +kubebuilder:validation:Type=string
369
+ // +kubebuilder:validation:MaxLength=253
370
+ // +kubebuilder:validation:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?$`
258
371
Namespace string `json:"namespace,omitempty"`
259
372
}
260
373
@@ -271,7 +384,11 @@ type PoolResourceRef struct {
271
384
// +openshift:compatibility-gen:level=4
272
385
type UpdateStatusList struct {
273
386
metav1.TypeMeta `json:",inline"`
387
+ // +optional
274
388
metav1.ListMeta `json:"metadata"`
275
389
390
+ // items is a list of UpdateStatus resources
391
+ // +optional
392
+ // +kubebuilder:validation:MaxItems=32
276
393
Items []UpdateStatus `json:"items"`
277
394
}
0 commit comments