diff --git a/internal/controllers/machineset/machineset_controller.go b/internal/controllers/machineset/machineset_controller.go index 05c9d325a8ad..36e202bbff03 100644 --- a/internal/controllers/machineset/machineset_controller.go +++ b/internal/controllers/machineset/machineset_controller.go @@ -362,8 +362,24 @@ func (r *Reconciler) syncMachines(ctx context.Context, machineSet *clusterv1.Mac log := ctrl.LoggerFrom(ctx) for i := range machines { m := machines[i] - // If the machine is already being deleted, we don't need to update it. + // If the machine is already being deleted, we only need to sync + // the subset of fields that impact tearing down a machine if !m.DeletionTimestamp.IsZero() { + patchHelper, err := patch.NewHelper(m, r.Client) + if err != nil { + return errors.Wrapf(err, "failed to generate patch for Machine %q", klog.KObj(m)) + } + + // Set all other in-place mutable fields that impact the ability to tear down existing machines. + m.Spec.NodeDrainTimeout = machineSet.Spec.Template.Spec.NodeDrainTimeout + m.Spec.NodeDeletionTimeout = machineSet.Spec.Template.Spec.NodeDeletionTimeout + m.Spec.NodeVolumeDetachTimeout = machineSet.Spec.Template.Spec.NodeVolumeDetachTimeout + + err = patchHelper.Patch(ctx, m) + if err != nil { + log.Error(err, "Failed to update Machine", "Machine", klog.KObj(m)) + return errors.Wrapf(err, "failed to update Machine %q", klog.KObj(m)) + } continue } diff --git a/internal/controllers/machineset/machineset_controller_test.go b/internal/controllers/machineset/machineset_controller_test.go index ff323b18d52c..fd3dba437c3c 100644 --- a/internal/controllers/machineset/machineset_controller_test.go +++ b/internal/controllers/machineset/machineset_controller_test.go @@ -1008,6 +1008,7 @@ func TestMachineSetReconciler_syncMachines(t *testing.T) { replicas := int32(2) version := "v1.25.3" duration10s := &metav1.Duration{Duration: 10 * time.Second} + duration11s := &metav1.Duration{Duration: 11 * time.Second} ms := &clusterv1.MachineSet{ ObjectMeta: metav1.ObjectMeta{ UID: "abc-123-ms-uid", @@ -1347,6 +1348,28 @@ func TestMachineSetReconciler_syncMachines(t *testing.T) { g.Expect(updatedDeletingMachine.Spec.NodeDeletionTimeout).Should(Equal(deletingMachine.Spec.NodeDeletionTimeout)) g.Expect(updatedDeletingMachine.Spec.NodeVolumeDetachTimeout).Should(Equal(deletingMachine.Spec.NodeVolumeDetachTimeout)) }, 5*time.Second).Should(Succeed()) + + // Verify in-place mutable fields are updated on the deleting machine + ms.Spec.Template.Spec.NodeDrainTimeout = duration11s + ms.Spec.Template.Spec.NodeDeletionTimeout = duration11s + ms.Spec.Template.Spec.NodeVolumeDetachTimeout = duration11s + g.Expect(reconciler.syncMachines(ctx, ms, []*clusterv1.Machine{updatedInPlaceMutatingMachine, deletingMachine})).To(Succeed()) + updatedDeletingMachine := deletingMachine.DeepCopy() + + g.Expect(env.GetAPIReader().Get(ctx, client.ObjectKeyFromObject(updatedDeletingMachine), updatedDeletingMachine)).To(Succeed()) + // Verify Node timeout values + g.Expect(updatedDeletingMachine.Spec.NodeDrainTimeout).Should(And( + Not(BeNil()), + HaveValue(Equal(*ms.Spec.Template.Spec.NodeDrainTimeout)), + )) + g.Expect(updatedDeletingMachine.Spec.NodeDeletionTimeout).Should(And( + Not(BeNil()), + HaveValue(Equal(*ms.Spec.Template.Spec.NodeDeletionTimeout)), + )) + g.Expect(updatedDeletingMachine.Spec.NodeVolumeDetachTimeout).Should(And( + Not(BeNil()), + HaveValue(Equal(*ms.Spec.Template.Spec.NodeVolumeDetachTimeout)), + )) } func TestMachineSetReconciler_reconcileUnhealthyMachines(t *testing.T) {