@@ -33,6 +33,7 @@ import (
3333 ctrl "sigs.k8s.io/controller-runtime"
3434 "sigs.k8s.io/controller-runtime/pkg/client"
3535 "sigs.k8s.io/controller-runtime/pkg/controller"
36+ "sigs.k8s.io/controller-runtime/pkg/handler"
3637
3738 infrav1 "sigs.k8s.io/cluster-api-provider-aws/v2/api/v1beta2"
3839 ekscontrolplanev1 "sigs.k8s.io/cluster-api-provider-aws/v2/controlplane/eks/api/v1beta2"
@@ -47,6 +48,11 @@ import (
4748 "sigs.k8s.io/cluster-api/util/predicates"
4849)
4950
51+ const (
52+ // awsMachineTemplateKind is the Kind name for AWSMachineTemplate resources.
53+ awsMachineTemplateKind = "AWSMachineTemplate"
54+ )
55+
5056// AWSMachineTemplateReconciler reconciles AWSMachineTemplate objects.
5157//
5258// This controller automatically populates capacity information for AWSMachineTemplate resources
@@ -62,11 +68,27 @@ type AWSMachineTemplateReconciler struct {
6268func (r * AWSMachineTemplateReconciler ) SetupWithManager (ctx context.Context , mgr ctrl.Manager , options controller.Options ) error {
6369 log := logger .FromContext (ctx )
6470
65- return ctrl .NewControllerManagedBy (mgr ).
71+ b := ctrl .NewControllerManagedBy (mgr ).
6672 For (& infrav1.AWSMachineTemplate {}).
6773 WithOptions (options ).
6874 WithEventFilter (predicates .ResourceNotPausedAndHasFilterLabel (mgr .GetScheme (), log .GetLogger (), r .WatchFilterValue )).
69- Complete (r )
75+ Watches (
76+ & clusterv1.MachineDeployment {},
77+ handler .EnqueueRequestsFromMapFunc (r .machineDeploymentToAWSMachineTemplate ),
78+ )
79+
80+ // Optionally watch KubeadmControlPlane if the CRD exists
81+ if _ , err := mgr .GetRESTMapper ().RESTMapping (schema.GroupKind {Group : controlplanev1 .GroupVersion .Group , Kind : "KubeadmControlPlane" }, controlplanev1 .GroupVersion .Version ); err == nil {
82+ b = b .Watches (& controlplanev1.KubeadmControlPlane {},
83+ handler .EnqueueRequestsFromMapFunc (r .kubeadmControlPlaneToAWSMachineTemplate ))
84+ }
85+
86+ _ , err := b .Build (r )
87+ if err != nil {
88+ return errors .Wrap (err , "failed setting up with a controller manager" )
89+ }
90+
91+ return nil
7092}
7193
7294// +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=awsmachinetemplates,verbs=get;list;watch
@@ -373,7 +395,7 @@ func (r *AWSMachineTemplateReconciler) getKubernetesVersion(ctx context.Context,
373395
374396 // Find MachineDeployments that reference this AWSMachineTemplate
375397 for _ , md := range machineDeploymentList .Items {
376- if md .Spec .Template .Spec .InfrastructureRef .Kind == "AWSMachineTemplate" &&
398+ if md .Spec .Template .Spec .InfrastructureRef .Kind == awsMachineTemplateKind &&
377399 md .Spec .Template .Spec .InfrastructureRef .Name == template .Name &&
378400 md .Spec .Template .Spec .Version != "" {
379401 return md .Spec .Template .Spec .Version , nil
@@ -388,7 +410,7 @@ func (r *AWSMachineTemplateReconciler) getKubernetesVersion(ctx context.Context,
388410
389411 // Find KubeadmControlPlanes that reference this AWSMachineTemplate
390412 for _ , kcp := range kcpList .Items {
391- if kcp .Spec .MachineTemplate .Spec .InfrastructureRef .Kind == "AWSMachineTemplate" &&
413+ if kcp .Spec .MachineTemplate .Spec .InfrastructureRef .Kind == awsMachineTemplateKind &&
392414 kcp .Spec .MachineTemplate .Spec .InfrastructureRef .Name == template .Name &&
393415 kcp .Spec .Version != "" {
394416 return kcp .Spec .Version , nil
@@ -420,3 +442,53 @@ func getParentListOptions(obj metav1.ObjectMeta) ([]client.ListOption, error) {
420442 }
421443 return listOpts , nil
422444}
445+
446+ // kubeadmControlPlaneToAWSMachineTemplate maps KubeadmControlPlane to AWSMachineTemplate reconcile requests.
447+ // This enables the controller to reconcile AWSMachineTemplate when its owner KubeadmControlPlane is created or updated,
448+ // ensuring that nodeInfo can be populated even if the cache hasn't synced yet.
449+ func (r * AWSMachineTemplateReconciler ) kubeadmControlPlaneToAWSMachineTemplate (ctx context.Context , o client.Object ) []ctrl.Request {
450+ kcp , ok := o .(* controlplanev1.KubeadmControlPlane )
451+ if ! ok {
452+ return nil
453+ }
454+
455+ // Check if it references an AWSMachineTemplate
456+ if kcp .Spec .MachineTemplate .Spec .InfrastructureRef .Kind != awsMachineTemplateKind {
457+ return nil
458+ }
459+
460+ // Return reconcile request for the referenced AWSMachineTemplate
461+ return []ctrl.Request {
462+ {
463+ NamespacedName : client.ObjectKey {
464+ Namespace : kcp .Namespace ,
465+ Name : kcp .Spec .MachineTemplate .Spec .InfrastructureRef .Name ,
466+ },
467+ },
468+ }
469+ }
470+
471+ // machineDeploymentToAWSMachineTemplate maps MachineDeployment to AWSMachineTemplate reconcile requests.
472+ // This enables the controller to reconcile AWSMachineTemplate when its owner MachineDeployment is created or updated,
473+ // ensuring that nodeInfo can be populated even if the cache hasn't synced yet.
474+ func (r * AWSMachineTemplateReconciler ) machineDeploymentToAWSMachineTemplate (ctx context.Context , o client.Object ) []ctrl.Request {
475+ md , ok := o .(* clusterv1.MachineDeployment )
476+ if ! ok {
477+ return nil
478+ }
479+
480+ // Check if it references an AWSMachineTemplate
481+ if md .Spec .Template .Spec .InfrastructureRef .Kind != awsMachineTemplateKind {
482+ return nil
483+ }
484+
485+ // Return reconcile request for the referenced AWSMachineTemplate
486+ return []ctrl.Request {
487+ {
488+ NamespacedName : client.ObjectKey {
489+ Namespace : md .Namespace ,
490+ Name : md .Spec .Template .Spec .InfrastructureRef .Name ,
491+ },
492+ },
493+ }
494+ }
0 commit comments