Skip to content

Commit add7c0d

Browse files
committed
wip: addressing feedback
1 parent 5c932c5 commit add7c0d

File tree

4 files changed

+31
-130
lines changed

4 files changed

+31
-130
lines changed

pkg/controllers/machinemigration/machine_migration_controller.go

+28-127
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@ package machinemigration
1919
import (
2020
"context"
2121
"fmt"
22-
"strings"
23-
"time"
2422

2523
"github.com/go-logr/logr"
2624
corev1 "k8s.io/api/core/v1"
@@ -106,96 +104,76 @@ func (r *MachineMigrationReconciler) Reconcile(ctx context.Context, req reconcil
106104
return ctrl.Result{}, fmt.Errorf("unable to apply authoritativeAPI to status with patch: %w", err)
107105
}
108106

109-
// Check again later.
110-
return ctrl.Result{RequeueAfter: time.Second}, nil
107+
// Wait for the patching to take effect.
108+
return ctrl.Result{}, nil
111109
}
112110

113111
// Check if the Synchronized condition is set to True.
114112
// If it is not, this indicates an unmigratable resource and therefore should take no action.
115113
if cond, err := util.GetConditionStatus(mapiMachine, string(consts.SynchronizedCondition)); err != nil {
116114
return ctrl.Result{}, fmt.Errorf("unable to get synchronizedCondition for %s/%s: %w", mapiMachine.Namespace, mapiMachine.Name, err)
117115
} else if cond != corev1.ConditionTrue {
118-
logger.Info("New machine not yet in sync with the old authoritative one, will retry later")
119-
return ctrl.Result{RequeueAfter: time.Second}, nil
120-
}
116+
logger.Info("Machine not synchronized with latest authoritative generation, will retry later")
121117

122-
logger.Info("Detected migration request for machine")
118+
return ctrl.Result{}, nil
119+
}
123120

124121
// Make sure the authoritativeAPI resource status is set to migrating.
125122
if mapiMachine.Status.AuthoritativeAPI != machinev1beta1.MachineAuthorityMigrating {
123+
logger.Info("Detected migration request for machine")
124+
126125
if err := r.applyStatusAuthoritativeAPIWithPatch(ctx, mapiMachine, machinev1beta1.MachineAuthorityMigrating); err != nil {
127126
return ctrl.Result{}, fmt.Errorf("unable to set authoritativeAPI %q to status: %w", machinev1beta1.MachineAuthorityMigrating, err)
128127
}
129-
// Then wait for it to take effect.
130-
return ctrl.Result{RequeueAfter: time.Second}, nil
131-
}
132128

133-
logger.Info("Acknowledged migration request for machine")
129+
logger.Info("Acknowledged migration request for machine")
130+
131+
// Wait for the change to propagate.
132+
return ctrl.Result{}, nil
133+
}
134134

135-
// Request pausing on the old authoritative resource.
135+
// Request pausing on the authoritative resource.
136136
if updated, err := r.requestOldAuthoritativeResourcePaused(ctx, mapiMachine); err != nil {
137-
return ctrl.Result{}, fmt.Errorf("failed to request pause on old authoritative machine: %w", err)
137+
return ctrl.Result{}, fmt.Errorf("failed to request pause on authoritative machine: %w", err)
138138
} else if updated {
139-
// Wait for it to take effect.
140-
return ctrl.Result{RequeueAfter: time.Second}, nil
141-
}
139+
logger.Info("Requested pausing for authoritative machine")
142140

143-
logger.Info("Requested pausing for old authoritative machine")
141+
// Wait for the change to propagate.
142+
return ctrl.Result{}, nil
143+
}
144144

145-
// Check that the old authoritative resource is paused.
145+
// Check that the authoritative resource is paused.
146146
if paused, err := r.isOldAuthoritativeResourcePaused(ctx, mapiMachine); err != nil {
147-
return ctrl.Result{}, fmt.Errorf("failed to check paused on old authoritative machine: %w", err)
147+
return ctrl.Result{}, fmt.Errorf("failed to check paused on authoritative machine: %w", err)
148148
} else if !paused {
149-
// The old Authoritative API resource is not paused yet, requeue to check later.
150-
return ctrl.Result{RequeueAfter: time.Second}, nil
151-
}
149+
// The Authoritative API resource is not paused yet, requeue to check later.
150+
logger.Info("Authoritative machine is not paused yet, will retry later")
152151

153-
logger.Info("Old authoritative machine is now paused")
152+
return ctrl.Result{}, nil
153+
}
154154

