@@ -19,7 +19,6 @@ package cluster
19
19
import (
20
20
"context"
21
21
"fmt"
22
- "path"
23
22
"strings"
24
23
"time"
25
24
@@ -28,6 +27,7 @@ import (
28
27
apierrors "k8s.io/apimachinery/pkg/api/errors"
29
28
"k8s.io/apimachinery/pkg/api/meta"
30
29
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
30
+ "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
31
31
"k8s.io/apimachinery/pkg/runtime"
32
32
kerrors "k8s.io/apimachinery/pkg/util/errors"
33
33
"k8s.io/client-go/tools/record"
@@ -141,6 +141,10 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (_ ctrl.Re
141
141
return ctrl.Result {}, err
142
142
}
143
143
144
+ s := & scope {
145
+ cluster : cluster ,
146
+ }
147
+
144
148
// Initialize the patch helper.
145
149
patchHelper , err := patch .NewHelper (cluster , r .Client )
146
150
if err != nil {
@@ -185,13 +189,28 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (_ ctrl.Re
185
189
})
186
190
}
187
191
192
+ alwaysReconcile := []clusterReconcileFunc {
193
+ r .reconcileInfrastructure ,
194
+ r .reconcileControlPlane ,
195
+ }
196
+
188
197
// Handle deletion reconciliation loop.
189
198
if ! cluster .ObjectMeta .DeletionTimestamp .IsZero () {
190
- return r .reconcileDelete (ctx , cluster )
199
+ reconcileDelete := append (
200
+ alwaysReconcile ,
201
+ r .reconcileDelete ,
202
+ )
203
+
204
+ return doReconcile (ctx , reconcileDelete , s )
191
205
}
192
206
193
207
// Handle normal reconciliation loop.
194
- return r .reconcile (ctx , cluster )
208
+ reconcileNormal := append (
209
+ alwaysReconcile ,
210
+ r .reconcileKubeconfig ,
211
+ r .reconcileControlPlaneInitialized ,
212
+ )
213
+ return doReconcile (ctx , reconcileNormal , s )
195
214
}
196
215
197
216
func patchCluster (ctx context.Context , patchHelper * patch.Helper , cluster * clusterv1.Cluster , options ... patch.Option ) error {
@@ -216,30 +235,14 @@ func patchCluster(ctx context.Context, patchHelper *patch.Helper, cluster *clust
216
235
return patchHelper .Patch (ctx , cluster , options ... )
217
236
}
218
237
219
- // reconcile handles cluster reconciliation.
220
- func (r * Reconciler ) reconcile (ctx context.Context , cluster * clusterv1.Cluster ) (ctrl.Result , error ) {
221
- log := ctrl .LoggerFrom (ctx )
222
-
223
- if cluster .Spec .Topology != nil {
224
- if cluster .Spec .ControlPlaneRef == nil || cluster .Spec .InfrastructureRef == nil {
225
- // TODO: add a condition to surface this scenario
226
- log .Info ("Waiting for the topology to be generated" )
227
- return ctrl.Result {}, nil
228
- }
229
- }
230
-
231
- phases := []func (context.Context , * clusterv1.Cluster ) (ctrl.Result , error ){
232
- r .reconcileInfrastructure ,
233
- r .reconcileControlPlane ,
234
- r .reconcileKubeconfig ,
235
- r .reconcileControlPlaneInitialized ,
236
- }
238
+ type clusterReconcileFunc func (context.Context , * scope ) (ctrl.Result , error )
237
239
240
+ func doReconcile (ctx context.Context , phases []clusterReconcileFunc , s * scope ) (ctrl.Result , error ) {
238
241
res := ctrl.Result {}
239
242
errs := []error {}
240
243
for _ , phase := range phases {
241
244
// Call the inner reconciliation methods.
242
- phaseResult , err := phase (ctx , cluster )
245
+ phaseResult , err := phase (ctx , s )
243
246
if err != nil {
244
247
errs = append (errs , err )
245
248
}
@@ -248,12 +251,42 @@ func (r *Reconciler) reconcile(ctx context.Context, cluster *clusterv1.Cluster)
248
251
}
249
252
res = util .LowestNonZeroResult (res , phaseResult )
250
253
}
251
- return res , kerrors .NewAggregate (errs )
254
+
255
+ if len (errs ) > 0 {
256
+ return ctrl.Result {}, kerrors .NewAggregate (errs )
257
+ }
258
+
259
+ return res , nil
260
+ }
261
+
262
+ // scope holds the different objects that are read and used during the reconcile.
263
+ type scope struct {
264
+ // cluster is the Cluster object the Machine belongs to.
265
+ // It is set at the beginning of the reconcile function.
266
+ cluster * clusterv1.Cluster
267
+
268
+ // infraCluster is the Infrastructure Cluster object that is referenced by the
269
+ // Cluster. It is set after reconcileInfrastructure is called.
270
+ infraCluster * unstructured.Unstructured
271
+
272
+ // infraClusterNotFound is true if getting the infra cluster object failed with an NotFound err
273
+ infraClusterIsNotFound bool
274
+
275
+ // controlPlane is the ControlPlane object that is referenced by the
276
+ // Cluster. It is set after reconcileBootstrap is called.
277
+ controlPlane * unstructured.Unstructured
278
+
279
+ // controlPlaneNotFound is true if getting the ControlPlane object failed with an NotFound err
280
+ controlPlaneIsNotFound bool
281
+
282
+ // descendants is the list of objects related to this Cluster
283
+ // descendants clusterDescendants
252
284
}
253
285
254
286
// reconcileDelete handles cluster deletion.
255
- func (r * Reconciler ) reconcileDelete (ctx context.Context , cluster * clusterv1. Cluster ) (reconcile.Result , error ) {
287
+ func (r * Reconciler ) reconcileDelete (ctx context.Context , s * scope ) (reconcile.Result , error ) {
256
288
log := ctrl .LoggerFrom (ctx )
289
+ cluster := s .cluster
257
290
258
291
// If the RuntimeSDK and ClusterTopology flags are enabled, for clusters with managed topologies
259
292
// only proceed with delete if the cluster is marked as `ok-to-delete`
@@ -314,28 +347,18 @@ func (r *Reconciler) reconcileDelete(ctx context.Context, cluster *clusterv1.Clu
314
347
}
315
348
316
349
if cluster .Spec .ControlPlaneRef != nil {
317
- obj , err := external .Get (ctx , r .Client , cluster .Spec .ControlPlaneRef , cluster .Namespace )
318
- switch {
319
- case apierrors .IsNotFound (errors .Cause (err )):
350
+ if s .controlPlaneIsNotFound {
320
351
// All good - the control plane resource has been deleted
321
352
conditions .MarkFalse (cluster , clusterv1 .ControlPlaneReadyCondition , clusterv1 .DeletedReason , clusterv1 .ConditionSeverityInfo , "" )
322
- case err != nil :
323
- return reconcile.Result {}, errors .Wrapf (err , "failed to get %s %q for Cluster %s/%s" ,
324
- path .Join (cluster .Spec .ControlPlaneRef .APIVersion , cluster .Spec .ControlPlaneRef .Kind ),
325
- cluster .Spec .ControlPlaneRef .Name , cluster .Namespace , cluster .Name )
326
- default :
327
- // Report a summary of current status of the control plane object defined for this cluster.
328
- conditions .SetMirror (cluster , clusterv1 .ControlPlaneReadyCondition ,
329
- conditions .UnstructuredGetter (obj ),
330
- conditions .WithFallbackValue (false , clusterv1 .DeletingReason , clusterv1 .ConditionSeverityInfo , "" ),
331
- )
353
+ }
332
354
355
+ if s .controlPlane != nil {
333
356
// Issue a deletion request for the control plane object.
334
357
// Once it's been deleted, the cluster will get processed again.
335
- if err := r .Client .Delete (ctx , obj ); err != nil {
358
+ if err := r .Client .Delete (ctx , s . controlPlane ); err != nil {
336
359
return ctrl.Result {}, errors .Wrapf (err ,
337
360
"failed to delete %v %q for Cluster %q in namespace %q" ,
338
- obj . GroupVersionKind (), obj .GetName (), cluster .Name , cluster .Namespace )
361
+ s . controlPlane . GroupVersionKind (), s . controlPlane .GetName (), cluster .Name , cluster .Namespace )
339
362
}
340
363
341
364
// Return here so we don't remove the finalizer yet.
@@ -345,28 +368,18 @@ func (r *Reconciler) reconcileDelete(ctx context.Context, cluster *clusterv1.Clu
345
368
}
346
369
347
370
if cluster .Spec .InfrastructureRef != nil {
348
- obj , err := external .Get (ctx , r .Client , cluster .Spec .InfrastructureRef , cluster .Namespace )
349
- switch {
350
- case apierrors .IsNotFound (errors .Cause (err )):
371
+ if s .infraClusterIsNotFound {
351
372
// All good - the infra resource has been deleted
352
373
conditions .MarkFalse (cluster , clusterv1 .InfrastructureReadyCondition , clusterv1 .DeletedReason , clusterv1 .ConditionSeverityInfo , "" )
353
- case err != nil :
354
- return ctrl.Result {}, errors .Wrapf (err , "failed to get %s %q for Cluster %s/%s" ,
355
- path .Join (cluster .Spec .InfrastructureRef .APIVersion , cluster .Spec .InfrastructureRef .Kind ),
356
- cluster .Spec .InfrastructureRef .Name , cluster .Namespace , cluster .Name )
357
- default :
358
- // Report a summary of current status of the infrastructure object defined for this cluster.
359
- conditions .SetMirror (cluster , clusterv1 .InfrastructureReadyCondition ,
360
- conditions .UnstructuredGetter (obj ),
361
- conditions .WithFallbackValue (false , clusterv1 .DeletingReason , clusterv1 .ConditionSeverityInfo , "" ),
362
- )
374
+ }
363
375
376
+ if s .infraCluster != nil {
364
377
// Issue a deletion request for the infrastructure object.
365
378
// Once it's been deleted, the cluster will get processed again.
366
- if err := r .Client .Delete (ctx , obj ); err != nil {
379
+ if err := r .Client .Delete (ctx , s . infraCluster ); err != nil {
367
380
return ctrl.Result {}, errors .Wrapf (err ,
368
381
"failed to delete %v %q for Cluster %q in namespace %q" ,
369
- obj . GroupVersionKind (), obj .GetName (), cluster .Name , cluster .Namespace )
382
+ s . infraCluster . GroupVersionKind (), s . infraCluster .GetName (), cluster .Name , cluster .Namespace )
370
383
}
371
384
372
385
// Return here so we don't remove the finalizer yet.
@@ -516,8 +529,9 @@ func (c clusterDescendants) filterOwnedDescendants(cluster *clusterv1.Cluster) (
516
529
return ownedDescendants , nil
517
530
}
518
531
519
- func (r * Reconciler ) reconcileControlPlaneInitialized (ctx context.Context , cluster * clusterv1. Cluster ) (ctrl.Result , error ) {
532
+ func (r * Reconciler ) reconcileControlPlaneInitialized (ctx context.Context , s * scope ) (ctrl.Result , error ) {
520
533
log := ctrl .LoggerFrom (ctx )
534
+ cluster := s .cluster
521
535
522
536
// Skip checking if the control plane is initialized when using a Control Plane Provider (this is reconciled in
523
537
// reconcileControlPlane instead).
0 commit comments