@@ -47,7 +47,7 @@ import (
4747 "sigs.k8s.io/cluster-api/feature"
4848 runtimeclient "sigs.k8s.io/cluster-api/internal/runtime/client"
4949 "sigs.k8s.io/cluster-api/internal/topology/variables"
50- "sigs.k8s.io/cluster-api/util/conditions "
50+ "sigs.k8s.io/cluster-api/util"
5151 "sigs.k8s.io/cluster-api/util/conversion"
5252 "sigs.k8s.io/cluster-api/util/patch"
5353 "sigs.k8s.io/cluster-api/util/paused"
@@ -94,7 +94,7 @@ func (r *Reconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager, opt
9494 return nil
9595}
9696
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 ) {
9898 clusterClass := & clusterv1.ClusterClass {}
9999 if err := r .Client .Get (ctx , req .NamespacedName , clusterClass ); err != nil {
100100 if apierrors .IsNotFound (err ) {
@@ -112,40 +112,94 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (_ ctrl.Re
112112 return ctrl.Result {}, nil
113113 }
114114
115+ s := & scope {
116+ clusterClass : clusterClass ,
117+ }
118+
115119 patchHelper , err := patch .NewHelper (clusterClass , r .Client )
116120 if err != nil {
117121 return ctrl.Result {}, err
118122 }
119123
120124 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+
121138 // Patch ObservedGeneration only if the reconciliation completed successfully
122- patchOpts := []patch.Option {}
123139 if reterr == nil {
124140 patchOpts = append (patchOpts , patch.WithStatusObservedGeneration {})
125141 }
126142 if err := patchHelper .Patch (ctx , clusterClass , patchOpts ... ); err != nil {
127143 reterr = kerrors .NewAggregate ([]error {reterr , err })
128144 return
129145 }
146+
147+ if reterr != nil {
148+ retres = ctrl.Result {}
149+ }
130150 }()
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 )
132157}
133158
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 )
137174 }
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 )
141178 }
142179
143- reconcileConditions (clusterClass , outdatedRefs )
180+ return res , nil
181+ }
144182
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
146198}
147199
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+
149203 // Collect all the reference from the ClusterClass to templates.
150204 refs := []* corev1.ObjectReference {}
151205
@@ -185,7 +239,7 @@ func (r *Reconciler) reconcileExternalReferences(ctx context.Context, clusterCla
185239 // or MachinePool classes.
186240 errs := []error {}
187241 reconciledRefs := sets.Set [string ]{}
188- outdatedRefs := map [ * corev1. ObjectReference ] * corev1. ObjectReference {}
242+ outdatedRefs := [] outdatedRef {}
189243 for i := range refs {
190244 ref := refs [i ]
191245 uniqueKey := uniqueObjectRefKey (ref )
@@ -212,16 +266,25 @@ func (r *Reconciler) reconcileExternalReferences(ctx context.Context, clusterCla
212266 errs = append (errs , err )
213267 }
214268 if ref .GroupVersionKind ().Version != updatedRef .GroupVersionKind ().Version {
215- outdatedRefs [ref ] = updatedRef
269+ outdatedRefs = append (outdatedRefs , outdatedRef {
270+ Outdated : ref ,
271+ UpToDate : updatedRef ,
272+ })
216273 }
217274 }
218275 if len (errs ) > 0 {
219- return nil , kerrors .NewAggregate (errs )
276+ err := kerrors .NewAggregate (errs )
277+ s .reconcileExternalReferencesError = err
278+ return ctrl.Result {}, err
220279 }
221- return outdatedRefs , nil
280+
281+ s .outdatedExternalReferences = outdatedRefs
282+ return ctrl.Result {}, nil
222283}
223284
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+
225288 errs := []error {}
226289 allVariableDefinitions := map [string ]* clusterv1.ClusterClassStatusVariable {}
227290 // Add inline variable definitions to the ClusterClass status.
@@ -270,10 +333,10 @@ func (r *Reconciler) reconcileVariables(ctx context.Context, clusterClass *clust
270333 }
271334 }
272335 if len (errs ) > 0 {
336+ err := kerrors .NewAggregate (errs )
337+ s .variableDiscoveryError = errors .Wrapf (err , "VariableDiscovery failed" )
273338 // 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 )
277340 }
278341
279342 statusVarList := []clusterv1.ClusterClassStatusVariable {}
@@ -297,37 +360,11 @@ func (r *Reconciler) reconcileVariables(ctx context.Context, clusterClass *clust
297360
298361 if len (variablesWithConflict ) > 0 {
299362 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 )
303365 }
304366
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
331368}
332369
333370func addNewStatusVariable (variable clusterv1.ClusterClassVariable , from string ) * clusterv1.ClusterClassStatusVariable {
@@ -373,7 +410,7 @@ func (r *Reconciler) reconcileExternal(ctx context.Context, clusterClass *cluste
373410 obj , err := external .Get (ctx , r .Client , ref , clusterClass .Namespace )
374411 if err != nil {
375412 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 )
377414 }
378415 return errors .Wrapf (err , "failed to get the external object for the ClusterClass. refGroupVersionKind: %s, refName: %s" , ref .GroupVersionKind (), ref .Name )
379416 }
@@ -384,7 +421,7 @@ func (r *Reconciler) reconcileExternal(ctx context.Context, clusterClass *cluste
384421 return err
385422 }
386423
387- // Set external object ControllerReference to the ClusterClass.
424+ // Set external object owner reference to the ClusterClass.
388425 if err := controllerutil .SetOwnerReference (clusterClass , obj , r .Client .Scheme ()); err != nil {
389426 return errors .Wrapf (err , "failed to set ClusterClass owner reference for %s %s" , obj .GetKind (), klog .KObj (obj ))
390427 }
0 commit comments