155155
// Check if the synchronizedGeneration matches the old authoritativeAPI's resource current generation.
156156
if isSynchronizedGenMatchingOldAuthority, err := r.isSynchronizedGenerationMatchingOldAuthoritativeAPIGeneration(ctx, mapiMachine); err != nil {
157157
return ctrl.Result{}, fmt.Errorf("unable to check synchronizedGeneration matches old authority: %w", err)
158158
} else if !isSynchronizedGenMatchingOldAuthority {
159159
// The to-be Authoritative API resource is not fully synced up yet, requeue to check later.
160-
logger.Info("To-be authoritative and old machine are not synced yet, will retry later")
161-
162-
return ctrl.Result{RequeueAfter: time.Second}, nil
163-
}
164-
165-
logger.Info("New machine is now in sync with the old authoritative one")
160+
logger.Info("Authoritative machine and its copy are not synchronized yet, will retry later")
166161

167-
// Add finalizer to new authoritative API, this ensures no status changes on the same reconcile.
168-
if added, err := r.ensureFinalizerOnNewAuthoritativeResource(ctx, mapiMachine); err != nil {
169-
return ctrl.Result{}, fmt.Errorf("failed to ensure finalizer on resource: %w", err)
170-
} else if added {
171-
// Wait for it to take effect.
172-
return ctrl.Result{RequeueAfter: time.Second}, nil
173-
}
174-
175-
// Remove finalizer from the old authoritative API, this ensures no status changes on the same reconcile.
176-
if removed, err := r.ensureNoFinalizerOnOldAuthoritativeResource(ctx, mapiMachine); err != nil {
177-
return ctrl.Result{}, fmt.Errorf("failed to remove finalizer from old resource: %w", err)
178-
} else if removed {
179-
// Wait for it to take effect.
180-
return ctrl.Result{RequeueAfter: time.Second}, nil
162+
return ctrl.Result{}, nil
181163
}
182164

183-
logger.Info("Switching authoritativeAPI for machine")
184-
185165
// Set the actual AuthoritativeAPI to the desired one, reset the synchronized generation and condition.
186166
if err := r.setNewAuthoritativeAPIAndResetSynchronized(ctx, mapiMachine, mapiMachine.Spec.AuthoritativeAPI); err != nil {
187167
return ctrl.Result{}, fmt.Errorf("unable to apply authoritativeAPI to status with patch: %w", err)
188168
}
189169

190-
logger.Info("Successfully switched authoritativeAPI for machine")
191-
192170
// Make sure the new authoritative resource has been requested to unpause.
193171
if err := r.ensureUnpauseRequestedOnNewAuthoritativeResource(ctx, mapiMachine); err != nil {
194172
return ctrl.Result{}, fmt.Errorf("unable to ensure the new AuthoritativeAPI has been un-paused: %w", err)
195173
}
196174

197-
logger.Info("Successfully unpaused new authoritative machine")
198-
logger.Info("Migration completed for machine")
175+
logger.Info("Machine authority switch has now been completed and the resource unpaused")
176+
logger.Info("Machine migrated successfully")
199177

