Skip to content

Commit ebbcf2d

Browse files
committed
machinesync: Create Cluster API InfraMachine if not exists while Cluster API Machine exists
1 parent a1a97d6 commit ebbcf2d

File tree

2 files changed

+63
-20
lines changed

2 files changed

+63
-20
lines changed

pkg/controllers/machinesync/machine_sync_controller.go

Lines changed: 56 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -180,14 +180,14 @@ func (r *MachineSyncReconciler) SetupWithManager(mgr ctrl.Manager) error {
180180

181181
// Reconcile reconciles CAPI and MAPI machines for their respective namespaces.
182182
//
183-
//nolint:funlen
183+
//nolint:funlen,cyclop
184184
func (r *MachineSyncReconciler) Reconcile(ctx context.Context, req reconcile.Request) (ctrl.Result, error) {
185185
logger := logf.FromContext(ctx, "namespace", req.Namespace, "name", req.Name)
186186

187187
logger.V(1).Info("Reconciling machine")
188188
defer logger.V(1).Info("Finished reconciling machine")
189189

190-
var mapiMachineNotFound, capiMachineNotFound bool
190+
var mapiMachineNotFound, capiMachineNotFound, capiInfraMachineExists bool
191191

192192
// Get the MAPI Machine.
193193
mapiMachine := &mapiv1beta1.Machine{}
@@ -243,12 +243,23 @@ func (r *MachineSyncReconciler) Reconcile(ctx context.Context, req reconcile.Req
243243
return ctrl.Result{}, nil
244244
}
245245

246+
// Check for existense of the Cluster API Infrastructure Machine or if it needs to get created from MAPI first.
247+
capiInfraMachineExists, err := r.doesCAPIInfraMachineExist(ctx, capiMachine, mapiMachine)
248+
if err != nil {
249+
return ctrl.Result{}, fmt.Errorf("failed to check for existence of Cluster API infrastructure machine: %w", err)
250+
}
251+
246252
authoritativeAPI := mapiMachine.Status.AuthoritativeAPI
247253

248254
switch {
249255
case authoritativeAPI == mapiv1beta1.MachineAuthorityMachineAPI:
250256
return r.reconcileMAPIMachinetoCAPIMachine(ctx, mapiMachine, capiMachine)
251257
case authoritativeAPI == mapiv1beta1.MachineAuthorityClusterAPI && !capiMachineNotFound:
258+
// Create Cluster API Infrastructure Machine from MAPI if it doesn't exist and the MAPI machine was created before the Cluster API machine.
259+
if !capiInfraMachineExists && (mapiMachine.CreationTimestamp.Equal(&capiMachine.CreationTimestamp) || mapiMachine.CreationTimestamp.Before(&capiMachine.CreationTimestamp)) {
260+
return r.reconcileMAPIMachinetoCAPIMachine(ctx, mapiMachine, capiMachine)
261+
}
262+
252263
return r.reconcileCAPIMachinetoMAPIMachine(ctx, capiMachine, mapiMachine)
253264
case authoritativeAPI == mapiv1beta1.MachineAuthorityClusterAPI && capiMachineNotFound:
254265
return r.reconcileMAPIMachinetoCAPIMachine(ctx, mapiMachine, capiMachine)
@@ -936,20 +947,14 @@ func (r *MachineSyncReconciler) fetchCAPIInfraResources(ctx context.Context, cap
936947
return nil, nil, nil
937948
}
938949

939-
var infraCluster, infraMachine client.Object
950+
var infraCluster client.Object
940951

941952
infraClusterKey := client.ObjectKey{
942953
Namespace: capiMachine.Namespace,
943954
Name: capiMachine.Spec.ClusterName,
944955
}
945956

946-
infraMachineRef := capiMachine.Spec.InfrastructureRef
947-
infraMachineKey := client.ObjectKey{
948-
Namespace: infraMachineRef.Namespace,
949-
Name: infraMachineRef.Name,
950-
}
951-
952-
infraMachine, infraCluster, err := controllers.InitInfraMachineAndInfraClusterFromProvider(r.Platform)
957+
_, infraCluster, err := controllers.InitInfraMachineAndInfraClusterFromProvider(r.Platform)
953958
if err != nil {
954959
return nil, nil, fmt.Errorf("unable to devise Cluster API infra resources: %w", err)
955960
}
@@ -958,13 +963,52 @@ func (r *MachineSyncReconciler) fetchCAPIInfraResources(ctx context.Context, cap
958963
return nil, nil, fmt.Errorf("failed to get Cluster API infrastructure cluster: %w", err)
959964
}
960965

966+
infraMachineRef := capiMachine.Spec.InfrastructureRef
967+
968+
infraMachine, err := r.fetchCAPIInfraMachine(ctx, infraMachineRef.Name, infraMachineRef.Namespace)
969+
if err != nil {
970+
return nil, nil, fmt.Errorf("failed to fetch Cluster API infrastructure machine: %w", err)
971+
}
972+
973+
return infraCluster, infraMachine, nil
974+
}
975+
976+
func (r *MachineSyncReconciler) fetchCAPIInfraMachine(ctx context.Context, name, namespace string) (client.Object, error) {
977+
infraMachine, _, err := controllers.InitInfraMachineAndInfraClusterFromProvider(r.Platform)
978+
if err != nil {
979+
return nil, fmt.Errorf("unable to devise Cluster API infra resources: %w", err)
980+
}
981+
982+
infraMachineKey := client.ObjectKey{
983+
Namespace: namespace,
984+
Name: name,
985+
}
986+
961987
if err := r.Get(ctx, infraMachineKey, infraMachine); err != nil && !apierrors.IsNotFound(err) {
962-
return nil, nil, fmt.Errorf("failed to get Cluster API infrastructure machine: %w", err)
988+
return nil, fmt.Errorf("failed to get: %w", err)
963989
} else if apierrors.IsNotFound(err) {
964990
infraMachine = nil
965991
}
966992

967-
return infraCluster, infraMachine, nil
993+
return infraMachine, nil
994+
}
995+
996+
// 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.
997+
func (r *MachineSyncReconciler) doesCAPIInfraMachineExist(ctx context.Context, capiMachine *clusterv1.Machine, mapiMachine *mapiv1beta1.Machine) (bool, error) {
998+
namespace := r.CAPINamespace
999+
name := mapiMachine.Name
1000+
1001+
if capiMachine != nil {
1002+
name = capiMachine.Spec.InfrastructureRef.Name
1003+
namespace = capiMachine.Spec.InfrastructureRef.Namespace
1004+
}
1005+
1006+
infraMachine, err := r.fetchCAPIInfraMachine(ctx, name, namespace)
1007+
if err != nil {
1008+
return false, fmt.Errorf("checking existence: %w", err)
1009+
}
1010+
1011+
return infraMachine != nil, nil
9681012
}
9691013

9701014
//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
@@ -779,20 +779,19 @@ var _ = Describe("With a running MachineSync Reconciler", func() {
779779
})
780780

781781
Context("and the InfraMachine does not exist", func() {
782-
It("should update the synchronized condition on the MAPI machine to False", func() {
783-
// TODO: Revert this to a useful error message.
784-
// We changed how fetchCAPIInfraResources behaves, so now we fail at a later point in the code.
785-
// This still fails, the behaviour is the same - it's just a less useful error for an end user.
786-
// We need to revisit fetchCAPIInfraResources.
782+
It("should create the Cluster API InfraMachine", func() {
787783
Eventually(k.Object(mapiMachine), timeout).Should(
788784
HaveField("Status.Conditions", ContainElement(
789785
SatisfyAll(
790786
HaveField("Type", Equal(consts.SynchronizedCondition)),
791-
HaveField("Status", Equal(corev1.ConditionFalse)),
792-
HaveField("Reason", Equal("FailedToConvertCAPIMachineToMAPI")),
793-
HaveField("Message", ContainSubstring("unexpected InfraMachine type, expected AWSMachine, got <nil>")),
787+
HaveField("Status", Equal(corev1.ConditionTrue)),
788+
HaveField("Reason", Equal("ResourceSynchronized")),
789+
HaveField("Message", ContainSubstring("Successfully synchronized CAPI Machine to MAPI")),
794790
))),
795791
)
792+
793+
capiInfraMachine := awsv1resourcebuilder.AWSMachine().WithName(mapiMachine.Name).WithNamespace(capiNamespace.Name).Build()
794+
Eventually(k.Get(capiInfraMachine), timeout).Should(Succeed())
796795
})
797796
})
798797
})

0 commit comments

Comments
 (0)