Skip to content

Commit 10f80ea

Browse files
committed
machinesync: Create Cluster API InfraMachine if not exists while Cluster API Machine exists
1 parent 4106e8b commit 10f80ea

File tree

2 files changed

+62
-18
lines changed

2 files changed

+62
-18
lines changed

pkg/controllers/machinesync/machine_sync_controller.go

Lines changed: 55 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -191,14 +191,14 @@ func (r *MachineSyncReconciler) SetupWithManager(mgr ctrl.Manager) error {
191191

192192
// Reconcile reconciles CAPI and MAPI machines for their respective namespaces.
193193
//
194-
//nolint:funlen
194+
//nolint:funlen,cyclop
195195
func (r *MachineSyncReconciler) Reconcile(ctx context.Context, req reconcile.Request) (ctrl.Result, error) {
196196
logger := logf.FromContext(ctx, "namespace", req.Namespace, "name", req.Name)
197197

198198
logger.V(1).Info("Reconciling machine")
199199
defer logger.V(1).Info("Finished reconciling machine")
200200

201-
var mapiMachineNotFound, capiMachineNotFound bool
201+
var mapiMachineNotFound, capiMachineNotFound, capiInfraMachineExists bool
202202

203203
// Get the MAPI Machine.
204204
mapiMachine := &mapiv1beta1.Machine{}
@@ -254,12 +254,24 @@ func (r *MachineSyncReconciler) Reconcile(ctx context.Context, req reconcile.Req
254254
return ctrl.Result{}, nil
255255
}
256256

257+
// Check for existence of the Cluster API Infrastructure Machine or if it needs to get created from MAPI first.
258+
capiInfraMachineExists, err := r.doesCAPIInfraMachineExist(ctx, capiMachine, mapiMachine)
259+
if err != nil {
260+
return ctrl.Result{}, fmt.Errorf("failed to check for existence of Cluster API infrastructure machine: %w", err)
261+
}
262+
257263
authoritativeAPI := mapiMachine.Status.AuthoritativeAPI
258264

259265
switch {
260266
case authoritativeAPI == mapiv1beta1.MachineAuthorityMachineAPI:
261267
return r.reconcileMAPIMachinetoCAPIMachine(ctx, mapiMachine, capiMachine)
262268
case authoritativeAPI == mapiv1beta1.MachineAuthorityClusterAPI && !capiMachineNotFound:
269+
// Create Cluster API Infrastructure Machine from MAPI if it doesn't exist
270+
// the CAPI machine is not marked for deletion and the MAPI machine was created before the Cluster API machine.
271+
if !capiInfraMachineExists && capiMachine.DeletionTimestamp.IsZero() && !mapiMachine.CreationTimestamp.After(capiMachine.CreationTimestamp.Time) {
272+
return r.reconcileMAPIMachinetoCAPIMachine(ctx, mapiMachine, capiMachine)
273+
}
274+
263275
return r.reconcileCAPIMachinetoMAPIMachine(ctx, capiMachine, mapiMachine)
264276
case authoritativeAPI == mapiv1beta1.MachineAuthorityClusterAPI && capiMachineNotFound:
265277
return r.reconcileMAPIMachinetoCAPIMachine(ctx, mapiMachine, capiMachine)
@@ -987,18 +999,14 @@ func (r *MachineSyncReconciler) fetchCAPIInfraResources(ctx context.Context, cap
987999
return nil, nil, nil
9881000
}
9891001

990-
var infraCluster, infraMachine client.Object
1002+
var infraCluster client.Object
9911003

9921004
infraClusterKey := client.ObjectKey{
9931005
Namespace: capiMachine.Namespace,
9941006
Name: capiMachine.Spec.ClusterName,
9951007
}
9961008

9971009
infraMachineRef := capiMachine.Spec.InfrastructureRef
998-
infraMachineKey := client.ObjectKey{
999-
Namespace: infraMachineRef.Namespace,
1000-
Name: infraMachineRef.Name,
1001-
}
10021010

10031011
// Validate that required references are not empty to avoid nil pointer issues later.
10041012
// These are terminal configuration errors that require user intervention.
@@ -1012,7 +1020,7 @@ func (r *MachineSyncReconciler) fetchCAPIInfraResources(ctx context.Context, cap
10121020
capiMachine.Namespace, capiMachine.Name, errInvalidInfraMachineReference)
10131021
}
10141022

1015-
infraMachine, infraCluster, err := controllers.InitInfraMachineAndInfraClusterFromProvider(r.Platform)
1023+
_, infraCluster, err := controllers.InitInfraMachineAndInfraClusterFromProvider(r.Platform)
10161024
if err != nil {
10171025
return nil, nil, fmt.Errorf("unable to devise Cluster API infra resources: %w", err)
10181026
}
@@ -1021,13 +1029,50 @@ func (r *MachineSyncReconciler) fetchCAPIInfraResources(ctx context.Context, cap
10211029
return nil, nil, fmt.Errorf("failed to get Cluster API infrastructure cluster: %w", err)
10221030
}
10231031

1032+
infraMachine, err := r.fetchCAPIInfraMachine(ctx, infraMachineRef.Name, infraMachineRef.Namespace)
1033+
if err != nil {
1034+
return nil, nil, fmt.Errorf("failed to fetch Cluster API infrastructure machine: %w", err)
1035+
}
1036+
1037+
return infraCluster, infraMachine, nil
1038+
}
1039+
1040+
func (r *MachineSyncReconciler) fetchCAPIInfraMachine(ctx context.Context, name, namespace string) (client.Object, error) {
1041+
infraMachine, _, err := controllers.InitInfraMachineAndInfraClusterFromProvider(r.Platform)
1042+
if err != nil {
1043+
return nil, fmt.Errorf("unable to devise Cluster API infra resources: %w", err)
1044+
}
1045+
1046+
infraMachineKey := client.ObjectKey{
1047+
Namespace: namespace,
1048+
Name: name,
1049+
}
1050+
10241051
if err := r.Get(ctx, infraMachineKey, infraMachine); err != nil && !apierrors.IsNotFound(err) {
1025-
return nil, nil, fmt.Errorf("failed to get Cluster API infrastructure machine: %w", err)
1052+
return nil, fmt.Errorf("failed to get: %w", err)
10261053
} else if apierrors.IsNotFound(err) {
10271054
infraMachine = nil
10281055
}
10291056

1030-
return infraCluster, infraMachine, nil
1057+
return infraMachine, nil
1058+
}
1059+
1060+
// doesCAPIInfraMachineExist checks if the Cluster API Infrastructure Machine exists. It uses the infrastructureRef of the Cluster API Machine with fallback to the name of the MAPI Machine.
1061+
func (r *MachineSyncReconciler) doesCAPIInfraMachineExist(ctx context.Context, capiMachine *clusterv1.Machine, mapiMachine *mapiv1beta1.Machine) (bool, error) {
1062+
namespace := r.CAPINamespace
1063+
name := mapiMachine.Name
1064+
1065+
if capiMachine != nil {
1066+
name = capiMachine.Spec.InfrastructureRef.Name
1067+
namespace = capiMachine.Spec.InfrastructureRef.Namespace
1068+
}
1069+
1070+
infraMachine, err := r.fetchCAPIInfraMachine(ctx, name, namespace)
1071+
if err != nil {
1072+
return false, fmt.Errorf("checking existence: %w", err)
1073+
}
1074+
1075+
return infraMachine != nil, nil
10311076
}
10321077

10331078
//nolint:funlen,gocognit,cyclop

pkg/controllers/machinesync/machine_sync_controller_test.go

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -949,20 +949,19 @@ var _ = Describe("With a running MachineSync Reconciler", func() {
949949
})
950950

951951
Context("and the InfraMachine does not exist", func() {
952-
It("should update the synchronized condition on the MAPI machine to False", func() {
953-
// TODO: Revert this to a useful error message.
954-
// We changed how fetchCAPIInfraResources behaves, so now we fail at a later point in the code.
955-
// This still fails, the behaviour is the same - it's just a less useful error for an end user.
956-
// We need to revisit fetchCAPIInfraResources.
952+
It("should create the Cluster API InfraMachine", func() {
957953
Eventually(k.Object(mapiMachine), timeout).Should(
958954
HaveField("Status.Conditions", ContainElement(
959955
SatisfyAll(
960956
HaveField("Type", Equal(consts.SynchronizedCondition)),
961-
HaveField("Status", Equal(corev1.ConditionFalse)),
962-
HaveField("Reason", Equal("FailedToConvertCAPIMachineToMAPI")),
963-
HaveField("Message", ContainSubstring("unexpected InfraMachine type, expected AWSMachine, got <nil>")),
957+
HaveField("Status", Equal(corev1.ConditionTrue)),
958+
HaveField("Reason", Equal("ResourceSynchronized")),
959+
HaveField("Message", ContainSubstring("Successfully synchronized CAPI Machine to MAPI")),
964960
))),
965961
)
962+
963+
capiInfraMachine := awsv1resourcebuilder.AWSMachine().WithName(mapiMachine.Name).WithNamespace(capiNamespace.Name).Build()
964+
Eventually(k.Get(capiInfraMachine), timeout).Should(Succeed())
966965
})
967966
})
968967
})

0 commit comments

Comments
 (0)