200178
return ctrl.Result{}, nil
201179
}
@@ -413,80 +391,3 @@ func (r *MachineMigrationReconciler) setNewAuthoritativeAPIAndResetSynchronized(
413391

414392
return nil
415393
}
416-
417-
// ensureFinalizerOnNewAuthoritativeResource adds a finalizer to the resource if required.
418-
// If the finalizer already exists, this function should be a no-op.
419-
// If the finalizer is added, the function will return true so that the reconciler can requeue the object.
420-
// Adding the finalizer in a separate reconcile ensures that spec updates are separate from status updates.
421-
func (r *MachineMigrationReconciler) ensureFinalizerOnNewAuthoritativeResource(ctx context.Context, m *machinev1beta1.Machine) (bool, error) {
422-
if m.Spec.AuthoritativeAPI != machinev1beta1.MachineAuthorityClusterAPI {
423-
return false, nil
424-
}
425-
426-
capiMachine := &capiv1beta1.Machine{}
427-
if err := r.Get(ctx, client.ObjectKey{Namespace: consts.DefaultManagedNamespace, Name: m.Name}, capiMachine); err != nil {
428-
return false, fmt.Errorf("failed to get Cluster API machine: %w", err)
429-
}
430-
431-
updated, err := util.EnsureFinalizer(ctx, r.Client, capiMachine, capiv1beta1.MachineFinalizer)
432-
if err != nil {
433-
return false, fmt.Errorf("failed to ensure finalizer on Cluster API machine: %w", err)
434-
}
435-
436-
infraMachineRef := capiMachine.Spec.InfrastructureRef
437-
438-
infraMachine, err := util.GetReferencedObject(ctx, r.Client, r.Scheme, infraMachineRef)
439-
if err != nil {
440-
return false, fmt.Errorf("failed to get Cluster API infra machine: %w", err)
441-
}
442-
443-
// All the CAPI providers I checked do use this format for their infra machine finalizer.
444-
infraMachineFinalizer := fmt.Sprintf("%s.infrastructure.cluster.x-k8s.io", strings.ToLower(infraMachineRef.Kind))
445-
446-
infraMachineUpdated, err := util.EnsureFinalizer(ctx, r.Client, infraMachine, infraMachineFinalizer)
447-
if err != nil {
448-
return false, fmt.Errorf("failed to ensure finalizer on Cluster API machine: %w", err)
449-
}
450-
451-
return updated || infraMachineUpdated, nil
452-
}
453-
454-
// ensureNoFinalizerOnOldAuthoritativeResource removes the finalizer from the resource if required.
455-
// If the finalizer doesn't exists, this function should be a no-op.
456-
// If the finalizer gets removed, the function will return true so that the reconciler can requeue the object.
457-
func (r *MachineMigrationReconciler) ensureNoFinalizerOnOldAuthoritativeResource(ctx context.Context, m *machinev1beta1.Machine) (bool, error) {
458-
if m.Spec.AuthoritativeAPI == machinev1beta1.MachineAuthorityClusterAPI {
459-
return false, nil
460-
}
461-
462-
capiMachine := &capiv1beta1.Machine{}
463-
if err := r.Get(ctx, client.ObjectKey{Namespace: consts.DefaultManagedNamespace, Name: m.Name}, capiMachine); err != nil {
464-
return false, fmt.Errorf("failed to get Cluster API machine: %w", err)
465-
}
466-
467-
// TODO: uncomment this, at the moment there is a bug in the cluster-api controllers that
468-
// set the finalizer before checking for the paused condition, as such the finalizer is always
469-
// repopulted even though the controller is paused.
470-
// ref: https://github.com/kubernetes-sigs/cluster-api/blob/c70dca0fc387b44457c69b71a719132a0d9bed58/internal/controllers/machine/machine_controller.go#L207-L210
471-
// updated, err := util.RemoveFinalizer(ctx, r.Client, capiMachine, capiv1beta1.MachineFinalizer)
472-
// if err != nil {
473-
// return false, fmt.Errorf("failed to remove finalizer from Cluster API machine: %w", err)
474-
// }
475-
updated := false
476-
477-
infraMachineRef := capiMachine.Spec.InfrastructureRef
478-
479-
infraMachine, err := util.GetReferencedObject(ctx, r.Client, r.Scheme, infraMachineRef)
480-
if err != nil {
481-
return false, fmt.Errorf("failed to get Cluster API infra machine: %w", err)
482-
}
483-
484-
infraMachineFinalizer := fmt.Sprintf("%s.infrastructure.cluster.x-k8s.io", strings.ToLower(infraMachineRef.Kind))
485-
486-
infraMachineUpdated, err := util.RemoveFinalizer(ctx, r.Client, infraMachine, infraMachineFinalizer)
487-
if err != nil {
488-
return false, fmt.Errorf("failed to remove finalizer from Cluster API infra machine: %w", err)
489-
}
490-
491-
return updated || infraMachineUpdated, nil
492-
}

pkg/controllers/machinemigration/suite_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ var testScheme *runtime.Scheme
5252
var testRESTMapper meta.RESTMapper
5353
var ctx = context.Background()
5454

55-
func TestAPIs(t *testing.T) {
55+
func TestMachineMigration(t *testing.T) {
5656
RegisterFailHandler(Fail)
5757

5858
RunSpecs(t, "Controller Suite")

pkg/controllers/machinesetmigration/suite_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ var testScheme *runtime.Scheme
5252
var testRESTMapper meta.RESTMapper
5353
var ctx = context.Background()
5454

55-
func TestAPIs(t *testing.T) {
55+
func TestMachineSetMigration(t *testing.T) {
5656
RegisterFailHandler(Fail)
5757

5858
RunSpecs(t, "Controller Suite")

pkg/util/annotations.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
Copyright 2024 Red Hat, Inc.
2+
Copyright 2025 Red Hat, Inc.
33
44
Licensed under the Apache License, Version 2.0 (the "License");
55
you may not use this file except in compliance with the License.

0 commit comments

Comments
 (0)