@@ -19,8 +19,6 @@ package machinemigration
19
19
import (
20
20
"context"
21
21
"fmt"
22
- "strings"
23
- "time"
24
22
25
23
"github.com/go-logr/logr"
26
24
corev1 "k8s.io/api/core/v1"
@@ -106,96 +104,76 @@ func (r *MachineMigrationReconciler) Reconcile(ctx context.Context, req reconcil
106
104
return ctrl.Result {}, fmt .Errorf ("unable to apply authoritativeAPI to status with patch: %w" , err )
107
105
}
108
106
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
111
109
}
112
110
113
111
// Check if the Synchronized condition is set to True.
114
112
// If it is not, this indicates an unmigratable resource and therefore should take no action.
115
113
if cond , err := util .GetConditionStatus (mapiMachine , string (consts .SynchronizedCondition )); err != nil {
116
114
return ctrl.Result {}, fmt .Errorf ("unable to get synchronizedCondition for %s/%s: %w" , mapiMachine .Namespace , mapiMachine .Name , err )
117
115
} 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" )
121
117
122
- logger .Info ("Detected migration request for machine" )
118
+ return ctrl.Result {}, nil
119
+ }
123
120
124
121
// Make sure the authoritativeAPI resource status is set to migrating.
125
122
if mapiMachine .Status .AuthoritativeAPI != machinev1beta1 .MachineAuthorityMigrating {
123
+ logger .Info ("Detected migration request for machine" )
124
+
126
125
if err := r .applyStatusAuthoritativeAPIWithPatch (ctx , mapiMachine , machinev1beta1 .MachineAuthorityMigrating ); err != nil {
127
126
return ctrl.Result {}, fmt .Errorf ("unable to set authoritativeAPI %q to status: %w" , machinev1beta1 .MachineAuthorityMigrating , err )
128
127
}
129
- // Then wait for it to take effect.
130
- return ctrl.Result {RequeueAfter : time .Second }, nil
131
- }
132
128
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
+ }
134
134
135
- // Request pausing on the old authoritative resource.
135
+ // Request pausing on the authoritative resource.
136
136
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 )
138
138
} 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" )
142
140
143
- logger .Info ("Requested pausing for old authoritative machine" )
141
+ // Wait for the change to propagate.
142
+ return ctrl.Result {}, nil
143
+ }
144
144
145
- // Check that the old authoritative resource is paused.
145
+ // Check that the authoritative resource is paused.
146
146
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 )
148
148
} 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" )
152
151
153
- logger .Info ("Old authoritative machine is now paused" )
152
+ return ctrl.Result {}, nil
153
+ }
154
154
155
155
// Check if the synchronizedGeneration matches the old authoritativeAPI's resource current generation.
156
156
if isSynchronizedGenMatchingOldAuthority , err := r .isSynchronizedGenerationMatchingOldAuthoritativeAPIGeneration (ctx , mapiMachine ); err != nil {
157
157
return ctrl.Result {}, fmt .Errorf ("unable to check synchronizedGeneration matches old authority: %w" , err )
158
158
} else if ! isSynchronizedGenMatchingOldAuthority {
159
159
// 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" )
166
161
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
181
163
}
182
164
183
- logger .Info ("Switching authoritativeAPI for machine" )
184
-
185
165
// Set the actual AuthoritativeAPI to the desired one, reset the synchronized generation and condition.
186
166
if err := r .setNewAuthoritativeAPIAndResetSynchronized (ctx , mapiMachine , mapiMachine .Spec .AuthoritativeAPI ); err != nil {
187
167
return ctrl.Result {}, fmt .Errorf ("unable to apply authoritativeAPI to status with patch: %w" , err )
188
168
}
189
169
190
- logger .Info ("Successfully switched authoritativeAPI for machine" )
191
-
192
170
// Make sure the new authoritative resource has been requested to unpause.
193
171
if err := r .ensureUnpauseRequestedOnNewAuthoritativeResource (ctx , mapiMachine ); err != nil {
194
172
return ctrl.Result {}, fmt .Errorf ("unable to ensure the new AuthoritativeAPI has been un-paused: %w" , err )
195
173
}
196
174
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 " )
199
177
200
178
return ctrl.Result {}, nil
201
179
}
@@ -413,80 +391,3 @@ func (r *MachineMigrationReconciler) setNewAuthoritativeAPIAndResetSynchronized(
413
391
414
392
return nil
415
393
}
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
- }
0 commit comments