@@ -47,7 +47,7 @@ import (
47
47
"sigs.k8s.io/cluster-api/feature"
48
48
runtimeclient "sigs.k8s.io/cluster-api/internal/runtime/client"
49
49
"sigs.k8s.io/cluster-api/internal/topology/variables"
50
- "sigs.k8s.io/cluster-api/util/conditions "
50
+ "sigs.k8s.io/cluster-api/util"
51
51
"sigs.k8s.io/cluster-api/util/conversion"
52
52
"sigs.k8s.io/cluster-api/util/patch"
53
53
"sigs.k8s.io/cluster-api/util/paused"
@@ -94,7 +94,7 @@ func (r *Reconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager, opt
94
94
return nil
95
95
}
96
96
97
- func (r * Reconciler ) Reconcile (ctx context.Context , req ctrl.Request ) (_ ctrl.Result , reterr error ) {
97
+ func (r * Reconciler ) Reconcile (ctx context.Context , req ctrl.Request ) (retres ctrl.Result , reterr error ) {
98
98
clusterClass := & clusterv1.ClusterClass {}
99
99
if err := r .Client .Get (ctx , req .NamespacedName , clusterClass ); err != nil {
100
100
if apierrors .IsNotFound (err ) {
@@ -112,40 +112,94 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (_ ctrl.Re
112
112
return ctrl.Result {}, nil
113
113
}
114
114
115
+ s := & scope {
116
+ clusterClass : clusterClass ,
117
+ }
118
+
115
119
patchHelper , err := patch .NewHelper (clusterClass , r .Client )
116
120
if err != nil {
117
121
return ctrl.Result {}, err
118
122
}
119
123
120
124
defer func () {
125
+ updateStatus (ctx , s )
126
+
127
+ patchOpts := []patch.Option {
128
+ patch.WithOwnedConditions {Conditions : []clusterv1.ConditionType {
129
+ clusterv1 .ClusterClassRefVersionsUpToDateCondition ,
130
+ clusterv1 .ClusterClassVariablesReconciledCondition ,
131
+ }},
132
+ patch.WithOwnedV1Beta2Conditions {Conditions : []string {
133
+ clusterv1 .ClusterClassRefVersionsUpToDateV1Beta2Condition ,
134
+ clusterv1 .ClusterClassVariablesReadyV1Beta2Condition ,
135
+ }},
136
+ }
137
+
121
138
// Patch ObservedGeneration only if the reconciliation completed successfully
122
- patchOpts := []patch.Option {}
123
139
if reterr == nil {
124
140
patchOpts = append (patchOpts , patch.WithStatusObservedGeneration {})
125
141
}
126
142
if err := patchHelper .Patch (ctx , clusterClass , patchOpts ... ); err != nil {
127
143
reterr = kerrors .NewAggregate ([]error {reterr , err })
128
144
return
129
145
}
146
+
147
+ if reterr != nil {
148
+ retres = ctrl.Result {}
149
+ }
130
150
}()
131
- return ctrl.Result {}, r .reconcile (ctx , clusterClass )
151
+
152
+ reconcileNormal := []clusterClassReconcileFunc {
153
+ r .reconcileExternalReferences ,
154
+ r .reconcileVariables ,
155
+ }
156
+ return doReconcile (ctx , reconcileNormal , s )
132
157
}
133
158
134
- func (r * Reconciler ) reconcile (ctx context.Context , clusterClass * clusterv1.ClusterClass ) error {
135
- if err := r .reconcileVariables (ctx , clusterClass ); err != nil {
136
- return err
159
+ type clusterClassReconcileFunc func (context.Context , * scope ) (ctrl.Result , error )
160
+
161
+ func doReconcile (ctx context.Context , phases []clusterClassReconcileFunc , s * scope ) (ctrl.Result , error ) {
162
+ res := ctrl.Result {}
163
+ errs := []error {}
164
+ for _ , phase := range phases {
165
+ // Call the inner reconciliation methods.
166
+ phaseResult , err := phase (ctx , s )
167
+ if err != nil {
168
+ errs = append (errs , err )
169
+ }
170
+ if len (errs ) > 0 {
171
+ continue
172
+ }
173
+ res = util .LowestNonZeroResult (res , phaseResult )
137
174
}
138
- outdatedRefs , err := r . reconcileExternalReferences ( ctx , clusterClass )
139
- if err != nil {
140
- return err
175
+
176
+ if len ( errs ) > 0 {
177
+ return ctrl. Result {}, kerrors . NewAggregate ( errs )
141
178
}
142
179
143
- reconcileConditions (clusterClass , outdatedRefs )
180
+ return res , nil
181
+ }
144
182
145
- return nil
183
+ // scope holds the different objects that are read and used during the reconcile.
184
+ type scope struct {
185
+ // clusterClass is the ClusterClass object being reconciled.
186
+ // It is set at the beginning of the reconcile function.
187
+ clusterClass * clusterv1.ClusterClass
188
+
189
+ reconcileExternalReferencesError error
190
+ outdatedExternalReferences []outdatedRef
191
+
192
+ variableDiscoveryError error
193
+ }
194
+
195
+ type outdatedRef struct {
196
+ Outdated * corev1.ObjectReference
197
+ UpToDate * corev1.ObjectReference
146
198
}
147
199
148
- func (r * Reconciler ) reconcileExternalReferences (ctx context.Context , clusterClass * clusterv1.ClusterClass ) (map [* corev1.ObjectReference ]* corev1.ObjectReference , error ) {
200
+ func (r * Reconciler ) reconcileExternalReferences (ctx context.Context , s * scope ) (ctrl.Result , error ) {
201
+ clusterClass := s .clusterClass
202
+
149
203
// Collect all the reference from the ClusterClass to templates.
150
204
refs := []* corev1.ObjectReference {}
151
205
@@ -185,7 +239,7 @@ func (r *Reconciler) reconcileExternalReferences(ctx context.Context, clusterCla
185
239
// or MachinePool classes.
186
240
errs := []error {}
187
241
reconciledRefs := sets.Set [string ]{}
188
- outdatedRefs := map [ * corev1. ObjectReference ] * corev1. ObjectReference {}
242
+ outdatedRefs := [] outdatedRef {}
189
243
for i := range refs {
190
244
ref := refs [i ]
191
245
uniqueKey := uniqueObjectRefKey (ref )
@@ -212,16 +266,25 @@ func (r *Reconciler) reconcileExternalReferences(ctx context.Context, clusterCla
212
266
errs = append (errs , err )
213
267
}
214
268
if ref .GroupVersionKind ().Version != updatedRef .GroupVersionKind ().Version {
215
- outdatedRefs [ref ] = updatedRef
269
+ outdatedRefs = append (outdatedRefs , outdatedRef {
270
+ Outdated : ref ,
271
+ UpToDate : updatedRef ,
272
+ })
216
273
}
217
274
}
218
275
if len (errs ) > 0 {
219
- return nil , kerrors .NewAggregate (errs )
276
+ err := kerrors .NewAggregate (errs )
277
+ s .reconcileExternalReferencesError = err
278
+ return ctrl.Result {}, err
220
279
}
221
- return outdatedRefs , nil
280
+
281
+ s .outdatedExternalReferences = outdatedRefs
282
+ return ctrl.Result {}, nil
222
283
}
223
284
224
- func (r * Reconciler ) reconcileVariables (ctx context.Context , clusterClass * clusterv1.ClusterClass ) error {
285
+ func (r * Reconciler ) reconcileVariables (ctx context.Context , s * scope ) (ctrl.Result , error ) {
286
+ clusterClass := s .clusterClass
287
+
225
288
errs := []error {}
226
289
allVariableDefinitions := map [string ]* clusterv1.ClusterClassStatusVariable {}
227
290
// Add inline variable definitions to the ClusterClass status.
@@ -270,10 +333,10 @@ func (r *Reconciler) reconcileVariables(ctx context.Context, clusterClass *clust
270
333
}
271
334
}
272
335
if len (errs ) > 0 {
336
+ err := kerrors .NewAggregate (errs )
337
+ s .variableDiscoveryError = errors .Wrapf (err , "VariableDiscovery failed" )
273
338
// TODO: Decide whether to remove old variables if discovery fails.
274
- conditions .MarkFalse (clusterClass , clusterv1 .ClusterClassVariablesReconciledCondition , clusterv1 .VariableDiscoveryFailedReason , clusterv1 .ConditionSeverityError ,
275
- "VariableDiscovery failed: %s" , kerrors .NewAggregate (errs ))
276
- return errors .Wrapf (kerrors .NewAggregate (errs ), "failed to discover variables for ClusterClass %s" , clusterClass .Name )
339
+ return ctrl.Result {}, errors .Wrapf (err , "failed to discover variables for ClusterClass %s" , clusterClass .Name )
277
340
}
278
341
279
342
statusVarList := []clusterv1.ClusterClassStatusVariable {}
@@ -297,37 +360,11 @@ func (r *Reconciler) reconcileVariables(ctx context.Context, clusterClass *clust
297
360
298
361
if len (variablesWithConflict ) > 0 {
299
362
err := fmt .Errorf ("the following variables have conflicting schemas: %s" , strings .Join (variablesWithConflict , "," ))
300
- conditions .MarkFalse (clusterClass , clusterv1 .ClusterClassVariablesReconciledCondition , clusterv1 .VariableDiscoveryFailedReason , clusterv1 .ConditionSeverityError ,
301
- "VariableDiscovery failed: %s" , err )
302
- return errors .Wrapf (err , "failed to discover variables for ClusterClass %s" , clusterClass .Name )
363
+ s .variableDiscoveryError = errors .Wrapf (err , "VariableDiscovery failed" )
364
+ return ctrl.Result {}, errors .Wrapf (err , "failed to discover variables for ClusterClass %s" , clusterClass .Name )
303
365
}
304
366
305
- conditions .MarkTrue (clusterClass , clusterv1 .ClusterClassVariablesReconciledCondition )
306
- return nil
307
- }
308
-
309
- func reconcileConditions (clusterClass * clusterv1.ClusterClass , outdatedRefs map [* corev1.ObjectReference ]* corev1.ObjectReference ) {
310
- if len (outdatedRefs ) > 0 {
311
- var msg []string
312
- for currentRef , updatedRef := range outdatedRefs {
313
- msg = append (msg , fmt .Sprintf ("Ref %q should be %q" , refString (currentRef ), refString (updatedRef )))
314
- }
315
- conditions .Set (
316
- clusterClass ,
317
- conditions .FalseCondition (
318
- clusterv1 .ClusterClassRefVersionsUpToDateCondition ,
319
- clusterv1 .ClusterClassOutdatedRefVersionsReason ,
320
- clusterv1 .ConditionSeverityWarning ,
321
- strings .Join (msg , ", " ),
322
- ),
323
- )
324
- return
325
- }
326
-
327
- conditions .Set (
328
- clusterClass ,
329
- conditions .TrueCondition (clusterv1 .ClusterClassRefVersionsUpToDateCondition ),
330
- )
367
+ return ctrl.Result {}, nil
331
368
}
332
369
333
370
func addNewStatusVariable (variable clusterv1.ClusterClassVariable , from string ) * clusterv1.ClusterClassStatusVariable {
@@ -373,7 +410,7 @@ func (r *Reconciler) reconcileExternal(ctx context.Context, clusterClass *cluste
373
410
obj , err := external .Get (ctx , r .Client , ref , clusterClass .Namespace )
374
411
if err != nil {
375
412
if apierrors .IsNotFound (errors .Cause (err )) {
376
- return errors .Wrapf (err , "Could not find external object for the ClusterClass. refGroupVersionKind: %s, refName: %s" , ref .GroupVersionKind (), ref .Name )
413
+ return errors .Wrapf (err , "could not find external object for the ClusterClass. refGroupVersionKind: %s, refName: %s" , ref .GroupVersionKind (), ref .Name )
377
414
}
378
415
return errors .Wrapf (err , "failed to get the external object for the ClusterClass. refGroupVersionKind: %s, refName: %s" , ref .GroupVersionKind (), ref .Name )
379
416
}
@@ -384,7 +421,7 @@ func (r *Reconciler) reconcileExternal(ctx context.Context, clusterClass *cluste
384
421
return err
385
422
}
386
423
387
- // Set external object ControllerReference to the ClusterClass.
424
+ // Set external object owner reference to the ClusterClass.
388
425
if err := controllerutil .SetOwnerReference (clusterClass , obj , r .Client .Scheme ()); err != nil {
389
426
return errors .Wrapf (err , "failed to set ClusterClass owner reference for %s %s" , obj .GetKind (), klog .KObj (obj ))
390
427
}
0 commit comments