Skip to content

Commit bfd1787

Browse files
committed
refactor pause logic
1 parent c6337fb commit bfd1787

File tree

6 files changed

+159
-60
lines changed

6 files changed

+159
-60
lines changed

internal/controller/linodecluster_controller.go

Lines changed: 17 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,6 @@ import (
3232
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
3333
kutil "sigs.k8s.io/cluster-api/util"
3434
conditions "sigs.k8s.io/cluster-api/util/conditions/v1beta2"
35-
"sigs.k8s.io/cluster-api/util/patch"
36-
"sigs.k8s.io/cluster-api/util/paused"
3735
"sigs.k8s.io/cluster-api/util/predicates"
3836
ctrl "sigs.k8s.io/controller-runtime"
3937
"sigs.k8s.io/controller-runtime/pkg/builder"
@@ -115,57 +113,38 @@ func (r *LinodeClusterReconciler) Reconcile(ctx context.Context, req ctrl.Reques
115113
return ctrl.Result{}, fmt.Errorf("failed to create cluster scope: %w", err)
116114
}
117115

116+
if reconciler.IsPaused(cluster, linodeCluster) {
117+
logger.Info("linodeCluster or linked cluster is marked as paused, won't reconcile.")
118+
return ctrl.Result{}, nil
119+
}
120+
118121
return r.reconcile(ctx, clusterScope, logger)
119122
}
120123

