sigs.k8s.io/cluster-api-provider-aws@v1.5.5/controllers/awsmachine_controller.go (about)

     1  /*
     2  Copyright 2019 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  	http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package controllers
    18  
    19  import (
    20  	"context"
    21  	"encoding/json"
    22  	"fmt"
    23  
    24  	"github.com/aws/aws-sdk-go/aws"
    25  	ignTypes "github.com/flatcar-linux/ignition/config/v2_3/types"
    26  	"github.com/go-logr/logr"
    27  	"github.com/google/go-cmp/cmp"
    28  	"github.com/pkg/errors"
    29  	corev1 "k8s.io/api/core/v1"
    30  	apierrors "k8s.io/apimachinery/pkg/api/errors"
    31  	"k8s.io/client-go/tools/record"
    32  	"k8s.io/utils/pointer"
    33  	ctrl "sigs.k8s.io/controller-runtime"
    34  	"sigs.k8s.io/controller-runtime/pkg/client"
    35  	"sigs.k8s.io/controller-runtime/pkg/controller"
    36  	"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
    37  	"sigs.k8s.io/controller-runtime/pkg/event"
    38  	"sigs.k8s.io/controller-runtime/pkg/handler"
    39  	"sigs.k8s.io/controller-runtime/pkg/predicate"
    40  	"sigs.k8s.io/controller-runtime/pkg/source"
    41  
    42  	infrav1 "sigs.k8s.io/cluster-api-provider-aws/api/v1beta1"
    43  	ekscontrolplanev1 "sigs.k8s.io/cluster-api-provider-aws/controlplane/eks/api/v1beta1"
    44  	"sigs.k8s.io/cluster-api-provider-aws/feature"
    45  	"sigs.k8s.io/cluster-api-provider-aws/pkg/cloud"
    46  	"sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/scope"
    47  	"sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services"
    48  	"sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services/ec2"
    49  	"sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services/elb"
    50  	"sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services/instancestate"
    51  	"sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services/s3"
    52  	"sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services/secretsmanager"
    53  	"sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services/ssm"
    54  	"sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services/userdata"
    55  	clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
    56  	"sigs.k8s.io/cluster-api/controllers/noderefutil"
    57  	capierrors "sigs.k8s.io/cluster-api/errors"
    58  	"sigs.k8s.io/cluster-api/util"
    59  	"sigs.k8s.io/cluster-api/util/annotations"
    60  	"sigs.k8s.io/cluster-api/util/conditions"
    61  	"sigs.k8s.io/cluster-api/util/predicates"
    62  )
    63  
    64  // InstanceIDIndex defines the aws machine controller's instance ID index.
    65  const InstanceIDIndex = ".spec.instanceID"
    66  
    67  // AWSMachineReconciler reconciles a AwsMachine object.
    68  type AWSMachineReconciler struct {
    69  	client.Client
    70  	Log                          logr.Logger
    71  	Recorder                     record.EventRecorder
    72  	ec2ServiceFactory            func(scope.EC2Scope) services.EC2Interface
    73  	elbServiceFactory            func(scope.ELBScope) services.ELBInterface
    74  	secretsManagerServiceFactory func(cloud.ClusterScoper) services.SecretInterface
    75  	SSMServiceFactory            func(cloud.ClusterScoper) services.SecretInterface
    76  	objectStoreServiceFactory    func(cloud.ClusterScoper) services.ObjectStoreInterface
    77  	Endpoints                    []scope.ServiceEndpoint
    78  	WatchFilterValue             string
    79  }
    80  
    81  const (
    82  	// AWSManagedControlPlaneRefKind is the string value indicating that a cluster is AWS managed.
    83  	AWSManagedControlPlaneRefKind = "AWSManagedControlPlane"
    84  )
    85  
    86  func (r *AWSMachineReconciler) getEC2Service(scope scope.EC2Scope) services.EC2Interface {
    87  	if r.ec2ServiceFactory != nil {
    88  		return r.ec2ServiceFactory(scope)
    89  	}
    90  
    91  	return ec2.NewService(scope)
    92  }
    93  
    94  func (r *AWSMachineReconciler) getSecretsManagerService(scope cloud.ClusterScoper) services.SecretInterface {
    95  	if r.secretsManagerServiceFactory != nil {
    96  		return r.secretsManagerServiceFactory(scope)
    97  	}
    98  
    99  	return secretsmanager.NewService(scope)
   100  }
   101  
   102  func (r *AWSMachineReconciler) getSSMService(scope cloud.ClusterScoper) services.SecretInterface {
   103  	if r.SSMServiceFactory != nil {
   104  		return r.SSMServiceFactory(scope)
   105  	}
   106  	return ssm.NewService(scope)
   107  }
   108  
   109  func (r *AWSMachineReconciler) getSecretService(machineScope *scope.MachineScope, scope cloud.ClusterScoper) (services.SecretInterface, error) {
   110  	switch machineScope.SecureSecretsBackend() {
   111  	case infrav1.SecretBackendSSMParameterStore:
   112  		return r.getSSMService(scope), nil
   113  	case infrav1.SecretBackendSecretsManager:
   114  		return r.getSecretsManagerService(scope), nil
   115  	}
   116  	return nil, errors.New("invalid secret backend")
   117  }
   118  
   119  func (r *AWSMachineReconciler) getELBService(elbScope scope.ELBScope) services.ELBInterface {
   120  	if r.elbServiceFactory != nil {
   121  		return r.elbServiceFactory(elbScope)
   122  	}
   123  	return elb.NewService(elbScope)
   124  }
   125  
   126  func (r *AWSMachineReconciler) getObjectStoreService(scope scope.S3Scope) services.ObjectStoreInterface {
   127  	if r.objectStoreServiceFactory != nil {
   128  		return r.objectStoreServiceFactory(scope)
   129  	}
   130  
   131  	return s3.NewService(scope)
   132  }
   133  
   134  // +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=awsmachines,verbs=get;list;watch;create;update;patch;delete
   135  // +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=awsmachines/status,verbs=get;update;patch
   136  // +kubebuilder:rbac:groups=cluster.x-k8s.io,resources=machines;machines/status,verbs=get;list;watch
   137  // +kubebuilder:rbac:groups="",resources=secrets;,verbs=get;list;watch
   138  // +kubebuilder:rbac:groups="",resources=namespaces,verbs=get;list;watch
   139  // +kubebuilder:rbac:groups="",resources=events,verbs=get;list;watch;create;update;patch
   140  
   141  func (r *AWSMachineReconciler) Reconcile(ctx context.Context, req ctrl.Request) (_ ctrl.Result, reterr error) {
   142  	log := ctrl.LoggerFrom(ctx)
   143  
   144  	// Fetch the AWSMachine instance.
   145  	awsMachine := &infrav1.AWSMachine{}
   146  	err := r.Get(ctx, req.NamespacedName, awsMachine)
   147  	if err != nil {
   148  		if apierrors.IsNotFound(err) {
   149  			return ctrl.Result{}, nil
   150  		}
   151  		return ctrl.Result{}, err
   152  	}
   153  
   154  	// Fetch the Machine.
   155  	machine, err := util.GetOwnerMachine(ctx, r.Client, awsMachine.ObjectMeta)
   156  	if err != nil {
   157  		return ctrl.Result{}, err
   158  	}
   159  	if machine == nil {
   160  		log.Info("Machine Controller has not yet set OwnerRef")
   161  		return ctrl.Result{}, nil
   162  	}
   163  
   164  	log = log.WithValues("machine", machine.Name)
   165  
   166  	// Fetch the Cluster.
   167  	cluster, err := util.GetClusterFromMetadata(ctx, r.Client, machine.ObjectMeta)
   168  	if err != nil {
   169  		log.Info("Machine is missing cluster label or cluster does not exist")
   170  		return ctrl.Result{}, nil
   171  	}
   172  
   173  	if annotations.IsPaused(cluster, awsMachine) {
   174  		log.Info("AWSMachine or linked Cluster is marked as paused. Won't reconcile")
   175  		return ctrl.Result{}, nil
   176  	}
   177  
   178  	log = log.WithValues("cluster", cluster.Name)
   179  
   180  	infraCluster, err := r.getInfraCluster(ctx, log, cluster, awsMachine)
   181  	if err != nil {
   182  		return ctrl.Result{}, errors.New("error getting infra provider cluster or control plane object")
   183  	}
   184  	if infraCluster == nil {
   185  		log.Info("AWSCluster or AWSManagedControlPlane is not ready yet")
   186  		return ctrl.Result{}, nil
   187  	}
   188  
   189  	// Create the machine scope
   190  	machineScope, err := scope.NewMachineScope(scope.MachineScopeParams{
   191  		Client:       r.Client,
   192  		Cluster:      cluster,
   193  		Machine:      machine,
   194  		InfraCluster: infraCluster,
   195  		AWSMachine:   awsMachine,
   196  	})
   197  	if err != nil {
   198  		log.Error(err, "failed to create scope")
   199  		return ctrl.Result{}, err
   200  	}
   201  
   202  	// Always close the scope when exiting this function so we can persist any AWSMachine changes.
   203  	defer func() {
   204  		if err := machineScope.Close(); err != nil && reterr == nil {
   205  			reterr = err
   206  		}
   207  	}()
   208  
   209  	switch infraScope := infraCluster.(type) {
   210  	case *scope.ManagedControlPlaneScope:
   211  		if !awsMachine.ObjectMeta.DeletionTimestamp.IsZero() {
   212  			return r.reconcileDelete(machineScope, infraScope, infraScope, nil, nil)
   213  		}
   214  
   215  		return r.reconcileNormal(ctx, machineScope, infraScope, infraScope, nil, nil)
   216  	case *scope.ClusterScope:
   217  		if !awsMachine.ObjectMeta.DeletionTimestamp.IsZero() {
   218  			return r.reconcileDelete(machineScope, infraScope, infraScope, infraScope, infraScope)
   219  		}
   220  
   221  		return r.reconcileNormal(ctx, machineScope, infraScope, infraScope, infraScope, infraScope)
   222  	default:
   223  		return ctrl.Result{}, errors.New("infraCluster has unknown type")
   224  	}
   225  }
   226  
   227  func (r *AWSMachineReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
   228  	log := ctrl.LoggerFrom(ctx)
   229  	AWSClusterToAWSMachines := r.AWSClusterToAWSMachines(log)
   230  
   231  	controller, err := ctrl.NewControllerManagedBy(mgr).
   232  		WithOptions(options).
   233  		For(&infrav1.AWSMachine{}).
   234  		Watches(
   235  			&source.Kind{Type: &clusterv1.Machine{}},
   236  			handler.EnqueueRequestsFromMapFunc(util.MachineToInfrastructureMapFunc(infrav1.GroupVersion.WithKind("AWSMachine"))),
   237  		).
   238  		Watches(
   239  			&source.Kind{Type: &infrav1.AWSCluster{}},
   240  			handler.EnqueueRequestsFromMapFunc(AWSClusterToAWSMachines),
   241  		).
   242  		WithEventFilter(predicates.ResourceNotPausedAndHasFilterLabel(log, r.WatchFilterValue)).
   243  		WithEventFilter(
   244  			predicate.Funcs{
   245  				// Avoid reconciling if the event triggering the reconciliation is related to incremental status updates
   246  				// for AWSMachine resources only
   247  				UpdateFunc: func(e event.UpdateEvent) bool {
   248  					if e.ObjectOld.GetObjectKind().GroupVersionKind().Kind != "AWSMachine" {
   249  						return true
   250  					}
   251  
   252  					oldMachine := e.ObjectOld.(*infrav1.AWSMachine).DeepCopy()
   253  					newMachine := e.ObjectNew.(*infrav1.AWSMachine).DeepCopy()
   254  
   255  					oldMachine.Status = infrav1.AWSMachineStatus{}
   256  					newMachine.Status = infrav1.AWSMachineStatus{}
   257  
   258  					oldMachine.ObjectMeta.ResourceVersion = ""
   259  					newMachine.ObjectMeta.ResourceVersion = ""
   260  
   261  					return !cmp.Equal(oldMachine, newMachine)
   262  				},
   263  			},
   264  		).
   265  		Build(r)
   266  	if err != nil {
   267  		return err
   268  	}
   269  
   270  	// Add index to AWSMachine to find by providerID
   271  	if err := mgr.GetFieldIndexer().IndexField(ctx, &infrav1.AWSMachine{},
   272  		InstanceIDIndex,
   273  		r.indexAWSMachineByInstanceID,
   274  	); err != nil {
   275  		return errors.Wrap(err, "error setting index fields")
   276  	}
   277  
   278  	requeueAWSMachinesForUnpausedCluster := r.requeueAWSMachinesForUnpausedCluster(log)
   279  	return controller.Watch(
   280  		&source.Kind{Type: &clusterv1.Cluster{}},
   281  		handler.EnqueueRequestsFromMapFunc(requeueAWSMachinesForUnpausedCluster),
   282  		predicates.ClusterUnpausedAndInfrastructureReady(log),
   283  	)
   284  }
   285  
   286  func (r *AWSMachineReconciler) reconcileDelete(machineScope *scope.MachineScope, clusterScope cloud.ClusterScoper, ec2Scope scope.EC2Scope, elbScope scope.ELBScope, objectStoreScope scope.S3Scope) (ctrl.Result, error) {
   287  	machineScope.Info("Handling deleted AWSMachine")
   288  
   289  	ec2Service := r.getEC2Service(ec2Scope)
   290  
   291  	if err := r.deleteBootstrapData(machineScope, clusterScope, objectStoreScope); err != nil {
   292  		machineScope.Error(err, "unable to delete machine")
   293  		return ctrl.Result{}, err
   294  	}
   295  
   296  	instance, err := r.findInstance(machineScope, ec2Service)
   297  	if err != nil && err != ec2.ErrInstanceNotFoundByID {
   298  		machineScope.Error(err, "query to find instance failed")
   299  		return ctrl.Result{}, err
   300  	}
   301  
   302  	if instance == nil {
   303  		// The machine was never created or was deleted by some other entity
   304  		// One way to reach this state:
   305  		// 1. Scale deployment to 0
   306  		// 2. Rename EC2 machine, and delete ProviderID from spec of both Machine
   307  		// and AWSMachine
   308  		// 3. Issue a delete
   309  		// 4. Scale controller deployment to 1
   310  		machineScope.V(2).Info("Unable to locate EC2 instance by ID or tags")
   311  		r.Recorder.Eventf(machineScope.AWSMachine, corev1.EventTypeWarning, "NoInstanceFound", "Unable to find matching EC2 instance")
   312  		controllerutil.RemoveFinalizer(machineScope.AWSMachine, infrav1.MachineFinalizer)
   313  		return ctrl.Result{}, nil
   314  	}
   315  
   316  	machineScope.V(3).Info("EC2 instance found matching deleted AWSMachine", "instance-id", instance.ID)
   317  
   318  	if err := r.reconcileLBAttachment(machineScope, elbScope, instance); err != nil {
   319  		// We are tolerating AccessDenied error, so this won't block for users with older version of IAM;
   320  		// all the other errors are blocking.
   321  		if !elb.IsAccessDenied(err) && !elb.IsNotFound(err) {
   322  			conditions.MarkFalse(machineScope.AWSMachine, infrav1.ELBAttachedCondition, "DeletingFailed", clusterv1.ConditionSeverityWarning, err.Error())
   323  			return ctrl.Result{}, errors.Errorf("failed to reconcile LB attachment: %+v", err)
   324  		}
   325  	}
   326  
   327  	if machineScope.IsControlPlane() {
   328  		conditions.MarkFalse(machineScope.AWSMachine, infrav1.ELBAttachedCondition, clusterv1.DeletedReason, clusterv1.ConditionSeverityInfo, "")
   329  	}
   330  
   331  	if feature.Gates.Enabled(feature.EventBridgeInstanceState) {
   332  		instancestateSvc := instancestate.NewService(ec2Scope)
   333  		instancestateSvc.RemoveInstanceFromEventPattern(instance.ID)
   334  	}
   335  
   336  	// Check the instance state. If it's already shutting down or terminated,
   337  	// do nothing. Otherwise attempt to delete it.
   338  	// This decision is based on the ec2-instance-lifecycle graph at
   339  	// https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-lifecycle.html
   340  	switch instance.State {
   341  	case infrav1.InstanceStateShuttingDown, infrav1.InstanceStateTerminated:
   342  		machineScope.Info("EC2 instance is shutting down or already terminated", "instance-id", instance.ID)
   343  	default:
   344  		machineScope.Info("Terminating EC2 instance", "instance-id", instance.ID)
   345  
   346  		// Set the InstanceReadyCondition and patch the object before the blocking operation
   347  		conditions.MarkFalse(machineScope.AWSMachine, infrav1.InstanceReadyCondition, clusterv1.DeletingReason, clusterv1.ConditionSeverityInfo, "")
   348  		if err := machineScope.PatchObject(); err != nil {
   349  			machineScope.Error(err, "failed to patch object")
   350  			return ctrl.Result{}, err
   351  		}
   352  
   353  		if err := ec2Service.TerminateInstanceAndWait(instance.ID); err != nil {
   354  			machineScope.Error(err, "failed to terminate instance")
   355  			conditions.MarkFalse(machineScope.AWSMachine, infrav1.InstanceReadyCondition, "DeletingFailed", clusterv1.ConditionSeverityWarning, err.Error())
   356  			r.Recorder.Eventf(machineScope.AWSMachine, corev1.EventTypeWarning, "FailedTerminate", "Failed to terminate instance %q: %v", instance.ID, err)
   357  			return ctrl.Result{}, err
   358  		}
   359  		conditions.MarkFalse(machineScope.AWSMachine, infrav1.InstanceReadyCondition, clusterv1.DeletedReason, clusterv1.ConditionSeverityInfo, "")
   360  
   361  		// If the AWSMachine specifies NetworkStatus Interfaces, detach the cluster's core Security Groups from them as part of deletion.
   362  		if len(machineScope.AWSMachine.Spec.NetworkInterfaces) > 0 {
   363  			core, err := ec2Service.GetCoreSecurityGroups(machineScope)
   364  			if err != nil {
   365  				machineScope.Error(err, "failed to get core security groups to detach from instance's network interfaces")
   366  				return ctrl.Result{}, err
   367  			}
   368  
   369  			machineScope.V(3).Info(
   370  				"Detaching security groups from provided network interface",
   371  				"groups", core,
   372  				"instanceID", instance.ID,
   373  			)
   374  
   375  			conditions.MarkFalse(machineScope.AWSMachine, infrav1.SecurityGroupsReadyCondition, clusterv1.DeletingReason, clusterv1.ConditionSeverityInfo, "")
   376  			if err := machineScope.PatchObject(); err != nil {
   377  				return ctrl.Result{}, err
   378  			}
   379  
   380  			for _, id := range machineScope.AWSMachine.Spec.NetworkInterfaces {
   381  				if err := ec2Service.DetachSecurityGroupsFromNetworkInterface(core, id); err != nil {
   382  					machineScope.Error(err, "failed to detach security groups from instance's network interfaces")
   383  					conditions.MarkFalse(machineScope.AWSMachine, infrav1.SecurityGroupsReadyCondition, "DeletingFailed", clusterv1.ConditionSeverityWarning, err.Error())
   384  					return ctrl.Result{}, err
   385  				}
   386  			}
   387  			conditions.MarkFalse(machineScope.AWSMachine, infrav1.SecurityGroupsReadyCondition, clusterv1.DeletedReason, clusterv1.ConditionSeverityInfo, "")
   388  		}
   389  
   390  		machineScope.Info("EC2 instance successfully terminated", "instance-id", instance.ID)
   391  		r.Recorder.Eventf(machineScope.AWSMachine, corev1.EventTypeNormal, "SuccessfulTerminate", "Terminated instance %q", instance.ID)
   392  	}
   393  
   394  	// Instance is deleted so remove the finalizer.
   395  	controllerutil.RemoveFinalizer(machineScope.AWSMachine, infrav1.MachineFinalizer)
   396  
   397  	return ctrl.Result{}, nil
   398  }
   399  
   400  // findInstance queries the EC2 apis and retrieves the instance if it exists.
   401  // If providerID is empty, finds instance by tags and if it cannot be found, returns empty instance with nil error.
   402  // If providerID is set, either finds the instance by ID or returns error.
   403  func (r *AWSMachineReconciler) findInstance(scope *scope.MachineScope, ec2svc services.EC2Interface) (*infrav1.Instance, error) {
   404  	var instance *infrav1.Instance
   405  
   406  	// Parse the ProviderID.
   407  	pid, err := noderefutil.NewProviderID(scope.GetProviderID())
   408  	if err != nil {
   409  		if !errors.Is(err, noderefutil.ErrEmptyProviderID) {
   410  			return nil, errors.Wrapf(err, "failed to parse Spec.ProviderID")
   411  		}
   412  		// If the ProviderID is empty, try to query the instance using tags.
   413  		// If an instance cannot be found, GetRunningInstanceByTags returns empty instance with nil error.
   414  		instance, err = ec2svc.GetRunningInstanceByTags(scope)
   415  		if err != nil {
   416  			return nil, errors.Wrapf(err, "failed to query AWSMachine instance by tags")
   417  		}
   418  	} else {
   419  		// If the ProviderID is populated, describe the instance using the ID.
   420  		// InstanceIfExists() returns error (ErrInstanceNotFoundByID or ErrDescribeInstance) if the instance could not be found.
   421  		instance, err = ec2svc.InstanceIfExists(pointer.StringPtr(pid.ID()))
   422  		if err != nil {
   423  			return nil, err
   424  		}
   425  	}
   426  
   427  	// The only case where the instance is nil here is when the providerId is empty and instance could not be found by tags.
   428  	return instance, nil
   429  }
   430  
   431  func (r *AWSMachineReconciler) reconcileNormal(_ context.Context, machineScope *scope.MachineScope, clusterScope cloud.ClusterScoper, ec2Scope scope.EC2Scope, elbScope scope.ELBScope, objectStoreScope scope.S3Scope) (ctrl.Result, error) {
   432  	machineScope.Info("Reconciling AWSMachine")
   433  
   434  	// If the AWSMachine is in an error state, return early.
   435  	if machineScope.HasFailed() {
   436  		machineScope.Info("Error state detected, skipping reconciliation")
   437  
   438  		// If we are in a failed state, delete the secret regardless of instance state.
   439  		if err := r.deleteBootstrapData(machineScope, clusterScope, objectStoreScope); err != nil {
   440  			machineScope.Error(err, "unable to reconcile machine")
   441  			return ctrl.Result{}, err
   442  		}
   443  
   444  		return ctrl.Result{}, nil
   445  	}
   446  
   447  	if !machineScope.Cluster.Status.InfrastructureReady {
   448  		machineScope.Info("Cluster infrastructure is not ready yet")
   449  		conditions.MarkFalse(machineScope.AWSMachine, infrav1.InstanceReadyCondition, infrav1.WaitingForClusterInfrastructureReason, clusterv1.ConditionSeverityInfo, "")
   450  		return ctrl.Result{}, nil
   451  	}
   452  
   453  	// Make sure bootstrap data is available and populated.
   454  	if machineScope.Machine.Spec.Bootstrap.DataSecretName == nil {
   455  		machineScope.Info("Bootstrap data secret reference is not yet available")
   456  		conditions.MarkFalse(machineScope.AWSMachine, infrav1.InstanceReadyCondition, infrav1.WaitingForBootstrapDataReason, clusterv1.ConditionSeverityInfo, "")
   457  		return ctrl.Result{}, nil
   458  	}
   459  
   460  	ec2svc := r.getEC2Service(ec2Scope)
   461  
   462  	// Find existing instance
   463  	instance, err := r.findInstance(machineScope, ec2svc)
   464  	if err != nil {
   465  		machineScope.Error(err, "unable to find instance")
   466  		conditions.MarkUnknown(machineScope.AWSMachine, infrav1.InstanceReadyCondition, infrav1.InstanceNotFoundReason, err.Error())
   467  		return ctrl.Result{}, err
   468  	}
   469  
   470  	// If the AWSMachine doesn't have our finalizer, add it.
   471  	controllerutil.AddFinalizer(machineScope.AWSMachine, infrav1.MachineFinalizer)
   472  	// Register the finalizer after first read operation from AWS to avoid orphaning AWS resources on delete
   473  	if err := machineScope.PatchObject(); err != nil {
   474  		machineScope.Error(err, "unable to patch object")
   475  		return ctrl.Result{}, err
   476  	}
   477  
   478  	// Create new instance since providerId is nil and instance could not be found by tags.
   479  	if instance == nil {
   480  		// Avoid a flickering condition between InstanceProvisionStarted and InstanceProvisionFailed if there's a persistent failure with createInstance
   481  		if conditions.GetReason(machineScope.AWSMachine, infrav1.InstanceReadyCondition) != infrav1.InstanceProvisionFailedReason {
   482  			conditions.MarkFalse(machineScope.AWSMachine, infrav1.InstanceReadyCondition, infrav1.InstanceProvisionStartedReason, clusterv1.ConditionSeverityInfo, "")
   483  			if patchErr := machineScope.PatchObject(); err != nil {
   484  				machineScope.Error(patchErr, "failed to patch conditions")
   485  				return ctrl.Result{}, patchErr
   486  			}
   487  		}
   488  
   489  		var objectStoreSvc services.ObjectStoreInterface
   490  
   491  		if objectStoreScope != nil {
   492  			objectStoreSvc = r.getObjectStoreService(objectStoreScope)
   493  		}
   494  
   495  		instance, err = r.createInstance(ec2svc, machineScope, clusterScope, objectStoreSvc)
   496  		if err != nil {
   497  			machineScope.Error(err, "unable to create instance")
   498  			conditions.MarkFalse(machineScope.AWSMachine, infrav1.InstanceReadyCondition, infrav1.InstanceProvisionFailedReason, clusterv1.ConditionSeverityError, err.Error())
   499  			return ctrl.Result{}, err
   500  		}
   501  	}
   502  	if feature.Gates.Enabled(feature.EventBridgeInstanceState) {
   503  		instancestateSvc := instancestate.NewService(ec2Scope)
   504  		if err := instancestateSvc.AddInstanceToEventPattern(instance.ID); err != nil {
   505  			return ctrl.Result{}, errors.Wrap(err, "failed to add instance to Event Bridge instance state rule")
   506  		}
   507  	}
   508  
   509  	// Make sure Spec.ProviderID and Spec.InstanceID are always set.
   510  	machineScope.SetProviderID(instance.ID, instance.AvailabilityZone)
   511  	machineScope.SetInstanceID(instance.ID)
   512  
   513  	// See https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-lifecycle.html
   514  
   515  	// Sets the AWSMachine status Interruptible, when the SpotMarketOptions is enabled for AWSMachine, Interruptible is set as true.
   516  	machineScope.SetInterruptible()
   517  
   518  	existingInstanceState := machineScope.GetInstanceState()
   519  	machineScope.SetInstanceState(instance.State)
   520  
   521  	// Proceed to reconcile the AWSMachine state.
   522  	if existingInstanceState == nil || *existingInstanceState != instance.State {
   523  		machineScope.Info("EC2 instance state changed", "state", instance.State, "instance-id", *machineScope.GetInstanceID())
   524  	}
   525  
   526  	switch instance.State {
   527  	case infrav1.InstanceStatePending:
   528  		machineScope.SetNotReady()
   529  		conditions.MarkFalse(machineScope.AWSMachine, infrav1.InstanceReadyCondition, infrav1.InstanceNotReadyReason, clusterv1.ConditionSeverityWarning, "")
   530  	case infrav1.InstanceStateStopping, infrav1.InstanceStateStopped:
   531  		machineScope.SetNotReady()
   532  		conditions.MarkFalse(machineScope.AWSMachine, infrav1.InstanceReadyCondition, infrav1.InstanceStoppedReason, clusterv1.ConditionSeverityError, "")
   533  	case infrav1.InstanceStateRunning:
   534  		machineScope.SetReady()
   535  		conditions.MarkTrue(machineScope.AWSMachine, infrav1.InstanceReadyCondition)
   536  	case infrav1.InstanceStateShuttingDown, infrav1.InstanceStateTerminated:
   537  		machineScope.SetNotReady()
   538  		machineScope.Info("Unexpected EC2 instance termination", "state", instance.State, "instance-id", *machineScope.GetInstanceID())
   539  		r.Recorder.Eventf(machineScope.AWSMachine, corev1.EventTypeWarning, "InstanceUnexpectedTermination", "Unexpected EC2 instance termination")
   540  		conditions.MarkFalse(machineScope.AWSMachine, infrav1.InstanceReadyCondition, infrav1.InstanceTerminatedReason, clusterv1.ConditionSeverityError, "")
   541  	default:
   542  		machineScope.SetNotReady()
   543  		machineScope.Info("EC2 instance state is undefined", "state", instance.State, "instance-id", *machineScope.GetInstanceID())
   544  		r.Recorder.Eventf(machineScope.AWSMachine, corev1.EventTypeWarning, "InstanceUnhandledState", "EC2 instance state is undefined")
   545  		machineScope.SetFailureReason(capierrors.UpdateMachineError)
   546  		machineScope.SetFailureMessage(errors.Errorf("EC2 instance state %q is undefined", instance.State))
   547  		conditions.MarkUnknown(machineScope.AWSMachine, infrav1.InstanceReadyCondition, "", "")
   548  	}
   549  
   550  	// reconcile the deletion of the bootstrap data secret now that we have updated instance state
   551  	if deleteSecretErr := r.deleteBootstrapData(machineScope, clusterScope, objectStoreScope); deleteSecretErr != nil {
   552  		r.Log.Error(deleteSecretErr, "unable to delete secrets")
   553  		return ctrl.Result{}, deleteSecretErr
   554  	}
   555  
   556  	if instance.State == infrav1.InstanceStateTerminated {
   557  		machineScope.SetFailureReason(capierrors.UpdateMachineError)
   558  		machineScope.SetFailureMessage(errors.Errorf("EC2 instance state %q is unexpected", instance.State))
   559  	}
   560  
   561  	// tasks that can take place during all known instance states
   562  	if machineScope.InstanceIsInKnownState() {
   563  		_, err = r.ensureTags(ec2svc, machineScope.AWSMachine, machineScope.GetInstanceID(), machineScope.AdditionalTags())
   564  		if err != nil {
   565  			machineScope.Error(err, "failed to ensure tags")
   566  			return ctrl.Result{}, err
   567  		}
   568  
   569  		if instance != nil {
   570  			r.ensureStorageTags(ec2svc, instance, machineScope.AWSMachine)
   571  		}
   572  
   573  		if err := r.reconcileLBAttachment(machineScope, elbScope, instance); err != nil {
   574  			machineScope.Error(err, "failed to reconcile LB attachment")
   575  			return ctrl.Result{}, err
   576  		}
   577  	}
   578  
   579  	// tasks that can only take place during operational instance states
   580  	if machineScope.InstanceIsOperational() {
   581  		machineScope.SetAddresses(instance.Addresses)
   582  
   583  		existingSecurityGroups, err := ec2svc.GetInstanceSecurityGroups(*machineScope.GetInstanceID())
   584  		if err != nil {
   585  			machineScope.Error(err, "unable to get instance security groups")
   586  			return ctrl.Result{}, err
   587  		}
   588  
   589  		// Ensure that the security groups are correct.
   590  		_, err = r.ensureSecurityGroups(ec2svc, machineScope, machineScope.AWSMachine.Spec.AdditionalSecurityGroups, existingSecurityGroups)
   591  		if err != nil {
   592  			conditions.MarkFalse(machineScope.AWSMachine, infrav1.SecurityGroupsReadyCondition, infrav1.SecurityGroupsFailedReason, clusterv1.ConditionSeverityError, err.Error())
   593  			machineScope.Error(err, "unable to ensure security groups")
   594  			return ctrl.Result{}, err
   595  		}
   596  		conditions.MarkTrue(machineScope.AWSMachine, infrav1.SecurityGroupsReadyCondition)
   597  	}
   598  
   599  	return ctrl.Result{}, nil
   600  }
   601  
   602  func (r *AWSMachineReconciler) deleteEncryptedBootstrapDataSecret(machineScope *scope.MachineScope, clusterScope cloud.ClusterScoper) error {
   603  	secretSvc, secretBackendErr := r.getSecretService(machineScope, clusterScope)
   604  	if secretBackendErr != nil {
   605  		machineScope.Error(secretBackendErr, "unable to get secret service backend")
   606  		return secretBackendErr
   607  	}
   608  
   609  	// do nothing if there isn't a secret
   610  	if machineScope.GetSecretPrefix() == "" {
   611  		return nil
   612  	}
   613  	if machineScope.GetSecretCount() == 0 {
   614  		return errors.New("secretPrefix present, but secretCount is not set")
   615  	}
   616  
   617  	// Do nothing if the AWSMachine is not in a failed state, and is operational from an EC2 perspective, but does not have a node reference
   618  	if !machineScope.HasFailed() && machineScope.InstanceIsOperational() && machineScope.Machine.Status.NodeRef == nil && !machineScope.AWSMachineIsDeleted() {
   619  		return nil
   620  	}
   621  	machineScope.Info("Deleting unneeded entry from AWS Secret", "secretPrefix", machineScope.GetSecretPrefix())
   622  	if err := secretSvc.Delete(machineScope); err != nil {
   623  		machineScope.Info("Unable to delete entries from AWS Secret containing encrypted userdata", "secretPrefix", machineScope.GetSecretPrefix())
   624  		r.Recorder.Eventf(machineScope.AWSMachine, corev1.EventTypeWarning, "FailedDeleteEncryptedBootstrapDataSecrets", "AWS Secret entries containing userdata not deleted")
   625  		return err
   626  	}
   627  	r.Recorder.Eventf(machineScope.AWSMachine, corev1.EventTypeNormal, "SuccessfulDeleteEncryptedBootstrapDataSecrets", "AWS Secret entries containing userdata deleted")
   628  
   629  	machineScope.DeleteSecretPrefix()
   630  	machineScope.SetSecretCount(0)
   631  
   632  	return nil
   633  }
   634  
   635  func (r *AWSMachineReconciler) createInstance(ec2svc services.EC2Interface, machineScope *scope.MachineScope, clusterScope cloud.ClusterScoper, objectStoreSvc services.ObjectStoreInterface) (*infrav1.Instance, error) {
   636  	machineScope.Info("Creating EC2 instance")
   637  
   638  	userData, userDataFormat, userDataErr := r.resolveUserData(machineScope, clusterScope, objectStoreSvc)
   639  	if userDataErr != nil {
   640  		return nil, errors.Wrapf(userDataErr, "failed to resolve userdata")
   641  	}
   642  
   643  	instance, err := ec2svc.CreateInstance(machineScope, userData, userDataFormat)
   644  	if err != nil {
   645  		return nil, errors.Wrapf(err, "failed to create AWSMachine instance")
   646  	}
   647  
   648  	return instance, nil
   649  }
   650  
   651  func (r *AWSMachineReconciler) resolveUserData(machineScope *scope.MachineScope, clusterScope cloud.ClusterScoper, objectStoreSvc services.ObjectStoreInterface) ([]byte, string, error) {
   652  	userData, userDataFormat, err := machineScope.GetRawBootstrapDataWithFormat()
   653  	if err != nil {
   654  		r.Recorder.Eventf(machineScope.AWSMachine, corev1.EventTypeWarning, "FailedGetBootstrapData", err.Error())
   655  		return nil, "", err
   656  	}
   657  
   658  	if machineScope.UseSecretsManager(userDataFormat) {
   659  		userData, err = r.cloudInitUserData(machineScope, clusterScope, userData)
   660  	}
   661  
   662  	if machineScope.UseIgnition(userDataFormat) {
   663  		userData, err = r.ignitionUserData(machineScope, objectStoreSvc, userData)
   664  	}
   665  
   666  	return userData, userDataFormat, err
   667  }
   668  
   669  func (r *AWSMachineReconciler) cloudInitUserData(machineScope *scope.MachineScope, clusterScope cloud.ClusterScoper, userData []byte) ([]byte, error) {
   670  	secretSvc, secretBackendErr := r.getSecretService(machineScope, clusterScope)
   671  	if secretBackendErr != nil {
   672  		machineScope.Error(secretBackendErr, "unable to reconcile machine")
   673  		return nil, secretBackendErr
   674  	}
   675  
   676  	compressedUserData, compressErr := userdata.GzipBytes(userData)
   677  	if compressErr != nil {
   678  		return nil, compressErr
   679  	}
   680  	prefix, chunks, serviceErr := secretSvc.Create(machineScope, compressedUserData)
   681  	// Only persist the AWS Secret Backend entries if there is at least one
   682  	if chunks > 0 {
   683  		machineScope.SetSecretPrefix(prefix)
   684  		machineScope.SetSecretCount(chunks)
   685  	}
   686  	// Register the Secret ARN immediately to avoid orphaning whatever AWS resources have been created
   687  	if err := machineScope.PatchObject(); err != nil {
   688  		return nil, err
   689  	}
   690  	if serviceErr != nil {
   691  		r.Recorder.Eventf(machineScope.AWSMachine, corev1.EventTypeWarning, "FailedCreateAWSSecrets", serviceErr.Error())
   692  		machineScope.Error(serviceErr, "Failed to create AWS Secret entry", "secretPrefix", prefix)
   693  		return nil, serviceErr
   694  	}
   695  	encryptedCloudInit, err := secretSvc.UserData(machineScope.GetSecretPrefix(), machineScope.GetSecretCount(), machineScope.InfraCluster.Region(), r.Endpoints)
   696  	if err != nil {
   697  		r.Recorder.Eventf(machineScope.AWSMachine, corev1.EventTypeWarning, "FailedGenerateAWSSecretsCloudInit", err.Error())
   698  		return nil, err
   699  	}
   700  	return encryptedCloudInit, nil
   701  }
   702  
   703  func (r *AWSMachineReconciler) ignitionUserData(scope *scope.MachineScope, objectStoreSvc services.ObjectStoreInterface, userData []byte) ([]byte, error) {
   704  	if objectStoreSvc == nil {
   705  		return nil, errors.New("object store service not available")
   706  	}
   707  
   708  	objectURL, err := objectStoreSvc.Create(scope, userData)
   709  	if err != nil {
   710  		return nil, errors.Wrap(err, "creating userdata object")
   711  	}
   712  
   713  	ignData := &ignTypes.Config{
   714  		Ignition: ignTypes.Ignition{
   715  			Version: "2.3.0",
   716  			Config: ignTypes.IgnitionConfig{
   717  				Append: []ignTypes.ConfigReference{
   718  					{
   719  						Source: objectURL,
   720  					},
   721  				},
   722  			},
   723  		},
   724  	}
   725  
   726  	ignitionUserData, err := json.Marshal(ignData)
   727  	if err != nil {
   728  		r.Recorder.Eventf(scope.AWSMachine, corev1.EventTypeWarning, "FailedGenerateIgnition", err.Error())
   729  		return nil, errors.Wrap(err, "serializing generated data")
   730  	}
   731  
   732  	return ignitionUserData, nil
   733  }
   734  
   735  func (r *AWSMachineReconciler) deleteBootstrapData(machineScope *scope.MachineScope, clusterScope cloud.ClusterScoper, objectStoreScope scope.S3Scope) error {
   736  	if !machineScope.AWSMachine.Spec.CloudInit.InsecureSkipSecretsManager {
   737  		if err := r.deleteEncryptedBootstrapDataSecret(machineScope, clusterScope); err != nil {
   738  			return err
   739  		}
   740  	}
   741  
   742  	if objectStoreScope != nil {
   743  		// Bootstrap data will be removed from S3 if it is already populated.
   744  		if err := r.deleteIgnitionBootstrapDataFromS3(machineScope, r.getObjectStoreService(objectStoreScope)); err != nil {
   745  			return err
   746  		}
   747  	}
   748  
   749  	return nil
   750  }
   751  
   752  func (r *AWSMachineReconciler) deleteIgnitionBootstrapDataFromS3(machineScope *scope.MachineScope, objectStoreSvc services.ObjectStoreInterface) error {
   753  	// Do nothing if the AWSMachine is not in a failed state, and is operational from an EC2 perspective, but does not have a node reference
   754  	if !machineScope.HasFailed() && machineScope.InstanceIsOperational() && machineScope.Machine.Status.NodeRef == nil && !machineScope.AWSMachineIsDeleted() {
   755  		return nil
   756  	}
   757  
   758  	// If bootstrap data has not been populated yet, we cannot determine it's format, so there is probably nothing to do.
   759  	if machineScope.Machine.Spec.Bootstrap.DataSecretName == nil {
   760  		return nil
   761  	}
   762  
   763  	machineScope.Info("Deleting unneeded entry from AWS S3", "secretPrefix", machineScope.GetSecretPrefix())
   764  
   765  	_, userDataFormat, err := machineScope.GetRawBootstrapDataWithFormat()
   766  	if err != nil {
   767  		r.Recorder.Eventf(machineScope.AWSMachine, corev1.EventTypeWarning, "FailedGetBootstrapData", err.Error())
   768  		return err
   769  	}
   770  
   771  	if !machineScope.UseIgnition(userDataFormat) {
   772  		return nil
   773  	}
   774  
   775  	if err := objectStoreSvc.Delete(machineScope); err != nil {
   776  		return errors.Wrap(err, "deleting bootstrap data object")
   777  	}
   778  
   779  	return nil
   780  }
   781  
   782  func (r *AWSMachineReconciler) reconcileLBAttachment(machineScope *scope.MachineScope, elbScope scope.ELBScope, i *infrav1.Instance) error {
   783  	if !machineScope.IsControlPlane() {
   784  		return nil
   785  	}
   786  
   787  	elbsvc := r.getELBService(elbScope)
   788  
   789  	// In order to prevent sending request to a "not-ready" control plane machines, it is required to remove the machine
   790  	// from the ELB as soon as the machine gets deleted or when the machine is in a not running state.
   791  	if !machineScope.AWSMachine.DeletionTimestamp.IsZero() || !machineScope.InstanceIsRunning() {
   792  		registered, err := elbsvc.IsInstanceRegisteredWithAPIServerELB(i)
   793  		if err != nil {
   794  			r.Recorder.Eventf(machineScope.AWSMachine, corev1.EventTypeWarning, "FailedDetachControlPlaneELB",
   795  				"Failed to deregister control plane instance %q from load balancer: failed to determine registration status: %v", i.ID, err)
   796  			return errors.Wrapf(err, "could not deregister control plane instance %q from load balancer - error determining registration status", i.ID)
   797  		}
   798  		if !registered {
   799  			// Already deregistered - nothing more to do
   800  			return nil
   801  		}
   802  
   803  		if err := elbsvc.DeregisterInstanceFromAPIServerELB(i); err != nil {
   804  			r.Recorder.Eventf(machineScope.AWSMachine, corev1.EventTypeWarning, "FailedDetachControlPlaneELB",
   805  				"Failed to deregister control plane instance %q from load balancer: %v", i.ID, err)
   806  			conditions.MarkFalse(machineScope.AWSMachine, infrav1.ELBAttachedCondition, infrav1.ELBDetachFailedReason, clusterv1.ConditionSeverityError, err.Error())
   807  			return errors.Wrapf(err, "could not deregister control plane instance %q from load balancer", i.ID)
   808  		}
   809  		r.Recorder.Eventf(machineScope.AWSMachine, corev1.EventTypeNormal, "SuccessfulDetachControlPlaneELB",
   810  			"Control plane instance %q is de-registered from load balancer", i.ID)
   811  		return nil
   812  	}
   813  
   814  	registered, err := elbsvc.IsInstanceRegisteredWithAPIServerELB(i)
   815  	if err != nil {
   816  		r.Recorder.Eventf(machineScope.AWSMachine, corev1.EventTypeWarning, "FailedAttachControlPlaneELB",
   817  			"Failed to register control plane instance %q with load balancer: failed to determine registration status: %v", i.ID, err)
   818  		return errors.Wrapf(err, "could not register control plane instance %q with load balancer - error determining registration status", i.ID)
   819  	}
   820  	if registered {
   821  		// Already registered - nothing more to do
   822  		return nil
   823  	}
   824  
   825  	if err := elbsvc.RegisterInstanceWithAPIServerELB(i); err != nil {
   826  		r.Recorder.Eventf(machineScope.AWSMachine, corev1.EventTypeWarning, "FailedAttachControlPlaneELB",
   827  			"Failed to register control plane instance %q with load balancer: %v", i.ID, err)
   828  		conditions.MarkFalse(machineScope.AWSMachine, infrav1.ELBAttachedCondition, infrav1.ELBAttachFailedReason, clusterv1.ConditionSeverityError, err.Error())
   829  		return errors.Wrapf(err, "could not register control plane instance %q with load balancer", i.ID)
   830  	}
   831  	r.Recorder.Eventf(machineScope.AWSMachine, corev1.EventTypeNormal, "SuccessfulAttachControlPlaneELB",
   832  		"Control plane instance %q is registered with load balancer", i.ID)
   833  	conditions.MarkTrue(machineScope.AWSMachine, infrav1.ELBAttachedCondition)
   834  	return nil
   835  }
   836  
   837  // AWSClusterToAWSMachines is a handler.ToRequestsFunc to be used to enqeue requests for reconciliation
   838  // of AWSMachines.
   839  func (r *AWSMachineReconciler) AWSClusterToAWSMachines(log logr.Logger) handler.MapFunc {
   840  	return func(o client.Object) []ctrl.Request {
   841  		c, ok := o.(*infrav1.AWSCluster)
   842  		if !ok {
   843  			panic(fmt.Sprintf("Expected a AWSCluster but got a %T", o))
   844  		}
   845  
   846  		log := log.WithValues("objectMapper", "awsClusterToAWSMachine", "namespace", c.Namespace, "awsCluster", c.Name)
   847  
   848  		// Don't handle deleted AWSClusters
   849  		if !c.ObjectMeta.DeletionTimestamp.IsZero() {
   850  			log.V(4).Info("AWSCluster has a deletion timestamp, skipping mapping.")
   851  			return nil
   852  		}
   853  
   854  		cluster, err := util.GetOwnerCluster(context.TODO(), r.Client, c.ObjectMeta)
   855  		switch {
   856  		case apierrors.IsNotFound(err) || cluster == nil:
   857  			log.V(4).Info("Cluster for AWSCluster not found, skipping mapping.")
   858  			return nil
   859  		case err != nil:
   860  			log.Error(err, "Failed to get owning cluster, skipping mapping.")
   861  			return nil
   862  		}
   863  
   864  		return r.requestsForCluster(log, cluster.Namespace, cluster.Name)
   865  	}
   866  }
   867  
   868  func (r *AWSMachineReconciler) requeueAWSMachinesForUnpausedCluster(log logr.Logger) handler.MapFunc {
   869  	return func(o client.Object) []ctrl.Request {
   870  		c, ok := o.(*clusterv1.Cluster)
   871  		if !ok {
   872  			panic(fmt.Sprintf("Expected a Cluster but got a %T", o))
   873  		}
   874  
   875  		log := log.WithValues("objectMapper", "clusterToAWSMachine", "namespace", c.Namespace, "cluster", c.Name)
   876  
   877  		// Don't handle deleted clusters
   878  		if !c.ObjectMeta.DeletionTimestamp.IsZero() {
   879  			log.V(4).Info("Cluster has a deletion timestamp, skipping mapping.")
   880  			return nil
   881  		}
   882  
   883  		return r.requestsForCluster(log, c.Namespace, c.Name)
   884  	}
   885  }
   886  
   887  func (r *AWSMachineReconciler) requestsForCluster(log logr.Logger, namespace, name string) []ctrl.Request {
   888  	labels := map[string]string{clusterv1.ClusterLabelName: name}
   889  	machineList := &clusterv1.MachineList{}
   890  	if err := r.Client.List(context.TODO(), machineList, client.InNamespace(namespace), client.MatchingLabels(labels)); err != nil {
   891  		log.Error(err, "Failed to get owned Machines, skipping mapping.")
   892  		return nil
   893  	}
   894  
   895  	result := make([]ctrl.Request, 0, len(machineList.Items))
   896  	for _, m := range machineList.Items {
   897  		log.WithValues("machine", m.Name)
   898  		if m.Spec.InfrastructureRef.GroupVersionKind().Kind != "AWSMachine" {
   899  			log.V(4).Info("Machine has an InfrastructureRef for a different type, will not add to reconciliation request.")
   900  			continue
   901  		}
   902  		if m.Spec.InfrastructureRef.Name == "" {
   903  			log.V(4).Info("Machine has an InfrastructureRef with an empty name, will not add to reconciliation request.")
   904  			continue
   905  		}
   906  		log.WithValues("awsMachine", m.Spec.InfrastructureRef.Name)
   907  		log.V(4).Info("Adding AWSMachine to reconciliation request.")
   908  		result = append(result, ctrl.Request{NamespacedName: client.ObjectKey{Namespace: m.Namespace, Name: m.Spec.InfrastructureRef.Name}})
   909  	}
   910  	return result
   911  }
   912  
   913  func (r *AWSMachineReconciler) getInfraCluster(ctx context.Context, log logr.Logger, cluster *clusterv1.Cluster, awsMachine *infrav1.AWSMachine) (scope.EC2Scope, error) {
   914  	var clusterScope *scope.ClusterScope
   915  	var managedControlPlaneScope *scope.ManagedControlPlaneScope
   916  	var err error
   917  
   918  	if cluster.Spec.ControlPlaneRef != nil && cluster.Spec.ControlPlaneRef.Kind == "AWSManagedControlPlane" {
   919  		controlPlane := &ekscontrolplanev1.AWSManagedControlPlane{}
   920  		controlPlaneName := client.ObjectKey{
   921  			Namespace: awsMachine.Namespace,
   922  			Name:      cluster.Spec.ControlPlaneRef.Name,
   923  		}
   924  
   925  		if err := r.Get(ctx, controlPlaneName, controlPlane); err != nil {
   926  			// AWSManagedControlPlane is not ready
   927  			return nil, nil // nolint:nilerr
   928  		}
   929  
   930  		managedControlPlaneScope, err = scope.NewManagedControlPlaneScope(scope.ManagedControlPlaneScopeParams{
   931  			Client:         r.Client,
   932  			Logger:         &log,
   933  			Cluster:        cluster,
   934  			ControlPlane:   controlPlane,
   935  			ControllerName: "awsManagedControlPlane",
   936  			Endpoints:      r.Endpoints,
   937  		})
   938  		if err != nil {
   939  			return nil, err
   940  		}
   941  
   942  		return managedControlPlaneScope, nil
   943  	}
   944  
   945  	awsCluster := &infrav1.AWSCluster{}
   946  
   947  	infraClusterName := client.ObjectKey{
   948  		Namespace: awsMachine.Namespace,
   949  		Name:      cluster.Spec.InfrastructureRef.Name,
   950  	}
   951  
   952  	if err := r.Client.Get(ctx, infraClusterName, awsCluster); err != nil {
   953  		// AWSCluster is not ready
   954  		return nil, nil // nolint:nilerr
   955  	}
   956  
   957  	// Create the cluster scope
   958  	clusterScope, err = scope.NewClusterScope(scope.ClusterScopeParams{
   959  		Client:         r.Client,
   960  		Logger:         &log,
   961  		Cluster:        cluster,
   962  		AWSCluster:     awsCluster,
   963  		ControllerName: "awsmachine",
   964  	})
   965  	if err != nil {
   966  		return nil, err
   967  	}
   968  
   969  	return clusterScope, nil
   970  }
   971  
   972  func (r *AWSMachineReconciler) indexAWSMachineByInstanceID(o client.Object) []string {
   973  	awsMachine, ok := o.(*infrav1.AWSMachine)
   974  	if !ok {
   975  		r.Log.Error(errors.New("incorrect type"), "expected an AWSMachine", "type", fmt.Sprintf("%T", o))
   976  		return nil
   977  	}
   978  
   979  	if awsMachine.Spec.InstanceID != nil {
   980  		return []string{*awsMachine.Spec.InstanceID}
   981  	}
   982  
   983  	return nil
   984  }
   985  
   986  func (r *AWSMachineReconciler) ensureStorageTags(ec2svc services.EC2Interface, instance *infrav1.Instance, machine *infrav1.AWSMachine) {
   987  	annotations, err := r.machineAnnotationJSON(machine, VolumeTagsLastAppliedAnnotation)
   988  	if err != nil {
   989  		r.Log.Error(err, "Failed to fetch the annotations for volume tags")
   990  	}
   991  	for _, volumeID := range instance.VolumeIDs {
   992  		if subAnnotation, ok := annotations[volumeID].(map[string]interface{}); ok {
   993  			newAnnotation, err := r.ensureVolumeTags(ec2svc, aws.String(volumeID), subAnnotation, machine.Spec.AdditionalTags)
   994  			if err != nil {
   995  				r.Log.Error(err, "Failed to fetch the changed volume tags in EC2 instance")
   996  			}
   997  			annotations[volumeID] = newAnnotation
   998  		} else {
   999  			newAnnotation, err := r.ensureVolumeTags(ec2svc, aws.String(volumeID), make(map[string]interface{}), machine.Spec.AdditionalTags)
  1000  			if err != nil {
  1001  				r.Log.Error(err, "Failed to fetch the changed volume tags in EC2 instance")
  1002  			}
  1003  			annotations[volumeID] = newAnnotation
  1004  		}
  1005  
  1006  		// We also need to update the annotation if anything changed.
  1007  		err = r.updateMachineAnnotationJSON(machine, VolumeTagsLastAppliedAnnotation, annotations)
  1008  		if err != nil {
  1009  			r.Log.Error(err, "Failed to fetch the changed volume tags in EC2 instance")
  1010  		}
  1011  	}
  1012  }