Skip to content

Commit 30c377c

Browse files
committed
Update and unify cluster/resource paused handling
- Ports predicates for handling paused annotations on resources from cluster-api-provider-aws - Includes logging of predicate handling (level v4) - Adds predicatee helpers for: - Aggregating predicates - adding a Watch to a controller for triggering updates on Cluster.Spec.Paused transitioning to false - Includes logging for predicate handling (level v4) - Avoids triggering events for Delete/Generic events - adding a Watch to a controller for triggering updates on both Cluster.Spec.Paused and Cluster.Status.InfrastructureReady - Includes logging for predicate handling (level v4) - Avoids triggering events for Delete/Generic events - Ensures that controllers get prompt updates for Cluster.Status.InfrastructureReady becoming true where needed - Updates in-tree controllers to standardize on the use of the above helpers - Unifies other aspects of paused handling among in-tree controllers
1 parent 0bb5cbf commit 30c377c

22 files changed

+623
-115
lines changed

Diff for: bootstrap/kubeadm/controllers/kubeadmconfig_controller.go

+23-9
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@ import (
4242
expv1 "sigs.k8s.io/cluster-api/exp/api/v1alpha3"
4343
"sigs.k8s.io/cluster-api/feature"
4444
"sigs.k8s.io/cluster-api/util"
45+
"sigs.k8s.io/cluster-api/util/annotations"
4546
"sigs.k8s.io/cluster-api/util/patch"
47+
"sigs.k8s.io/cluster-api/util/predicates"
4648
"sigs.k8s.io/cluster-api/util/secret"
4749
ctrl "sigs.k8s.io/controller-runtime"
4850
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -90,35 +92,42 @@ func (r *KubeadmConfigReconciler) SetupWithManager(mgr ctrl.Manager, option cont
9092

9193
r.scheme = mgr.GetScheme()
9294

93-
builder := ctrl.NewControllerManagedBy(mgr).
95+
b := ctrl.NewControllerManagedBy(mgr).
9496
For(&bootstrapv1.KubeadmConfig{}).
9597
WithOptions(option).
98+
WithEventFilter(predicates.ResourceNotPaused(r.Log)).
9699
Watches(
97100
&source.Kind{Type: &clusterv1.Machine{}},
98101
&handler.EnqueueRequestsFromMapFunc{
99102
ToRequests: handler.ToRequestsFunc(r.MachineToBootstrapMapFunc),
100103
},
101-
).
102-
Watches(
103-
&source.Kind{Type: &clusterv1.Cluster{}},
104-
&handler.EnqueueRequestsFromMapFunc{
105-
ToRequests: handler.ToRequestsFunc(r.ClusterToKubeadmConfigs),
106-
},
107104
)
108105

109106
if feature.Gates.Enabled(feature.MachinePool) {
110-
builder = builder.Watches(
107+
b = b.Watches(
111108
&source.Kind{Type: &expv1.MachinePool{}},
112109
&handler.EnqueueRequestsFromMapFunc{
113110
ToRequests: handler.ToRequestsFunc(r.MachinePoolToBootstrapMapFunc),
114111
},
115112
)
116113
}
117114

118-
if err := builder.Complete(r); err != nil {
115+
c, err := b.Build(r)
116+
if err != nil {
119117
return errors.Wrap(err, "failed setting up with a controller manager")
120118
}
121119

120+
err = c.Watch(
121+
&source.Kind{Type: &clusterv1.Cluster{}},
122+
&handler.EnqueueRequestsFromMapFunc{
123+
ToRequests: handler.ToRequestsFunc(r.ClusterToKubeadmConfigs),
124+
},
125+
predicates.ClusterUnpausedAndInfrastructureReady(r.Log),
126+
)
127+
if err != nil {
128+
return errors.Wrap(err, "failed adding Watch for Clusters to controller manager")
129+
}
130+
122131
return nil
123132
}
124133

@@ -168,6 +177,11 @@ func (r *KubeadmConfigReconciler) Reconcile(req ctrl.Request) (_ ctrl.Result, re
168177
return ctrl.Result{}, err
169178
}
170179

180+
if annotations.IsPaused(cluster, config) {
181+
log.Info("Reconciliation is paused for this object")
182+
return ctrl.Result{}, nil
183+
}
184+
171185
scope := &Scope{
172186
Logger: log,
173187
Config: config,

Diff for: controllers/cluster_controller.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@ import (
3535
"sigs.k8s.io/cluster-api/controllers/metrics"
3636
capierrors "sigs.k8s.io/cluster-api/errors"
3737
"sigs.k8s.io/cluster-api/util"
38+
"sigs.k8s.io/cluster-api/util/annotations"
3839
"sigs.k8s.io/cluster-api/util/patch"
40+
"sigs.k8s.io/cluster-api/util/predicates"
3941
"sigs.k8s.io/cluster-api/util/secret"
4042
ctrl "sigs.k8s.io/controller-runtime"
4143
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -77,6 +79,7 @@ func (r *ClusterReconciler) SetupWithManager(mgr ctrl.Manager, options controlle
7779
&handler.EnqueueRequestsFromMapFunc{ToRequests: handler.ToRequestsFunc(r.controlPlaneMachineToCluster)},
7880
).
7981
WithOptions(options).
82+
WithEventFilter(predicates.ResourceNotPaused(r.Log)).
8083
Build(r)
8184

8285
if err != nil {
@@ -109,7 +112,7 @@ func (r *ClusterReconciler) Reconcile(req ctrl.Request) (_ ctrl.Result, reterr e
109112
}
110113

111114
// Return early if the object or Cluster is paused.
112-
if util.IsPaused(cluster, cluster) {
115+
if annotations.IsPaused(cluster, cluster) {
113116
logger.Info("Reconciliation is paused for this object")
114117
return ctrl.Result{}, nil
115118
}

Diff for: controllers/cluster_controller_phases.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import (
2929
"sigs.k8s.io/cluster-api/controllers/external"
3030
capierrors "sigs.k8s.io/cluster-api/errors"
3131
"sigs.k8s.io/cluster-api/util"
32+
"sigs.k8s.io/cluster-api/util/annotations"
3233
utilconversion "sigs.k8s.io/cluster-api/util/conversion"
3334
"sigs.k8s.io/cluster-api/util/kubeconfig"
3435
"sigs.k8s.io/cluster-api/util/patch"
@@ -78,7 +79,7 @@ func (r *ClusterReconciler) reconcileExternal(ctx context.Context, cluster *clus
7879
}
7980

8081
// if external ref is paused, return error.
81-
if util.IsPaused(cluster, obj) {
82+
if annotations.IsPaused(cluster, obj) {
8283
logger.V(3).Info("External object referenced is paused")
8384
return external.ReconcileOutput{Paused: true}, nil
8485
}

Diff for: controllers/external/tracker.go

+2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"github.com/pkg/errors"
2424
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
2525
"k8s.io/apimachinery/pkg/runtime"
26+
"sigs.k8s.io/cluster-api/util/predicates"
2627
"sigs.k8s.io/controller-runtime/pkg/controller"
2728
"sigs.k8s.io/controller-runtime/pkg/handler"
2829
"sigs.k8s.io/controller-runtime/pkg/source"
@@ -55,6 +56,7 @@ func (o *ObjectTracker) Watch(log logr.Logger, obj runtime.Object, handler handl
5556
err := o.Controller.Watch(
5657
&source.Kind{Type: u},
5758
handler,
59+
predicates.ResourceNotPaused(log),
5860
)
5961
if err != nil {
6062
o.m.Delete(obj)

Diff for: controllers/machine_controller.go

+19-8
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,16 @@ import (
4242
capierrors "sigs.k8s.io/cluster-api/errors"
4343
kubedrain "sigs.k8s.io/cluster-api/third_party/kubernetes-drain"
4444
"sigs.k8s.io/cluster-api/util"
45+
"sigs.k8s.io/cluster-api/util/annotations"
4546
"sigs.k8s.io/cluster-api/util/patch"
47+
"sigs.k8s.io/cluster-api/util/predicates"
4648
ctrl "sigs.k8s.io/controller-runtime"
4749
"sigs.k8s.io/controller-runtime/pkg/client"
4850
"sigs.k8s.io/controller-runtime/pkg/controller"
4951
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
5052
"sigs.k8s.io/controller-runtime/pkg/handler"
5153
"sigs.k8s.io/controller-runtime/pkg/reconcile"
54+
"sigs.k8s.io/controller-runtime/pkg/source"
5255
)
5356

5457
var (
@@ -77,22 +80,30 @@ type MachineReconciler struct {
7780
}
7881

7982
func (r *MachineReconciler) SetupWithManager(mgr ctrl.Manager, options controller.Options) error {
83+
clusterToMachines, err := util.ClusterToObjectsMapper(mgr.GetClient(), &clusterv1.MachineList{}, mgr.GetScheme())
84+
if err != nil {
85+
return err
86+
}
87+
8088
controller, err := ctrl.NewControllerManagedBy(mgr).
8189
For(&clusterv1.Machine{}).
8290
WithOptions(options).
91+
WithEventFilter(predicates.ResourceNotPaused(r.Log)).
8392
Build(r)
84-
8593
if err != nil {
8694
return errors.Wrap(err, "failed setting up with a controller manager")
8795
}
8896

89-
// Add a watch on clusterv1.Cluster object for paused notifications.
90-
clusterToMachines, err := util.ClusterToObjectsMapper(mgr.GetClient(), &clusterv1.MachineList{}, mgr.GetScheme())
97+
err = controller.Watch(
98+
&source.Kind{Type: &clusterv1.Cluster{}},
99+
&handler.EnqueueRequestsFromMapFunc{
100+
ToRequests: clusterToMachines,
101+
},
102+
// TODO: should this wait for Cluster.Status.InfrastructureReady similar to Infra Machine resources?
103+
predicates.ClusterUnpaused(r.Log),
104+
)
91105
if err != nil {
92-
return err
93-
}
94-
if err := util.WatchOnClusterPaused(controller, clusterToMachines); err != nil {
95-
return err
106+
return errors.Wrap(err, "failed to add Watch for Clusters to controller manager")
96107
}
97108

98109
r.recorder = mgr.GetEventRecorderFor("machine-controller")
@@ -143,7 +154,7 @@ func (r *MachineReconciler) Reconcile(req ctrl.Request) (_ ctrl.Result, reterr e
143154
}
144155

145156
// Return early if the object or Cluster is paused.
146-
if util.IsPaused(cluster, m) {
157+
if annotations.IsPaused(cluster, m) {
147158
logger.Info("Reconciliation is paused for this object")
148159
return ctrl.Result{}, nil
149160
}

Diff for: controllers/machine_controller_phases.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import (
2828
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2929
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
3030
"k8s.io/utils/pointer"
31+
"sigs.k8s.io/cluster-api/util/annotations"
3132
utilconversion "sigs.k8s.io/cluster-api/util/conversion"
3233
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
3334
"sigs.k8s.io/controller-runtime/pkg/handler"
@@ -102,7 +103,7 @@ func (r *MachineReconciler) reconcileExternal(ctx context.Context, cluster *clus
102103
}
103104

104105
// if external ref is paused, return error.
105-
if util.IsPaused(cluster, obj) {
106+
if annotations.IsPaused(cluster, obj) {
106107
logger.V(3).Info("External object referenced is paused")
107108
return external.ReconcileOutput{Paused: true}, nil
108109
}

Diff for: controllers/machinedeployment_controller.go

+19-9
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ import (
3030
"k8s.io/client-go/tools/record"
3131
clusterv1 "sigs.k8s.io/cluster-api/api/v1alpha3"
3232
"sigs.k8s.io/cluster-api/util"
33+
"sigs.k8s.io/cluster-api/util/annotations"
3334
"sigs.k8s.io/cluster-api/util/patch"
35+
"sigs.k8s.io/cluster-api/util/predicates"
3436
ctrl "sigs.k8s.io/controller-runtime"
3537
"sigs.k8s.io/controller-runtime/pkg/client"
3638
"sigs.k8s.io/controller-runtime/pkg/controller"
@@ -58,27 +60,35 @@ type MachineDeploymentReconciler struct {
5860
}
5961

6062
func (r *MachineDeploymentReconciler) SetupWithManager(mgr ctrl.Manager, options controller.Options) error {
61-
controller, err := ctrl.NewControllerManagedBy(mgr).
63+
clusterToMachineDeployments, err := util.ClusterToObjectsMapper(mgr.GetClient(), &clusterv1.MachineDeploymentList{}, mgr.GetScheme())
64+
if err != nil {
65+
return err
66+
}
67+
68+
c, err := ctrl.NewControllerManagedBy(mgr).
6269
For(&clusterv1.MachineDeployment{}).
6370
Owns(&clusterv1.MachineSet{}).
6471
Watches(
6572
&source.Kind{Type: &clusterv1.MachineSet{}},
6673
&handler.EnqueueRequestsFromMapFunc{ToRequests: handler.ToRequestsFunc(r.MachineSetToDeployments)},
6774
).
6875
WithOptions(options).
76+
WithEventFilter(predicates.ResourceNotPaused(r.Log)).
6977
Build(r)
70-
7178
if err != nil {
7279
return errors.Wrap(err, "failed setting up with a controller manager")
7380
}
7481

75-
// Add a watch on clusterv1.Cluster object for paused notifications.
76-
clusterToMachineDeployments, err := util.ClusterToObjectsMapper(mgr.GetClient(), &clusterv1.MachineDeploymentList{}, mgr.GetScheme())
82+
err = c.Watch(
83+
&source.Kind{Type: &clusterv1.Cluster{}},
84+
&handler.EnqueueRequestsFromMapFunc{
85+
ToRequests: clusterToMachineDeployments,
86+
},
87+
// TODO: should this wait for Cluster.Status.InfrastructureReady similar to Infra Machine resources?
88+
predicates.ClusterUnpaused(r.Log),
89+
)
7790
if err != nil {
78-
return err
79-
}
80-
if err := util.WatchOnClusterPaused(controller, clusterToMachineDeployments); err != nil {
81-
return err
91+
return errors.Wrap(err, "failed to add Watch for Clusters to controller manager")
8292
}
8393

8494
r.recorder = mgr.GetEventRecorderFor("machinedeployment-controller")
@@ -107,7 +117,7 @@ func (r *MachineDeploymentReconciler) Reconcile(req ctrl.Request) (_ ctrl.Result
107117
}
108118

109119
// Return early if the object or Cluster is paused.
110-
if util.IsPaused(cluster, deployment) {
120+
if annotations.IsPaused(cluster, deployment) {
111121
logger.Info("Reconciliation is paused for this object")
112122
return ctrl.Result{}, nil
113123
}

Diff for: controllers/machinehealthcheck_controller.go

+13-6
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@ import (
3535
clusterv1 "sigs.k8s.io/cluster-api/api/v1alpha3"
3636
"sigs.k8s.io/cluster-api/controllers/remote"
3737
"sigs.k8s.io/cluster-api/util"
38+
"sigs.k8s.io/cluster-api/util/annotations"
3839
"sigs.k8s.io/cluster-api/util/patch"
40+
"sigs.k8s.io/cluster-api/util/predicates"
3941
ctrl "sigs.k8s.io/controller-runtime"
4042
"sigs.k8s.io/controller-runtime/pkg/cache"
4143
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -76,20 +78,25 @@ type MachineHealthCheckReconciler struct {
7678
func (r *MachineHealthCheckReconciler) SetupWithManager(mgr ctrl.Manager, options controller.Options) error {
7779
controller, err := ctrl.NewControllerManagedBy(mgr).
7880
For(&clusterv1.MachineHealthCheck{}).
79-
Watches(
80-
&source.Kind{Type: &clusterv1.Cluster{}},
81-
&handler.EnqueueRequestsFromMapFunc{ToRequests: handler.ToRequestsFunc(r.clusterToMachineHealthCheck)},
82-
).
8381
Watches(
8482
&source.Kind{Type: &clusterv1.Machine{}},
8583
&handler.EnqueueRequestsFromMapFunc{ToRequests: handler.ToRequestsFunc(r.machineToMachineHealthCheck)},
8684
).
8785
WithOptions(options).
86+
WithEventFilter(predicates.ResourceNotPaused(r.Log)).
8887
Build(r)
89-
9088
if err != nil {
9189
return errors.Wrap(err, "failed setting up with a controller manager")
9290
}
91+
err = controller.Watch(
92+
&source.Kind{Type: &clusterv1.Cluster{}},
93+
&handler.EnqueueRequestsFromMapFunc{ToRequests: handler.ToRequestsFunc(r.clusterToMachineHealthCheck)},
94+
// TODO: should this wait for Cluster.Status.InfrastructureReady similar to Infra Machine resources?
95+
predicates.ClusterUnpaused(r.Log),
96+
)
97+
if err != nil {
98+
return errors.Wrap(err, "failed to add Watch for Clusters to controller manager")
99+
}
93100

94101
// Add index to MachineHealthCheck for listing by Cluster Name
95102
if err := mgr.GetCache().IndexField(&clusterv1.MachineHealthCheck{},
@@ -140,7 +147,7 @@ func (r *MachineHealthCheckReconciler) Reconcile(req ctrl.Request) (_ ctrl.Resul
140147
}
141148

142149
// Return early if the object or Cluster is paused.
143-
if util.IsPaused(cluster, m) {
150+
if annotations.IsPaused(cluster, m) {
144151
logger.Info("Reconciliation is paused for this object")
145152
return ctrl.Result{}, nil
146153
}

Diff for: controllers/machineset_controller.go

+17-9
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,10 @@ import (
3838
"sigs.k8s.io/cluster-api/controllers/noderefutil"
3939
"sigs.k8s.io/cluster-api/controllers/remote"
4040
"sigs.k8s.io/cluster-api/util"
41+
"sigs.k8s.io/cluster-api/util/annotations"
4142
utilconversion "sigs.k8s.io/cluster-api/util/conversion"
4243
"sigs.k8s.io/cluster-api/util/patch"
44+
"sigs.k8s.io/cluster-api/util/predicates"
4345
ctrl "sigs.k8s.io/controller-runtime"
4446
"sigs.k8s.io/controller-runtime/pkg/client"
4547
"sigs.k8s.io/controller-runtime/pkg/controller"
@@ -75,27 +77,33 @@ type MachineSetReconciler struct {
7577
}
7678

7779
func (r *MachineSetReconciler) SetupWithManager(mgr ctrl.Manager, options controller.Options) error {
78-
controller, err := ctrl.NewControllerManagedBy(mgr).
80+
clusterToMachineSets, err := util.ClusterToObjectsMapper(mgr.GetClient(), &clusterv1.MachineSetList{}, mgr.GetScheme())
81+
if err != nil {
82+
return err
83+
}
84+
85+
c, err := ctrl.NewControllerManagedBy(mgr).
7986
For(&clusterv1.MachineSet{}).
8087
Owns(&clusterv1.Machine{}).
8188
Watches(
8289
&source.Kind{Type: &clusterv1.Machine{}},
8390
&handler.EnqueueRequestsFromMapFunc{ToRequests: handler.ToRequestsFunc(r.MachineToMachineSets)},
8491
).
8592
WithOptions(options).
93+
WithEventFilter(predicates.ResourceNotPaused(r.Log)).
8694
Build(r)
87-
8895
if err != nil {
8996
return errors.Wrap(err, "failed setting up with a controller manager")
9097
}
9198

92-
// Add a watch on clusterv1.Cluster object for paused notifications.
93-
clusterToMachineSets, err := util.ClusterToObjectsMapper(mgr.GetClient(), &clusterv1.MachineSetList{}, mgr.GetScheme())
99+
err = c.Watch(
100+
&source.Kind{Type: &clusterv1.Cluster{}},
101+
&handler.EnqueueRequestsFromMapFunc{ToRequests: clusterToMachineSets},
102+
// TODO: should this wait for Cluster.Status.InfrastructureReady similar to Infra Machine resources?
103+
predicates.ClusterUnpaused(r.Log),
104+
)
94105
if err != nil {
95-
return err
96-
}
97-
if err := util.WatchOnClusterPaused(controller, clusterToMachineSets); err != nil {
98-
return err
106+
return errors.Wrap(err, "failed to add Watch for Clusters to controller manager")
99107
}
100108

101109
r.recorder = mgr.GetEventRecorderFor("machineset-controller")
@@ -124,7 +132,7 @@ func (r *MachineSetReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error)
124132
}
125133

126134
// Return early if the object or Cluster is paused.
127-
if util.IsPaused(cluster, machineSet) {
135+
if annotations.IsPaused(cluster, machineSet) {
128136
logger.Info("Reconciliation is paused for this object")
129137
return ctrl.Result{}, nil
130138
}

0 commit comments

Comments
 (0)