Skip to content

Commit 2a3745e

Browse files
authored
Add support for pausing cluster reconcilation (#1769)
1 parent 9b07704 commit 2a3745e

File tree

3 files changed

+95
-10
lines changed

3 files changed

+95
-10
lines changed

controllers/ibmpowervscluster_controller.go

+17-2
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@ import (
3636
ctrl "sigs.k8s.io/controller-runtime"
3737
"sigs.k8s.io/controller-runtime/pkg/client"
3838
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
39+
"sigs.k8s.io/controller-runtime/pkg/handler"
3940
"sigs.k8s.io/controller-runtime/pkg/reconcile"
41+
"sigs.k8s.io/controller-runtime/pkg/source"
4042

4143
capiv1beta1 "sigs.k8s.io/cluster-api/api/v1beta1"
4244
"sigs.k8s.io/cluster-api/util"
@@ -562,8 +564,21 @@ func (c clusterDescendants) filterOwnedDescendants(cluster *infrav1beta2.IBMPowe
562564

563565
// SetupWithManager creates a new IBMPowerVSCluster controller for a manager.
564566
func (r *IBMPowerVSClusterReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager) error {
565-
return ctrl.NewControllerManagedBy(mgr).
567+
controller, err := ctrl.NewControllerManagedBy(mgr).
566568
For(&infrav1beta2.IBMPowerVSCluster{}).
567569
WithEventFilter(predicates.ResourceIsNotExternallyManaged(ctrl.LoggerFrom(ctx))).
568-
Complete(r)
570+
WithEventFilter(predicates.ResourceNotPaused(ctrl.LoggerFrom(ctx))).
571+
Build(r)
572+
if err != nil {
573+
return errors.Wrap(err, "error creating controller")
574+
}
575+
// Add a watch on capiv1beta1.Cluster object for unpause notifications.
576+
if err = controller.Watch(
577+
source.Kind[client.Object](mgr.GetCache(), &capiv1beta1.Cluster{},
578+
handler.EnqueueRequestsFromMapFunc(util.ClusterToInfrastructureMapFunc(ctx, infrav1beta2.GroupVersion.WithKind("IBMPowerVSCluster"), mgr.GetClient(), &infrav1beta2.IBMPowerVSCluster{})),
579+
predicates.ClusterUnpaused(ctrl.LoggerFrom(ctx)),
580+
)); err != nil {
581+
return errors.Wrap(err, "failed adding a watch for ready clusters")
582+
}
583+
return nil
569584
}

controllers/ibmpowervsmachine_controller.go

+77-7
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"time"
2323

2424
"github.com/go-logr/logr"
25+
"github.com/pkg/errors"
2526

2627
"github.com/IBM-Cloud/power-go-client/power/models"
2728

@@ -34,11 +35,14 @@ import (
3435
ctrl "sigs.k8s.io/controller-runtime"
3536
"sigs.k8s.io/controller-runtime/pkg/client"
3637
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
38+
"sigs.k8s.io/controller-runtime/pkg/handler"
39+
"sigs.k8s.io/controller-runtime/pkg/source"
3740

3841
capiv1beta1 "sigs.k8s.io/cluster-api/api/v1beta1"
3942
capierrors "sigs.k8s.io/cluster-api/errors"
4043
"sigs.k8s.io/cluster-api/util"
4144
"sigs.k8s.io/cluster-api/util/conditions"
45+
"sigs.k8s.io/cluster-api/util/predicates"
4246

4347
infrav1beta2 "sigs.k8s.io/cluster-api-provider-ibmcloud/api/v1beta2"
4448
"sigs.k8s.io/cluster-api-provider-ibmcloud/cloud/scope"
@@ -156,13 +160,6 @@ func (r *IBMPowerVSMachineReconciler) Reconcile(ctx context.Context, req ctrl.Re
156160
return r.reconcileNormal(machineScope)
157161
}
158162

159-
// SetupWithManager creates a new IBMPowerVSMachine controller for a manager.
160-
func (r *IBMPowerVSMachineReconciler) SetupWithManager(mgr ctrl.Manager) error {
161-
return ctrl.NewControllerManagedBy(mgr).
162-
For(&infrav1beta2.IBMPowerVSMachine{}).
163-
Complete(r)
164-
}
165-
166163
func (r *IBMPowerVSMachineReconciler) reconcileDelete(scope *scope.PowerVSMachineScope) (_ ctrl.Result, reterr error) {
167164
scope.Info("Handling deleted IBMPowerVSMachine")
168165

@@ -311,3 +308,76 @@ func (r *IBMPowerVSMachineReconciler) reconcileNormal(machineScope *scope.PowerV
311308

312309
return ctrl.Result{}, nil
313310
}
311+
312+
// IBMPowerVSClusterToIBMPowerVSMachines is a handler.ToRequestsFunc to be used to enqeue requests for reconciliation
313+
// of IBMPowerVSMachines.
314+
func (r *IBMPowerVSMachineReconciler) IBMPowerVSClusterToIBMPowerVSMachines(ctx context.Context) handler.MapFunc {
315+
log := ctrl.LoggerFrom(ctx)
316+
return func(mapCtx context.Context, o client.Object) []ctrl.Request {
317+
result := []ctrl.Request{}
318+
319+
c, ok := o.(*infrav1beta2.IBMPowerVSCluster)
320+
if !ok {
321+
log.Error(errors.Errorf("expected a IBMPowerVSCluster but got a %T", o), "failed to get IBMPowerVSMachines for IBMPowerVSCluster")
322+
return nil
323+
}
324+
325+
cluster, err := util.GetOwnerCluster(mapCtx, r.Client, c.ObjectMeta)
326+
switch {
327+
case apierrors.IsNotFound(err) || cluster == nil:
328+
return result
329+
case err != nil:
330+
log.Error(err, "failed to get owning cluster")
331+
return result
332+
}
333+
334+
labels := map[string]string{capiv1beta1.ClusterNameLabel: cluster.Name}
335+
machineList := &capiv1beta1.MachineList{}
336+
if err := r.List(mapCtx, machineList, client.InNamespace(c.Namespace), client.MatchingLabels(labels)); err != nil {
337+
log.Error(err, "failed to list Machines")
338+
return nil
339+
}
340+
for _, m := range machineList.Items {
341+
if m.Spec.InfrastructureRef.Name == "" {
342+
continue
343+
}
344+
name := client.ObjectKey{Namespace: m.Namespace, Name: m.Spec.InfrastructureRef.Name}
345+
result = append(result, ctrl.Request{NamespacedName: name})
346+
}
347+
348+
return result
349+
}
350+
}
351+
352+
// SetupWithManager creates a new IBMVPCMachine controller for a manager.
353+
func (r *IBMPowerVSMachineReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager) error {
354+
controller, err := ctrl.NewControllerManagedBy(mgr).
355+
For(&infrav1beta2.IBMPowerVSMachine{}).
356+
WithEventFilter(predicates.ResourceNotPaused(ctrl.LoggerFrom(ctx))).
357+
Watches(
358+
&capiv1beta1.Machine{},
359+
handler.EnqueueRequestsFromMapFunc(util.MachineToInfrastructureMapFunc(infrav1beta2.GroupVersion.WithKind("IBMPowerVSMachine"))),
360+
).
361+
Watches(
362+
&infrav1beta2.IBMPowerVSCluster{},
363+
handler.EnqueueRequestsFromMapFunc(r.IBMPowerVSClusterToIBMPowerVSMachines(ctx)),
364+
).
365+
Build(r)
366+
if err != nil {
367+
return errors.Wrap(err, "error creating controller")
368+
}
369+
370+
clusterToObjectFunc, err := util.ClusterToTypedObjectsMapper(r.Client, &infrav1beta2.IBMPowerVSMachineList{}, mgr.GetScheme())
371+
if err != nil {
372+
return errors.Wrap(err, "failed to create mapper for Cluster to IBMPowerVSMachines")
373+
}
374+
// Add a watch on capiv1beta1.Cluster object for unpause & ready notifications.
375+
if err := controller.Watch(
376+
source.Kind[client.Object](mgr.GetCache(), &capiv1beta1.Cluster{},
377+
handler.EnqueueRequestsFromMapFunc(clusterToObjectFunc),
378+
predicates.ClusterUnpausedAndInfrastructureReady(ctrl.LoggerFrom(ctx)),
379+
)); err != nil {
380+
return errors.Wrap(err, "failed adding a watch for ready clusters")
381+
}
382+
return nil
383+
}

main.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ func setupReconcilers(ctx context.Context, mgr ctrl.Manager, serviceEndpoint []e
285285
Recorder: mgr.GetEventRecorderFor("ibmpowervsmachine-controller"),
286286
ServiceEndpoint: serviceEndpoint,
287287
Scheme: mgr.GetScheme(),
288-
}).SetupWithManager(mgr); err != nil {
288+
}).SetupWithManager(ctx, mgr); err != nil {
289289
setupLog.Error(err, "unable to create controller", "controller", "IBMPowerVSMachine")
290290
os.Exit(1)
291291
}

0 commit comments

Comments
 (0)