diff --git a/pkg/controllers/machinesetsync/machineset_sync_controller.go b/pkg/controllers/machinesetsync/machineset_sync_controller.go index 97bc6185e..d7f8c9641 100644 --- a/pkg/controllers/machinesetsync/machineset_sync_controller.go +++ b/pkg/controllers/machinesetsync/machineset_sync_controller.go @@ -172,7 +172,20 @@ func (r *MachineSetSyncReconciler) Reconcile(ctx context.Context, req reconcile. } if mapiMachineSet == nil { + // The MAPI MachineSet has already been deleted. + // If the CAPI MachineSet is deleting and still has our sync finalizer, + // reconcile its deletion so the finalizer can be removed. + if shouldRequeue, err := r.reconcileCAPItoMAPIMachineSetDeletion(ctx, nil, capiMachineSet); err != nil { + return ctrl.Result{}, fmt.Errorf( + "failed to reconcile Cluster API machine set deletion: %w", + err, + ) + } else if shouldRequeue { + return ctrl.Result{}, nil + } + logger.Info("Only CAPI machine set found, nothing to do") + return ctrl.Result{}, nil } diff --git a/pkg/controllers/machinesetsync/machineset_sync_controller_test.go b/pkg/controllers/machinesetsync/machineset_sync_controller_test.go index 74eafc4be..e552ba7a8 100644 --- a/pkg/controllers/machinesetsync/machineset_sync_controller_test.go +++ b/pkg/controllers/machinesetsync/machineset_sync_controller_test.go @@ -1168,6 +1168,31 @@ var _ = Describe("With a running MachineSetSync controller", func() { ContainElement(HaveField("ObjectMeta.Name", Equal(capiMachineSet.GetName()))), )) }) + + // Regression test for OCPBUGS-98492: ensure the sync finalizer is removed + // when the MAPI MachineSet is already absent. + Context("when the CAPI machine set has the sync finalizer and is being deleted", func() { + BeforeEach(func() { + By("Adding the sync finalizer to the CAPI machine set") + Eventually(k.Update(capiMachineSet, func() { + capiMachineSet.SetFinalizers([]string{machinesync.SyncFinalizer}) + })).Should(Succeed()) + + By("Waiting for the manager's informer cache to observe the finalizer") + eventuallyManagerInformerCache(capiMachineSet).Should( + HaveField("ObjectMeta.Finalizers", ContainElement(machinesync.SyncFinalizer)), + ) + + By("Deleting the CAPI machine set") + Eventually(kDelete(ctx, capiMachineSet)).Should(Succeed()) + }) + + It("should remove the sync finalizer and allow the CAPI machine set to be deleted", func() { + Eventually(k.Get(capiMachineSet), timeout).Should( + WithTransform(apierrors.IsNotFound, BeTrue()), + ) + }) + }) }) Context("when the CAPI infra machine template resource does not exist", func() {