sigs.k8s.io/cluster-api-provider-aws@v1.5.5/controllers/awsmachine_controller_test.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  	"fmt"
    21  	"testing"
    22  	"time"
    23  
    24  	"github.com/aws/aws-sdk-go/aws"
    25  	"github.com/aws/aws-sdk-go/service/ec2"
    26  	"github.com/aws/aws-sdk-go/service/elb"
    27  	"github.com/golang/mock/gomock"
    28  	. "github.com/onsi/gomega"
    29  	"github.com/pkg/errors"
    30  	corev1 "k8s.io/api/core/v1"
    31  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    32  	"k8s.io/client-go/tools/record"
    33  	"k8s.io/utils/pointer"
    34  	"sigs.k8s.io/controller-runtime/pkg/client"
    35  
    36  	infrav1 "sigs.k8s.io/cluster-api-provider-aws/api/v1beta1"
    37  	"sigs.k8s.io/cluster-api-provider-aws/pkg/cloud"
    38  	"sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/scope"
    39  	"sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services"
    40  	ec2Service "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services/ec2"
    41  	elbService "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services/elb"
    42  	"sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services/mock_services"
    43  	"sigs.k8s.io/cluster-api-provider-aws/test/mocks"
    44  	clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
    45  	"sigs.k8s.io/cluster-api/util"
    46  	"sigs.k8s.io/cluster-api/util/conditions"
    47  )
    48  
    49  func TestAWSMachineReconciler_IntegrationTests(t *testing.T) {
    50  	var (
    51  		reconciler AWSMachineReconciler
    52  		mockCtrl   *gomock.Controller
    53  		recorder   *record.FakeRecorder
    54  	)
    55  
    56  	setup := func(t *testing.T, g *WithT) {
    57  		t.Helper()
    58  		mockCtrl = gomock.NewController(t)
    59  		recorder = record.NewFakeRecorder(10)
    60  		reconciler = AWSMachineReconciler{
    61  			Client:   testEnv.Client,
    62  			Recorder: recorder,
    63  		}
    64  	}
    65  
    66  	teardown := func(g *WithT) {
    67  		mockCtrl.Finish()
    68  	}
    69  
    70  	t.Run("Should successfully reconcile control plane machine creation", func(t *testing.T) {
    71  		g := NewWithT(t)
    72  		mockCtrl = gomock.NewController(t)
    73  		ec2Mock := mocks.NewMockEC2API(mockCtrl)
    74  		secretMock := mock_services.NewMockSecretInterface(mockCtrl)
    75  		elbMock := mocks.NewMockELBAPI(mockCtrl)
    76  
    77  		expect := func(m *mocks.MockEC2APIMockRecorder, s *mock_services.MockSecretInterfaceMockRecorder, e *mocks.MockELBAPIMockRecorder) {
    78  			mockedCreateInstanceCalls(m)
    79  			mockedCreateSecretCall(s)
    80  			mockedCreateLBCalls(t, e)
    81  		}
    82  		expect(ec2Mock.EXPECT(), secretMock.EXPECT(), elbMock.EXPECT())
    83  
    84  		ns, err := testEnv.CreateNamespace(ctx, fmt.Sprintf("integ-test-%s", util.RandomString(5)))
    85  		g.Expect(err).To(BeNil())
    86  
    87  		secret := &corev1.Secret{
    88  			ObjectMeta: metav1.ObjectMeta{
    89  				Name:      "bootstrap-data",
    90  				Namespace: ns.Name,
    91  			},
    92  			Data: map[string][]byte{
    93  				"value": []byte("shell-script"),
    94  			},
    95  		}
    96  		g.Expect(testEnv.Create(ctx, secret)).To(Succeed())
    97  
    98  		setup(t, g)
    99  		awsMachine := getAWSMachine()
   100  		awsMachine.Namespace = ns.Name
   101  		createAWSMachine(g, awsMachine)
   102  
   103  		defer teardown(g)
   104  		defer t.Cleanup(func() {
   105  			g.Expect(testEnv.Cleanup(ctx, awsMachine, ns, secret)).To(Succeed())
   106  		})
   107  
   108  		cs, err := getClusterScope(infrav1.AWSCluster{ObjectMeta: metav1.ObjectMeta{Name: "test"}, Spec: infrav1.AWSClusterSpec{NetworkSpec: infrav1.NetworkSpec{Subnets: []infrav1.SubnetSpec{
   109  			{
   110  				ID:               "subnet-1",
   111  				AvailabilityZone: "us-east-1a",
   112  			}},
   113  		}}})
   114  		g.Expect(err).To(BeNil())
   115  		cs.Cluster = &clusterv1.Cluster{ObjectMeta: metav1.ObjectMeta{Name: "test-cluster"}}
   116  		cs.AWSCluster.Status.Network.APIServerELB.DNSName = DNSName
   117  		cs.AWSCluster.Status.Network.SecurityGroups = map[infrav1.SecurityGroupRole]infrav1.SecurityGroup{
   118  			infrav1.SecurityGroupNode: {
   119  				ID: "1",
   120  			},
   121  			infrav1.SecurityGroupLB: {
   122  				ID: "2",
   123  			},
   124  			infrav1.SecurityGroupControlPlane: {
   125  				ID: "3",
   126  			}}
   127  		ms, err := getMachineScope(cs, awsMachine)
   128  		g.Expect(err).To(BeNil())
   129  
   130  		ms.Machine.Spec.Bootstrap.DataSecretName = aws.String("bootstrap-data")
   131  		ms.Machine.Spec.Version = aws.String("test")
   132  		ms.AWSMachine.Spec.Subnet = &infrav1.AWSResourceReference{ID: aws.String("subnet-1")}
   133  		ms.AWSMachine.Status.InstanceState = &infrav1.InstanceStateRunning
   134  		ms.Machine.Labels = map[string]string{clusterv1.MachineControlPlaneLabelName: ""}
   135  
   136  		ec2Svc := ec2Service.NewService(cs)
   137  		ec2Svc.EC2Client = ec2Mock
   138  		reconciler.ec2ServiceFactory = func(scope scope.EC2Scope) services.EC2Interface {
   139  			return ec2Svc
   140  		}
   141  
   142  		elbSvc := elbService.NewService(cs)
   143  		elbSvc.EC2Client = ec2Mock
   144  		elbSvc.ELBClient = elbMock
   145  		reconciler.elbServiceFactory = func(scope scope.ELBScope) services.ELBInterface {
   146  			return elbSvc
   147  		}
   148  
   149  		reconciler.secretsManagerServiceFactory = func(clusterScope cloud.ClusterScoper) services.SecretInterface {
   150  			return secretMock
   151  		}
   152  
   153  		_, err = reconciler.reconcileNormal(ctx, ms, cs, cs, cs, cs)
   154  		g.Expect(err).To(BeNil())
   155  		expectConditions(g, ms.AWSMachine, []conditionAssertion{{infrav1.SecurityGroupsReadyCondition, corev1.ConditionTrue, "", ""},
   156  			{infrav1.InstanceReadyCondition, corev1.ConditionTrue, "", ""},
   157  			{infrav1.ELBAttachedCondition, corev1.ConditionTrue, "", ""}})
   158  		g.Expect(ms.AWSMachine.Finalizers).Should(ContainElement(infrav1.MachineFinalizer))
   159  	})
   160  	t.Run("Should successfully reconcile control plane machine deletion", func(t *testing.T) {
   161  		g := NewWithT(t)
   162  		mockCtrl = gomock.NewController(t)
   163  		ec2Mock := mocks.NewMockEC2API(mockCtrl)
   164  		elbMock := mocks.NewMockELBAPI(mockCtrl)
   165  
   166  		expect := func(m *mocks.MockEC2APIMockRecorder, e *mocks.MockELBAPIMockRecorder) {
   167  			mockedDescribeInstanceCalls(m)
   168  			mockedDeleteLBCalls(e)
   169  			mockedDeleteInstanceCalls(m)
   170  		}
   171  		expect(ec2Mock.EXPECT(), elbMock.EXPECT())
   172  
   173  		ns, err := testEnv.CreateNamespace(ctx, fmt.Sprintf("integ-test-%s", util.RandomString(5)))
   174  		g.Expect(err).To(BeNil())
   175  
   176  		setup(t, g)
   177  		awsMachine := getAWSMachine()
   178  		awsMachine.Namespace = ns.Name
   179  		createAWSMachine(g, awsMachine)
   180  
   181  		defer teardown(g)
   182  		defer t.Cleanup(func() {
   183  			g.Expect(testEnv.Cleanup(ctx, awsMachine, ns)).To(Succeed())
   184  		})
   185  
   186  		cs, err := getClusterScope(infrav1.AWSCluster{ObjectMeta: metav1.ObjectMeta{Name: "test"}})
   187  		g.Expect(err).To(BeNil())
   188  		cs.Cluster = &clusterv1.Cluster{ObjectMeta: metav1.ObjectMeta{Name: "test-cluster"}}
   189  		ms, err := getMachineScope(cs, awsMachine)
   190  		g.Expect(err).To(BeNil())
   191  
   192  		ms.AWSMachine.Status.InstanceState = &infrav1.InstanceStateRunning
   193  		ms.Machine.Labels = map[string]string{clusterv1.MachineControlPlaneLabelName: ""}
   194  		ms.AWSMachine.Spec.ProviderID = aws.String("aws:////myMachine")
   195  
   196  		ec2Svc := ec2Service.NewService(cs)
   197  		ec2Svc.EC2Client = ec2Mock
   198  		reconciler.ec2ServiceFactory = func(scope scope.EC2Scope) services.EC2Interface {
   199  			return ec2Svc
   200  		}
   201  
   202  		elbSvc := elbService.NewService(cs)
   203  		elbSvc.EC2Client = ec2Mock
   204  		elbSvc.ELBClient = elbMock
   205  		reconciler.elbServiceFactory = func(scope scope.ELBScope) services.ELBInterface {
   206  			return elbSvc
   207  		}
   208  
   209  		_, err = reconciler.reconcileDelete(ms, cs, cs, cs, cs)
   210  		g.Expect(err).To(BeNil())
   211  		expectConditions(g, ms.AWSMachine, []conditionAssertion{
   212  			{infrav1.InstanceReadyCondition, corev1.ConditionFalse, clusterv1.ConditionSeverityInfo, clusterv1.DeletedReason},
   213  			{infrav1.ELBAttachedCondition, corev1.ConditionFalse, clusterv1.ConditionSeverityInfo, clusterv1.DeletedReason}})
   214  		g.Expect(ms.AWSMachine.Finalizers).ShouldNot(ContainElement(infrav1.MachineFinalizer))
   215  	})
   216  	t.Run("Should fail reconciling control-plane machine creation while attaching load balancer", func(t *testing.T) {
   217  		g := NewWithT(t)
   218  		mockCtrl = gomock.NewController(t)
   219  		ec2Mock := mocks.NewMockEC2API(mockCtrl)
   220  		secretMock := mock_services.NewMockSecretInterface(mockCtrl)
   221  		elbMock := mocks.NewMockELBAPI(mockCtrl)
   222  
   223  		expect := func(m *mocks.MockEC2APIMockRecorder, s *mock_services.MockSecretInterfaceMockRecorder, e *mocks.MockELBAPIMockRecorder) {
   224  			mockedCreateInstanceCalls(m)
   225  			mockedCreateSecretCall(s)
   226  			e.DescribeLoadBalancers(gomock.Eq(&elb.DescribeLoadBalancersInput{
   227  				LoadBalancerNames: aws.StringSlice([]string{"test-cluster-apiserver"}),
   228  			})).
   229  				Return(&elb.DescribeLoadBalancersOutput{}, nil)
   230  		}
   231  		expect(ec2Mock.EXPECT(), secretMock.EXPECT(), elbMock.EXPECT())
   232  
   233  		ns, err := testEnv.CreateNamespace(ctx, fmt.Sprintf("integ-test-%s", util.RandomString(5)))
   234  		g.Expect(err).To(BeNil())
   235  
   236  		secret := &corev1.Secret{
   237  			ObjectMeta: metav1.ObjectMeta{
   238  				Name:      "bootstrap-data",
   239  				Namespace: ns.Name,
   240  			},
   241  			Data: map[string][]byte{
   242  				"value": []byte("shell-script"),
   243  			},
   244  		}
   245  		g.Expect(testEnv.Create(ctx, secret)).To(Succeed())
   246  
   247  		setup(t, g)
   248  		awsMachine := getAWSMachine()
   249  		awsMachine.Namespace = ns.Name
   250  		createAWSMachine(g, awsMachine)
   251  
   252  		defer teardown(g)
   253  		defer t.Cleanup(func() {
   254  			g.Expect(testEnv.Cleanup(ctx, awsMachine, ns, secret)).To(Succeed())
   255  		})
   256  
   257  		cs, err := getClusterScope(infrav1.AWSCluster{ObjectMeta: metav1.ObjectMeta{Name: "test"}, Spec: infrav1.AWSClusterSpec{NetworkSpec: infrav1.NetworkSpec{Subnets: []infrav1.SubnetSpec{
   258  			{
   259  				ID:               "subnet-1",
   260  				AvailabilityZone: "us-east-1a",
   261  			}},
   262  		}}})
   263  		g.Expect(err).To(BeNil())
   264  		cs.Cluster = &clusterv1.Cluster{ObjectMeta: metav1.ObjectMeta{Name: "test-cluster"}}
   265  		cs.AWSCluster.Status.Network.APIServerELB.DNSName = DNSName
   266  		cs.AWSCluster.Status.Network.SecurityGroups = map[infrav1.SecurityGroupRole]infrav1.SecurityGroup{
   267  			infrav1.SecurityGroupNode: {
   268  				ID: "1",
   269  			},
   270  			infrav1.SecurityGroupLB: {
   271  				ID: "2",
   272  			},
   273  			infrav1.SecurityGroupControlPlane: {
   274  				ID: "3",
   275  			}}
   276  		ms, err := getMachineScope(cs, awsMachine)
   277  		g.Expect(err).To(BeNil())
   278  
   279  		ms.Machine.Spec.Bootstrap.DataSecretName = aws.String("bootstrap-data")
   280  		ms.Machine.Spec.Version = aws.String("test")
   281  		ms.AWSMachine.Spec.Subnet = &infrav1.AWSResourceReference{ID: aws.String("subnet-1")}
   282  		ms.AWSMachine.Status.InstanceState = &infrav1.InstanceStateRunning
   283  		ms.Machine.Labels = map[string]string{clusterv1.MachineControlPlaneLabelName: ""}
   284  
   285  		ec2Svc := ec2Service.NewService(cs)
   286  		ec2Svc.EC2Client = ec2Mock
   287  		reconciler.ec2ServiceFactory = func(scope scope.EC2Scope) services.EC2Interface {
   288  			return ec2Svc
   289  		}
   290  
   291  		elbSvc := elbService.NewService(cs)
   292  		elbSvc.EC2Client = ec2Mock
   293  		elbSvc.ELBClient = elbMock
   294  		reconciler.elbServiceFactory = func(scope scope.ELBScope) services.ELBInterface {
   295  			return elbSvc
   296  		}
   297  
   298  		reconciler.secretsManagerServiceFactory = func(clusterScope cloud.ClusterScoper) services.SecretInterface {
   299  			return secretMock
   300  		}
   301  
   302  		_, err = reconciler.reconcileNormal(ctx, ms, cs, cs, cs, cs)
   303  		g.Expect(err).Should(HaveOccurred())
   304  		expectConditions(g, ms.AWSMachine, []conditionAssertion{{infrav1.InstanceReadyCondition, corev1.ConditionTrue, "", ""}})
   305  		g.Expect(ms.AWSMachine.Finalizers).Should(ContainElement(infrav1.MachineFinalizer))
   306  	})
   307  	t.Run("Should fail in reconciling control-plane machine deletion while terminating instance ", func(t *testing.T) {
   308  		g := NewWithT(t)
   309  		mockCtrl = gomock.NewController(t)
   310  		ec2Mock := mocks.NewMockEC2API(mockCtrl)
   311  		elbMock := mocks.NewMockELBAPI(mockCtrl)
   312  
   313  		expect := func(m *mocks.MockEC2APIMockRecorder, e *mocks.MockELBAPIMockRecorder) {
   314  			mockedDescribeInstanceCalls(m)
   315  			mockedDeleteLBCalls(e)
   316  			m.TerminateInstances(
   317  				gomock.Eq(&ec2.TerminateInstancesInput{
   318  					InstanceIds: aws.StringSlice([]string{"id-1"}),
   319  				}),
   320  			).
   321  				Return(nil, errors.New("Failed to delete instance"))
   322  		}
   323  		expect(ec2Mock.EXPECT(), elbMock.EXPECT())
   324  
   325  		ns, err := testEnv.CreateNamespace(ctx, fmt.Sprintf("integ-test-%s", util.RandomString(5)))
   326  		g.Expect(err).To(BeNil())
   327  
   328  		setup(t, g)
   329  		awsMachine := getAWSMachine()
   330  		awsMachine.Namespace = ns.Name
   331  		createAWSMachine(g, awsMachine)
   332  
   333  		defer teardown(g)
   334  		defer t.Cleanup(func() {
   335  			g.Expect(testEnv.Cleanup(ctx, awsMachine, ns)).To(Succeed())
   336  		})
   337  
   338  		cs, err := getClusterScope(infrav1.AWSCluster{ObjectMeta: metav1.ObjectMeta{Name: "test"}})
   339  		g.Expect(err).To(BeNil())
   340  		cs.Cluster = &clusterv1.Cluster{ObjectMeta: metav1.ObjectMeta{Name: "test-cluster"}}
   341  		ms, err := getMachineScope(cs, awsMachine)
   342  		g.Expect(err).To(BeNil())
   343  
   344  		ms.AWSMachine.Status.InstanceState = &infrav1.InstanceStateRunning
   345  		ms.Machine.Labels = map[string]string{clusterv1.MachineControlPlaneLabelName: ""}
   346  		ms.AWSMachine.Spec.ProviderID = aws.String("aws:////myMachine")
   347  
   348  		ec2Svc := ec2Service.NewService(cs)
   349  		ec2Svc.EC2Client = ec2Mock
   350  		reconciler.ec2ServiceFactory = func(scope scope.EC2Scope) services.EC2Interface {
   351  			return ec2Svc
   352  		}
   353  
   354  		elbSvc := elbService.NewService(cs)
   355  		elbSvc.EC2Client = ec2Mock
   356  		elbSvc.ELBClient = elbMock
   357  		reconciler.elbServiceFactory = func(scope scope.ELBScope) services.ELBInterface {
   358  			return elbSvc
   359  		}
   360  
   361  		_, err = reconciler.reconcileDelete(ms, cs, cs, cs, cs)
   362  		g.Expect(err).Should(HaveOccurred())
   363  		expectConditions(g, ms.AWSMachine, []conditionAssertion{{infrav1.InstanceReadyCondition, corev1.ConditionFalse, clusterv1.ConditionSeverityWarning, "DeletingFailed"},
   364  			{infrav1.ELBAttachedCondition, corev1.ConditionFalse, clusterv1.ConditionSeverityInfo, clusterv1.DeletedReason}})
   365  		g.Expect(ms.AWSMachine.Finalizers).ShouldNot(ContainElement(infrav1.MachineFinalizer))
   366  	})
   367  }
   368  
   369  func getMachineScope(cs *scope.ClusterScope, awsMachine *infrav1.AWSMachine) (*scope.MachineScope, error) {
   370  	return scope.NewMachineScope(
   371  		scope.MachineScopeParams{
   372  			Client: testEnv,
   373  			Cluster: &clusterv1.Cluster{
   374  				ObjectMeta: metav1.ObjectMeta{
   375  					Name: "test",
   376  				},
   377  				Status: clusterv1.ClusterStatus{
   378  					InfrastructureReady: true,
   379  				},
   380  			},
   381  			Machine: &clusterv1.Machine{
   382  				ObjectMeta: metav1.ObjectMeta{
   383  					Name: "test",
   384  				},
   385  				Spec: clusterv1.MachineSpec{
   386  					Bootstrap: clusterv1.Bootstrap{
   387  						DataSecretName: pointer.StringPtr("bootstrap-data"),
   388  					},
   389  				},
   390  			},
   391  			InfraCluster: cs,
   392  			AWSMachine:   awsMachine,
   393  		},
   394  	)
   395  }
   396  
   397  func createAWSMachine(g *WithT, awsMachine *infrav1.AWSMachine) {
   398  	g.Expect(testEnv.Create(ctx, awsMachine)).To(Succeed())
   399  	g.Eventually(func() bool {
   400  		machine := &infrav1.AWSMachine{}
   401  		key := client.ObjectKey{
   402  			Name:      awsMachine.Name,
   403  			Namespace: awsMachine.Namespace,
   404  		}
   405  		return testEnv.Get(ctx, key, machine) == nil
   406  	}, 10*time.Second).Should(Equal(true))
   407  }
   408  
   409  func getAWSMachine() *infrav1.AWSMachine {
   410  	return &infrav1.AWSMachine{
   411  		ObjectMeta: metav1.ObjectMeta{
   412  			Name: "test",
   413  		},
   414  		Spec: infrav1.AWSMachineSpec{
   415  			CloudInit: infrav1.CloudInit{
   416  				SecureSecretsBackend: infrav1.SecretBackendSecretsManager,
   417  				SecretPrefix:         "prefix",
   418  				SecretCount:          1000,
   419  			},
   420  			InstanceType: "test",
   421  			Subnet:       &infrav1.AWSResourceReference{ID: aws.String("subnet-1")},
   422  		},
   423  	}
   424  }
   425  
   426  func getAWSMachineWithAdditionalTags() *infrav1.AWSMachine {
   427  	return &infrav1.AWSMachine{
   428  		ObjectMeta: metav1.ObjectMeta{
   429  			Name: "test",
   430  		},
   431  		Spec: infrav1.AWSMachineSpec{
   432  			CloudInit: infrav1.CloudInit{
   433  				SecureSecretsBackend: infrav1.SecretBackendSecretsManager,
   434  			},
   435  			AdditionalTags: map[string]string{"foo": "bar"},
   436  		},
   437  	}
   438  }
   439  
   440  func PointsTo(s string) gomock.Matcher {
   441  	return &pointsTo{
   442  		val: s,
   443  	}
   444  }
   445  
   446  type pointsTo struct {
   447  	val string
   448  }
   449  
   450  func (p *pointsTo) Matches(x interface{}) bool {
   451  	ptr, ok := x.(*string)
   452  	if !ok {
   453  		return false
   454  	}
   455  
   456  	if ptr == nil {
   457  		return false
   458  	}
   459  
   460  	return *ptr == p.val
   461  }
   462  
   463  func (p *pointsTo) String() string {
   464  	return fmt.Sprintf("Pointer to string %q", p.val)
   465  }
   466  
   467  type conditionAssertion struct {
   468  	conditionType clusterv1.ConditionType
   469  	status        corev1.ConditionStatus
   470  	severity      clusterv1.ConditionSeverity
   471  	reason        string
   472  }
   473  
   474  func expectConditions(g *WithT, m *infrav1.AWSMachine, expected []conditionAssertion) {
   475  	g.Expect(len(m.Status.Conditions)).To(BeNumerically(">=", len(expected)), "number of conditions")
   476  	for _, c := range expected {
   477  		actual := conditions.Get(m, c.conditionType)
   478  		g.Expect(actual).To(Not(BeNil()))
   479  		g.Expect(actual.Type).To(Equal(c.conditionType))
   480  		g.Expect(actual.Status).To(Equal(c.status))
   481  		g.Expect(actual.Severity).To(Equal(c.severity))
   482  		g.Expect(actual.Reason).To(Equal(c.reason))
   483  	}
   484  }
   485  
   486  func mockedCreateSecretCall(s *mock_services.MockSecretInterfaceMockRecorder) {
   487  	s.Create(gomock.AssignableToTypeOf(&scope.MachineScope{}), gomock.AssignableToTypeOf([]byte{}))
   488  	s.UserData(gomock.Any(), gomock.Any(), gomock.Any(), gomock.AssignableToTypeOf([]scope.ServiceEndpoint{}))
   489  }
   490  
   491  func mockedCreateInstanceCalls(m *mocks.MockEC2APIMockRecorder) {
   492  	m.DescribeInstances(gomock.Eq(&ec2.DescribeInstancesInput{
   493  		Filters: []*ec2.Filter{
   494  			{
   495  				Name:   aws.String("vpc-id"),
   496  				Values: aws.StringSlice([]string{""}),
   497  			},
   498  			{
   499  				Name:   aws.String("tag:sigs.k8s.io/cluster-api-provider-aws/cluster/test-cluster"),
   500  				Values: aws.StringSlice([]string{"owned"}),
   501  			},
   502  			{
   503  				Name:   aws.String("tag:Name"),
   504  				Values: aws.StringSlice([]string{"test"}),
   505  			},
   506  			{
   507  				Name:   aws.String("instance-state-name"),
   508  				Values: aws.StringSlice([]string{"pending", "running"}),
   509  			},
   510  		},
   511  	})).Return(&ec2.DescribeInstancesOutput{}, nil)
   512  	m.DescribeImages(gomock.Eq(&ec2.DescribeImagesInput{
   513  		Filters: []*ec2.Filter{
   514  			{
   515  				Name:   aws.String("owner-id"),
   516  				Values: aws.StringSlice([]string{"258751437250"}),
   517  			},
   518  			{
   519  				Name:   aws.String("name"),
   520  				Values: aws.StringSlice([]string{"capa-ami-ubuntu-18.04-?test-*"}),
   521  			},
   522  			{
   523  				Name:   aws.String("architecture"),
   524  				Values: aws.StringSlice([]string{"x86_64"}),
   525  			},
   526  			{
   527  				Name:   aws.String("state"),
   528  				Values: aws.StringSlice([]string{"available"}),
   529  			},
   530  			{
   531  				Name:   aws.String("virtualization-type"),
   532  				Values: aws.StringSlice([]string{"hvm"}),
   533  			},
   534  		}})).Return(&ec2.DescribeImagesOutput{Images: []*ec2.Image{
   535  		{
   536  			ImageId:      aws.String("latest"),
   537  			CreationDate: aws.String("2019-02-08T17:02:31.000Z"),
   538  		},
   539  	}}, nil)
   540  	m.RunInstances(gomock.Any()).Return(&ec2.Reservation{
   541  		Instances: []*ec2.Instance{
   542  			{
   543  				State: &ec2.InstanceState{
   544  					Name: aws.String(ec2.InstanceStateNameRunning),
   545  				},
   546  				IamInstanceProfile: &ec2.IamInstanceProfile{
   547  					Arn: aws.String("arn:aws:iam::123456789012:instance-profile/foo"),
   548  				},
   549  				InstanceId:     aws.String("two"),
   550  				InstanceType:   aws.String("m5.large"),
   551  				SubnetId:       aws.String("subnet-1"),
   552  				ImageId:        aws.String("ami-1"),
   553  				RootDeviceName: aws.String("device-1"),
   554  				BlockDeviceMappings: []*ec2.InstanceBlockDeviceMapping{
   555  					{
   556  						DeviceName: aws.String("device-1"),
   557  						Ebs: &ec2.EbsInstanceBlockDevice{
   558  							VolumeId: aws.String("volume-1"),
   559  						},
   560  					},
   561  				},
   562  				Placement: &ec2.Placement{
   563  					AvailabilityZone: aws.String("us-east-1a"),
   564  				},
   565  			},
   566  		},
   567  	}, nil)
   568  	m.WaitUntilInstanceRunningWithContext(gomock.Any(), gomock.Any(), gomock.Any()).
   569  		Return(nil)
   570  	m.DescribeNetworkInterfaces(gomock.Eq(&ec2.DescribeNetworkInterfacesInput{Filters: []*ec2.Filter{
   571  		{
   572  			Name:   aws.String("attachment.instance-id"),
   573  			Values: aws.StringSlice([]string{"two"}),
   574  		},
   575  	}})).Return(&ec2.DescribeNetworkInterfacesOutput{
   576  		NetworkInterfaces: []*ec2.NetworkInterface{
   577  			{
   578  				NetworkInterfaceId: aws.String("eni-1"),
   579  				Groups: []*ec2.GroupIdentifier{
   580  					{
   581  						GroupId: aws.String("3"),
   582  					},
   583  				},
   584  			},
   585  		}}, nil).MaxTimes(2)
   586  	m.DescribeNetworkInterfaceAttribute(gomock.Eq(&ec2.DescribeNetworkInterfaceAttributeInput{
   587  		NetworkInterfaceId: aws.String("eni-1"),
   588  		Attribute:          aws.String("groupSet"),
   589  	})).Return(&ec2.DescribeNetworkInterfaceAttributeOutput{Groups: []*ec2.GroupIdentifier{{GroupId: aws.String("3")}}}, nil).MaxTimes(1)
   590  	m.ModifyNetworkInterfaceAttribute(gomock.Any()).AnyTimes()
   591  	m.DescribeSubnets(gomock.Eq(&ec2.DescribeSubnetsInput{Filters: []*ec2.Filter{
   592  		{
   593  			Name:   aws.String("state"),
   594  			Values: aws.StringSlice([]string{"pending", "available"}),
   595  		},
   596  		{
   597  			Name:   aws.String("vpc-id"),
   598  			Values: aws.StringSlice([]string{""}),
   599  		},
   600  		{
   601  			Name:   aws.String("subnet-id"),
   602  			Values: aws.StringSlice([]string{"subnet-1"}),
   603  		},
   604  	}})).Return(&ec2.DescribeSubnetsOutput{Subnets: []*ec2.Subnet{
   605  		{
   606  			SubnetId: aws.String("subnet-1"),
   607  		},
   608  	}}, nil)
   609  }
   610  
   611  func mockedDescribeInstanceCalls(m *mocks.MockEC2APIMockRecorder) {
   612  	m.DescribeInstances(gomock.Eq(&ec2.DescribeInstancesInput{
   613  		InstanceIds: aws.StringSlice([]string{"myMachine"}),
   614  	})).Return(&ec2.DescribeInstancesOutput{
   615  		Reservations: []*ec2.Reservation{{Instances: []*ec2.Instance{{Placement: &ec2.Placement{AvailabilityZone: aws.String("us-east-1a")}, InstanceId: aws.String("id-1"), State: &ec2.InstanceState{Name: aws.String("id-1"), Code: aws.Int64(16)}}}}},
   616  	}, nil)
   617  }