@@ -31,9 +31,12 @@ import (
3131 "k8s.io/apimachinery/pkg/runtime/schema"
3232 "k8s.io/utils/ptr"
3333 ctrl "sigs.k8s.io/controller-runtime"
34+ "sigs.k8s.io/controller-runtime/pkg/builder"
3435 "sigs.k8s.io/controller-runtime/pkg/client"
3536 "sigs.k8s.io/controller-runtime/pkg/controller"
37+ "sigs.k8s.io/controller-runtime/pkg/event"
3638 "sigs.k8s.io/controller-runtime/pkg/handler"
39+ "sigs.k8s.io/controller-runtime/pkg/predicate"
3740
3841 infrav1 "sigs.k8s.io/cluster-api-provider-aws/v2/api/v1beta2"
3942 ekscontrolplanev1 "sigs.k8s.io/cluster-api-provider-aws/v2/controlplane/eks/api/v1beta2"
@@ -75,12 +78,38 @@ func (r *AWSMachineTemplateReconciler) SetupWithManager(ctx context.Context, mgr
7578 Watches (
7679 & clusterv1.MachineDeployment {},
7780 handler .EnqueueRequestsFromMapFunc (r .machineDeploymentToAWSMachineTemplate ),
81+ // Only emit events for creation to reconcile in case the MachineDeployment got created after the AWSMachineTemplate was reconciled.
82+ builder .WithPredicates (predicate.Funcs {
83+ CreateFunc : func (e event.CreateEvent ) bool { return true },
84+ UpdateFunc : func (e event.UpdateEvent ) bool { return false },
85+ DeleteFunc : func (e event.DeleteEvent ) bool { return false },
86+ GenericFunc : func (e event.GenericEvent ) bool { return true },
87+ }),
88+ ).
89+ Watches (
90+ & clusterv1.MachineSet {},
91+ handler .EnqueueRequestsFromMapFunc (r .machineSetToAWSMachineTemplate ),
92+ // Only emit events for creation to reconcile in case the MachineDeployment got created after the AWSMachineTemplate was reconciled.
93+ builder .WithPredicates (predicate.Funcs {
94+ CreateFunc : func (e event.CreateEvent ) bool { return true },
95+ UpdateFunc : func (e event.UpdateEvent ) bool { return false },
96+ DeleteFunc : func (e event.DeleteEvent ) bool { return false },
97+ GenericFunc : func (e event.GenericEvent ) bool { return true },
98+ }),
7899 )
79100
80- // Optionally watch KubeadmControlPlane if the CRD exists
101+ // Watch KubeadmControlPlane if they exist.
81102 if _ , err := mgr .GetRESTMapper ().RESTMapping (schema.GroupKind {Group : controlplanev1 .GroupVersion .Group , Kind : "KubeadmControlPlane" }, controlplanev1 .GroupVersion .Version ); err == nil {
82103 b = b .Watches (& controlplanev1.KubeadmControlPlane {},
83- handler .EnqueueRequestsFromMapFunc (r .kubeadmControlPlaneToAWSMachineTemplate ))
104+ handler .EnqueueRequestsFromMapFunc (r .kubeadmControlPlaneToAWSMachineTemplate ),
105+ // Only emit events for creation to reconcile in case the KubeadmControlPlane got created after the AWSMachineTemplate was reconciled.
106+ builder .WithPredicates (predicate.Funcs {
107+ CreateFunc : func (e event.CreateEvent ) bool { return true },
108+ UpdateFunc : func (e event.UpdateEvent ) bool { return false },
109+ DeleteFunc : func (e event.DeleteEvent ) bool { return false },
110+ GenericFunc : func (e event.GenericEvent ) bool { return true },
111+ }),
112+ )
84113 }
85114
86115 _ , err := b .Build (r )
@@ -95,7 +124,7 @@ func (r *AWSMachineTemplateReconciler) SetupWithManager(ctx context.Context, mgr
95124// +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=awsmachinetemplates/status,verbs=get;update;patch
96125// +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=awsclusters,verbs=get;list;watch
97126// +kubebuilder:rbac:groups=cluster.x-k8s.io,resources=clusters,verbs=get;list;watch
98- // +kubebuilder:rbac:groups=cluster.x-k8s.io,resources=machinedeployments,verbs=get;list;watch
127+ // +kubebuilder:rbac:groups=cluster.x-k8s.io,resources=machinedeployments;machinesets ,verbs=get;list;watch
99128// +kubebuilder:rbac:groups="",resources=events,verbs=get;list;watch;create;update;patch
100129
101130// Reconcile populates capacity information for AWSMachineTemplate.
@@ -387,7 +416,22 @@ func (r *AWSMachineTemplateReconciler) getKubernetesVersion(ctx context.Context,
387416 return "" , errors .Wrap (err , "failed to get parent list options" )
388417 }
389418
390- // Try to find version from MachineDeployment first
419+ // Try to find version from MachineSet first
420+ machineSetList := & clusterv1.MachineSetList {}
421+ if err := r .List (ctx , machineSetList , listOpts ... ); err != nil {
422+ return "" , errors .Wrap (err , "failed to list MachineSets" )
423+ }
424+
425+ // Find MachineDeployments that reference this AWSMachineTemplate
426+ for _ , ms := range machineSetList .Items {
427+ if ms .Spec .Template .Spec .InfrastructureRef .Kind == awsMachineTemplateKind &&
428+ ms .Spec .Template .Spec .InfrastructureRef .Name == template .Name &&
429+ ms .Spec .Template .Spec .Version != "" {
430+ return ms .Spec .Template .Spec .Version , nil
431+ }
432+ }
433+
434+ // If not found, try MachineDeployment.
391435 machineDeploymentList := & clusterv1.MachineDeploymentList {}
392436 if err := r .List (ctx , machineDeploymentList , listOpts ... ); err != nil {
393437 return "" , errors .Wrap (err , "failed to list MachineDeployments" )
@@ -402,7 +446,7 @@ func (r *AWSMachineTemplateReconciler) getKubernetesVersion(ctx context.Context,
402446 }
403447 }
404448
405- // If not found in MachineDeployment , try KubeadmControlPlane
449+ // If not found, try KubeadmControlPlane
406450 kcpList := & controlplanev1.KubeadmControlPlaneList {}
407451 if err := r .List (ctx , kcpList , listOpts ... ); err != nil {
408452 return "" , errors .Wrap (err , "failed to list KubeadmControlPlanes" )
@@ -492,3 +536,28 @@ func (r *AWSMachineTemplateReconciler) machineDeploymentToAWSMachineTemplate(ctx
492536 },
493537 }
494538}
539+
540+ // machineSetToAWSMachineTemplate maps MachineSet to AWSMachineTemplate reconcile requests.
541+ // This enables the controller to reconcile AWSMachineTemplate when its owner MachineSet is created or updated,
542+ // ensuring that nodeInfo can be populated even if the cache hasn't synced yet.
543+ func (r * AWSMachineTemplateReconciler ) machineSetToAWSMachineTemplate (ctx context.Context , o client.Object ) []ctrl.Request {
544+ md , ok := o .(* clusterv1.MachineSet )
545+ if ! ok {
546+ return nil
547+ }
548+
549+ // Check if it references an AWSMachineTemplate
550+ if md .Spec .Template .Spec .InfrastructureRef .Kind != awsMachineTemplateKind {
551+ return nil
552+ }
553+
554+ // Return reconcile request for the referenced AWSMachineTemplate
555+ return []ctrl.Request {
556+ {
557+ NamespacedName : client.ObjectKey {
558+ Namespace : md .Namespace ,
559+ Name : md .Spec .Template .Spec .InfrastructureRef .Name ,
560+ },
561+ },
562+ }
563+ }
0 commit comments