@@ -260,7 +260,8 @@ func (r *Reconciler) reconcile(ctx context.Context, cluster *clusterv1.Cluster,
260
260
return ctrl.Result {}, err
261
261
}
262
262
263
- // If the Machine belongs to a cluster, add an owner reference.
263
+ // If the machine is a stand-alone one, meaning not originated from a MachineDeployment, then set it as directly
264
+ // owned by the Cluster (if not already present).
264
265
if r .shouldAdopt (m ) {
265
266
m .OwnerReferences = util .EnsureOwnerRef (m .OwnerReferences , metav1.OwnerReference {
266
267
APIVersion : clusterv1 .GroupVersion .String (),
@@ -741,8 +742,20 @@ func (r *Reconciler) reconcileDeleteExternal(ctx context.Context, m *clusterv1.M
741
742
return obj , nil
742
743
}
743
744
745
+ // shouldAdopt returns true if the Machine should be adopted as a stand-alone Machine directly owned by the Cluster.
744
746
func (r * Reconciler ) shouldAdopt (m * clusterv1.Machine ) bool {
745
- return metav1 .GetControllerOf (m ) == nil && ! util .HasOwner (m .OwnerReferences , clusterv1 .GroupVersion .String (), []string {"Cluster" })
747
+ // if the machine is controlled by something (MS or KCP), or if it is a stand-alone machine directly owned by the Cluster, then no-op.
748
+ if metav1 .GetControllerOf (m ) != nil || util .HasOwner (m .OwnerReferences , clusterv1 .GroupVersion .String (), []string {"Cluster" }) {
749
+ return false
750
+ }
751
+
752
+ // If the Machine is originated by a MachineDeployment, this prevents it from being adopted as a stand-alone Machine.
753
+ // Note: this is required because after restore from a backup both the Machine controller and the
754
+ // MachineSet controller are racing to adopt Machines, see https://github.com/kubernetes-sigs/cluster-api/issues/7529
755
+ if _ , ok := m .Labels [clusterv1 .MachineDeploymentUniqueLabel ]; ok {
756
+ return false
757
+ }
758
+ return true
746
759
}
747
760
748
761
func (r * Reconciler ) watchClusterNodes (ctx context.Context , cluster * clusterv1.Cluster ) error {
0 commit comments