121-
func (r *LinodeClusterReconciler) reconcilePause(ctx context.Context, clusterScope *scope.ClusterScope, logger logr.Logger) error {
122-
// Pausing a cluster pauses the VPC as well.
123-
// First thing to do is handle a paused Cluster. Paused clusters shouldn't be deleted.
124-
isPaused, conditionChanged, err := paused.EnsurePausedCondition(ctx, clusterScope.Client, clusterScope.Cluster, clusterScope.LinodeCluster)
125-
if err != nil {
126-
return err
127-
}
128-
if !(isPaused || conditionChanged) {
129-
return nil
130-
}
131-
124+
func (r *LinodeClusterReconciler) reconcileVPCLabel(ctx context.Context, clusterScope *scope.ClusterScope, logger logr.Logger) error {
132125
if clusterScope.LinodeCluster.Spec.VPCRef == nil {
133-
logger.Info("Paused reconciliation is skipped due to missing VPC ref")
126+
logger.Info("label reconciliation is skipped due to missing VPC ref")
134127
return nil
135128
}
136-
137129
linodeVPC := infrav1alpha2.LinodeVPC{
138130
ObjectMeta: metav1.ObjectMeta{
139131
Namespace: clusterScope.LinodeCluster.Spec.VPCRef.Namespace,
140132
Name: clusterScope.LinodeCluster.Spec.VPCRef.Name,
141133
},
142134
}
143-
144135
if err := clusterScope.Client.Get(ctx, client.ObjectKeyFromObject(&linodeVPC), &linodeVPC); err != nil {
145136
return err
146137
}
147-
148-
annotations := linodeVPC.ObjectMeta.GetAnnotations()
149-
if annotations == nil {
150-
annotations = map[string]string{}
138+
labels := linodeVPC.ObjectMeta.GetLabels()
139+
if labels == nil {
140+
labels = map[string]string{}
151141
}
152-
153-
if isPaused {
154-
logger.Info("CAPI cluster is paused, pausing VPC")
155-
// if we're paused, we should slap the pause annotation on our children
156-
// get the vpc & add the annotation
157-
annotations[clusterv1.PausedAnnotation] = pauseAnnotationValue
158-
} else {
159-
// we are not paused here, but were previously paused (we can get here only if conditionChanged is true.
160-
logger.Info("CAPI cluster is no longer paused, removing pause annotation from VPC")
161-
delete(annotations, clusterv1.PausedAnnotation)
162-
}
163-
linodeVPC.SetAnnotations(annotations)
164-
vpcPatchHelper, err := patch.NewHelper(&linodeVPC, clusterScope.Client)
165-
if err != nil {
166-
return fmt.Errorf("failed to build patch helper for linode VPC object: %w", err)
142+
if _, ok := labels[clusterv1.ClusterNameLabel]; ok {
143+
return nil
167144
}
168-
return vpcPatchHelper.Patch(ctx, &linodeVPC)
145+
labels[clusterv1.ClusterNameLabel] = clusterScope.Cluster.Name
146+
linodeVPC.ObjectMeta.SetLabels(labels)
147+
return clusterScope.Client.Update(ctx, &linodeVPC)
169148
}
170149

171150
//nolint:cyclop // can't make it simpler with existing API
@@ -201,7 +180,8 @@ func (r *LinodeClusterReconciler) reconcile(
201180
return res, err
202181
}
203182

204-
if err := r.reconcilePause(ctx, clusterScope, logger); err != nil {
183+
err := r.reconcileVPCLabel(ctx, clusterScope, logger)
184+
if err != nil {
205185
return res, err
206186
}
207187

internal/controller/linodefirewall_controller.go

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ func (r *LinodeFirewallReconciler) Reconcile(ctx context.Context, req ctrl.Reque
7878

7979
return ctrl.Result{}, client.IgnoreNotFound(err)
8080
}
81-
81+
var err error
8282
// Create the firewall scope.
8383
fwScope, err := scope.NewFirewallScope(
8484
ctx,
@@ -93,6 +93,20 @@ func (r *LinodeFirewallReconciler) Reconcile(ctx context.Context, req ctrl.Reque
9393
return ctrl.Result{}, fmt.Errorf("failed to create cluster scope: %w", err)
9494
}
9595

96+
var cluster *clusterv1.Cluster
97+
if _, ok := linodeFirewall.ObjectMeta.Labels[clusterv1.ClusterNameLabel]; ok {
98+
cluster, err = kutil.GetClusterFromMetadata(ctx, r.TracedClient(), linodeFirewall.ObjectMeta)
99+
if err != nil {
100+
log.Error(err, "failed to fetch cluster from metadata")
101+
return ctrl.Result{}, err
102+
}
103+
}
104+
105+
if reconciler.IsPaused(cluster, linodeFirewall) {
106+
log.Info("linodefirewall or linked cluster is paused, skipping reconcilation")
107+
return ctrl.Result{}, nil
108+
}
109+
96110
return r.reconcile(ctx, log, fwScope)
97111
}
98112

internal/controller/linodemachine_controller.go

Lines changed: 84 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ import (
3535
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
3636
kutil "sigs.k8s.io/cluster-api/util"
3737
conditions "sigs.k8s.io/cluster-api/util/conditions/v1beta2"
38-
"sigs.k8s.io/cluster-api/util/patch"
3938
"sigs.k8s.io/cluster-api/util/paused"
4039
"sigs.k8s.io/cluster-api/util/predicates"
4140
ctrl "sigs.k8s.io/controller-runtime"
@@ -191,26 +190,21 @@ func (r *LinodeMachineReconciler) pauseReferencedFirewall(ctx context.Context, l
191190
if annotations == nil {
192191
annotations = map[string]string{}
193192
}
194-
193+
if !conditionChanged {
194+
logger.Info("CAPI cluster condition has not changed, not updating firewall annotations.")
195+
return nil
196+
}
195197
if isPaused {
196-
logger.Info("CAPI cluster is paused, pausing Firewall too")
197198
// if we're paused, we should slap the pause annotation on our children
198199
// get the firewall & add the annotation
199-
annotations[clusterv1.PausedAnnotation] = pauseAnnotationValue
200-
} else if conditionChanged {
200+
annotations[clusterv1.PausedAnnotation] = "true"
201+
} else {
201202
// we are not paused here, but were previously paused
202203
logger.Info("CAPI cluster is no longer paused, removing pause annotation from Firewall")
203204
delete(annotations, clusterv1.PausedAnnotation)
204205
}
205206
linodeFW.SetAnnotations(annotations)
206-
fwPatchHelper, err := patch.NewHelper(&linodeFW, machineScope.Client)
207-
if err != nil {
208-
return fmt.Errorf("failed to create patch helper for firewalls: %w", err)
209-
}
210-
if err := fwPatchHelper.Patch(ctx, &linodeFW); err != nil {
211-
return fmt.Errorf("failed to patch firewall: %w", err)
212-
}
213-
return nil
207+
return machineScope.Client.Update(ctx, &linodeFW)
214208
}
215209

216210
func (r *LinodeMachineReconciler) pauseReferencedPlacementGroup(ctx context.Context, logger logr.Logger, machineScope *scope.MachineScope, isPaused, conditionChanged bool) error {
@@ -235,23 +229,83 @@ func (r *LinodeMachineReconciler) pauseReferencedPlacementGroup(ctx context.Cont
235229
}
236230

237231
if isPaused {
238-
logger.Info("CAPI cluster is paused, pausing Placement Group too")
239232
// if we're paused, we should slap the pause annotation on our children
240233
// get the firewall & add the annotation
241-
annotations[clusterv1.PausedAnnotation] = pauseAnnotationValue
234+
annotations[clusterv1.PausedAnnotation] = "true"
242235
} else if conditionChanged {
243236
// we are not paused here, but were previously paused
244237
logger.Info("CAPI cluster is no longer paused, removing pause annotation from Placement Group ")
245238
delete(annotations, clusterv1.PausedAnnotation)
246239
}
247240

248241
linodePG.SetAnnotations(annotations)
249-
fwPatchHelper, err := patch.NewHelper(&linodePG, machineScope.Client)
250-
if err != nil {
251-
return fmt.Errorf("failed to create patch helper for firewalls: %w", err)
242+
243+
return machineScope.Client.Update(ctx, &linodePG)
244+
}
245+
246+
// reconcileFirewallLabel adds the cluster-name label to placement group referenced in the machineScope if it does not already exist
247+
func (r *LinodeMachineReconciler) reconcileFirewallLabel(ctx context.Context, logger logr.Logger, machineScope *scope.MachineScope) error {
248+
if machineScope.LinodeMachine.Spec.FirewallRef == nil {
249+
logger.Info("Paused reconciliation is skipped due to missing Firewall ref")
250+
return nil
251+
}
252+
253+
linodeFW := infrav1alpha2.LinodeFirewall{
254+
ObjectMeta: metav1.ObjectMeta{
255+
Namespace: machineScope.LinodeMachine.Spec.FirewallRef.Namespace,
256+
Name: machineScope.LinodeMachine.Spec.FirewallRef.Name,
257+
},
252258
}
253-
if err := fwPatchHelper.Patch(ctx, &linodePG); err != nil {
254-
return fmt.Errorf("failed to patch firewall: %w", err)
259+
if err := machineScope.Client.Get(ctx, client.ObjectKeyFromObject(&linodeFW), &linodeFW); err != nil {
260+
return err
261+
}
262+
labels := linodeFW.ObjectMeta.GetLabels()
263+
if labels == nil {
264+
labels = map[string]string{}
265+
}
266+
if _, ok := labels[clusterv1.ClusterNameLabel]; !ok {
267+
labels[clusterv1.ClusterNameLabel] = machineScope.Machine.Labels[clusterv1.ClusterNameLabel]
268+
}
269+
linodeFW.SetLabels(labels)
270+
return machineScope.Client.Update(ctx, &linodeFW)
271+
}
272+
273+
// reconcilePGLabel adds the cluster-name label to placement group referenced in the machineScope if it does not already exist
274+
func (r *LinodeMachineReconciler) reconcilePGLabel(ctx context.Context, logger logr.Logger, machineScope *scope.MachineScope) error {
275+
276+
if machineScope.LinodeMachine.Spec.PlacementGroupRef == nil {
277+
logger.Info("Paused reconciliation is skipped due to missing placement group ref")
278+
return nil
279+
}
280+
linodePG := infrav1alpha2.LinodePlacementGroup{
281+
ObjectMeta: metav1.ObjectMeta{
282+
Namespace: machineScope.LinodeMachine.Spec.PlacementGroupRef.Namespace,
283+
Name: machineScope.LinodeMachine.Spec.PlacementGroupRef.Name,
284+
},
285+
}
286+
if err := machineScope.Client.Get(ctx, client.ObjectKeyFromObject(&linodePG), &linodePG); err != nil {
287+
return err
288+
}
289+
labels := linodePG.ObjectMeta.GetLabels()
290+
if labels == nil {
291+
labels = map[string]string{}
292+
}
293+
if _, ok := labels[clusterv1.ClusterNameLabel]; ok {
294+
return nil
295+
}
296+
labels[clusterv1.ClusterNameLabel] = machineScope.Machine.Labels[clusterv1.ClusterNameLabel]
297+
linodePG.ObjectMeta.SetLabels(labels)
298+
return machineScope.Client.Update(ctx, &linodePG)
299+
}
300+
301+
// reconcileLabel adds the cluster-name label to placement groups and firewalls that are difference in the machine spec
302+
// to ensure that they are represented as part of the cluster
303+
func (r *LinodeMachineReconciler) reconcileLabels(ctx context.Context, logger logr.Logger, machineScope *scope.MachineScope) error {
304+
if err := r.reconcilePGLabel(ctx, logger, machineScope); err != nil {
305+
return fmt.Errorf("failed to label referenced placement group: %w", err)
306+
}
307+
if err := r.reconcileFirewallLabel(ctx, logger, machineScope); err != nil {
308+
return fmt.Errorf("failed to label referenced firewall: %w", err)
255309
}
256310
return nil
257311
}
@@ -322,11 +376,21 @@ func (r *LinodeMachineReconciler) reconcile(ctx context.Context, logger logr.Log
322376
}
323377
}
324378

379+
// Add labels to referenced resources
380+
if err := r.reconcileLabels(ctx, logger, machineScope); err != nil {
381+
return ctrl.Result{}, err
382+
}
383+
325384
// Pause
326385
if err := r.reconcilePause(ctx, logger, machineScope); err != nil {
327386
return ctrl.Result{}, err
328387
}
329388

389+
// Stop if paused
390+
if reconciler.IsPaused(machineScope.Cluster, machineScope.Machine) {
391+
logger.Info("LinodeMachine or linked cluster is marked as paused, won't reconcile.")
392+
return ctrl.Result{}, nil
393+
}
330394
// Delete
331395
if !machineScope.LinodeMachine.ObjectMeta.DeletionTimestamp.IsZero() {
332396
failureReason = util.DeleteError

internal/controller/linodeplacementgroup_controller.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,15 @@ func (r *LinodePlacementGroupReconciler) Reconcile(ctx context.Context, req ctrl
8686

8787
return ctrl.Result{}, err
8888
}
89+
var cluster *clusterv1.Cluster
90+
var err error
91+
if _, ok := linodeplacementgroup.ObjectMeta.Labels[clusterv1.ClusterNameLabel]; ok {
92+
cluster, err = kutil.GetClusterFromMetadata(ctx, r.TracedClient(), linodeplacementgroup.ObjectMeta)
93+
if err != nil {
94+
log.Error(err, "failed to fetch cluster from metadata")
95+
return ctrl.Result{}, err
96+
}
97+
}
8998

9099
pgScope, err := scope.NewPlacementGroupScope(
91100
ctx,
@@ -101,6 +110,11 @@ func (r *LinodePlacementGroupReconciler) Reconcile(ctx context.Context, req ctrl
101110
return ctrl.Result{}, fmt.Errorf("failed to create Placement Group scope: %w", err)
102111
}
103112

113+
if reconciler.IsPaused(cluster, linodeplacementgroup) {
114+
log.Info("linodeplacementgroup or linked cluster is paused, skipping reconcilation")
115+
return ctrl.Result{}, nil
116+
}
117+
104118
return r.reconcile(ctx, log, pgScope)
105119
}
106120

internal/controller/linodevpc_controller.go

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,6 @@ func (r *LinodeVPCReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
8383
defer cancel()
8484

8585
log := ctrl.LoggerFrom(ctx).WithName("LinodeVPCReconciler").WithValues("name", req.NamespacedName.String())
86-
8786
linodeVPC := &infrav1alpha2.LinodeVPC{}
8887
if err := r.TracedClient().Get(ctx, req.NamespacedName, linodeVPC); err != nil {
8988
if err = client.IgnoreNotFound(err); err != nil {
@@ -92,7 +91,15 @@ func (r *LinodeVPCReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
9291

9392
return ctrl.Result{}, err
9493
}
95-
94+
var cluster *clusterv1.Cluster
95+
var err error
96+
if _, ok := linodeVPC.ObjectMeta.Labels[clusterv1.ClusterNameLabel]; ok {
97+
cluster, err = kutil.GetClusterFromMetadata(ctx, r.TracedClient(), linodeVPC.ObjectMeta)
98+
if err != nil {
99+
log.Error(err, "failed to fetch cluster from metadata")
100+
return ctrl.Result{}, err
101+
}
102+
}
96103
vpcScope, err := scope.NewVPCScope(
97104
ctx,
98105
r.LinodeClientConfig,
@@ -107,6 +114,11 @@ func (r *LinodeVPCReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
107114
return ctrl.Result{}, fmt.Errorf("failed to create VPC scope: %w", err)
108115
}
109116

117+
if reconciler.IsPaused(cluster, linodeVPC) {
118+
log.Info("linodeVPC or linked cluster is paused, skipping reconcilation")
119+
return ctrl.Result{}, nil
120+
}
121+
110122
return r.reconcile(ctx, log, vpcScope)
111123
}
112124

util/reconciler/annotations.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package reconciler
2+
3+
import (
4+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
5+
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
6+
"sigs.k8s.io/cluster-api/util/annotations"
7+
)
8+
9+
func IsPaused(cluster *clusterv1.Cluster, o metav1.Object) bool {
10+
if cluster != nil {
11+
return annotations.IsPaused(cluster, o)
12+
}
13+
return annotations.HasPaused(o)
14+
15+
}

0 commit comments

Comments
 (0)