Repository: kubernetes-sigs/cluster-api-provider-aws
Pull request #1407 (2019-12-10 13:43:49)

⚠️ Support bootstrap data in secret
<!-- please add a icon to the title of this PR (see https://sigs.k8s.io/cluster-api/VERSIONING.md), and delete this line and similar ones -->
<!-- the icon will be either ⚠️ (:warning:, major or breaking changes), ✨ (:sparkles:, minor or feature additions), 🐛 (:bug:, patch and bugfixes), 📖 (:book:, documentation or proposals), or 🏃 (:running:, other) -->

**What this PR does / why we need it**:
This PR is a follow-up requirement to an upstream change that now stores the bootstrap data in a secret rather than inline plaintext field.



Patch:
diff --git a/Makefile b/Makefile
index cc55371c2..7a8b5b6f7 100644
--- a/Makefile
+++ b/Makefile
@@ -75,7 +75,7 @@ help:  ## Display this help
 ## --------------------------------------
 
 .PHONY: test
-test: generate lint ## Run tests
+test: ## Run tests
 	go test -v ./...
 
 .PHONY: test-integration
diff --git a/controllers/awsmachine_controller.go b/controllers/awsmachine_controller.go
index e301516d0..8533a0754 100644
--- a/controllers/awsmachine_controller.go
+++ b/controllers/awsmachine_controller.go
@@ -285,8 +285,8 @@ func (r *AWSMachineReconciler) reconcileNormal(ctx context.Context, machineScope
 	}
 
 	// Make sure bootstrap data is available and populated.
-	if machineScope.Machine.Spec.Bootstrap.Data == nil {
-		machineScope.Info("Bootstrap data is not yet available")
+	if machineScope.Machine.Spec.Bootstrap.DataSecretName == nil {
+		machineScope.Info("Bootstrap data secret reference is not yet available")
 		return reconcile.Result{}, nil
 	}
 
@@ -381,7 +381,7 @@ func (r *AWSMachineReconciler) getOrCreate(scope *scope.MachineScope, ec2svc ser
 		// Create a new AWSMachine instance if we couldn't find a running instance.
 		instance, err = ec2svc.CreateInstance(scope)
 		if err != nil {
-			return nil, errors.Wrapf(err, "failed to create EC2 instance")
+			return nil, errors.Wrapf(err, "failed to create EC2 instance for AWSMachine %s/%s", scope.Namespace(), scope.Name())
 		}
 	}
 
diff --git a/go.mod b/go.mod
index 96263e7c9..e7a6dd922 100644
--- a/go.mod
+++ b/go.mod
@@ -6,22 +6,19 @@ require (
 	github.com/aws/aws-sdk-go v1.25.16
 	github.com/awslabs/goformation/v3 v3.0.0
 	github.com/go-logr/logr v0.1.0
-	github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef // indirect
 	github.com/golang/mock v1.2.0
 	github.com/onsi/ginkgo v1.10.1
 	github.com/onsi/gomega v1.7.0
 	github.com/pkg/errors v0.8.1
 	github.com/spf13/cobra v0.0.5
 	github.com/spf13/pflag v1.0.5
-	go.uber.org/atomic v1.4.0 // indirect
-	go.uber.org/zap v1.10.0 // indirect
-	golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7
+	golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392
 	golang.org/x/net v0.0.0-20191021144547-ec77196f6094
 	k8s.io/api v0.0.0-20191121015604-11707872ac1c
 	k8s.io/apimachinery v0.0.0-20191121015412-41065c7a8c2a
 	k8s.io/client-go v0.0.0-20190918160344-1fbdaa4c8d90
 	k8s.io/klog v1.0.0
-	k8s.io/utils v0.0.0-20190809000727-6c36bc71fc4a
-	sigs.k8s.io/cluster-api v0.2.6-0.20191209170203-ccb217449658
+	k8s.io/utils v0.0.0-20191030222137-2b95a09bc58d
+	sigs.k8s.io/cluster-api v0.2.6-0.20191209220803-5ea5faa9d9ba
 	sigs.k8s.io/controller-runtime v0.4.0
 )
diff --git a/go.sum b/go.sum
index a73d810fd..7e11257ec 100644
--- a/go.sum
+++ b/go.sum
@@ -112,12 +112,14 @@ github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/me
 github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
 github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d h1:3PaI8p3seN09VjbTYC/QWlUZdZ1qS1zGjy7LH2Wt07I=
 github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
+github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
+github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
 github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
 github.com/golang/groupcache v0.0.0-20180513044358-24b0969c4cb7 h1:u4bArs140e9+AfE52mFHOXVFnOSBJBRlzTHrOPLOIhE=
 github.com/golang/groupcache v0.0.0-20180513044358-24b0969c4cb7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
-github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef h1:veQD95Isof8w9/WXiA+pa3tz3fJXkt5B7QaRBrM62gk=
-github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/groupcache v0.0.0-20191027212112-611e8accdfc9 h1:uHTyIjqVhYRhLbJ8nIiOJHkEZZ+5YoOsAbD3sk82NiE=
+github.com/golang/groupcache v0.0.0-20191027212112-611e8accdfc9/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
 github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
 github.com/golang/mock v1.2.0 h1:28o5sBqPkBsMGnC6b4MvE2TzSr5/AT4c/1fLqVGIwlk=
 github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
@@ -316,9 +318,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90Pveol
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7 h1:0hQKqeLdqlt5iIwVOBErRisrHJAN57yOiPRQItI20fU=
-golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392 h1:ACG4HJsFiNMf47Y4PeRoebLNy/2lXT9EtprMuTFWt1M=
+golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190312203227-4b39c73a6495/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -373,6 +374,7 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191008105621-543471e840be h1:QAcqgptGM8IQBC9K/RC4o+O9YmqEm0diQn9QmZw/0mU=
 golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -383,6 +385,8 @@ golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 golang.org/x/time v0.0.0-20181108054448-85acf8d2951c h1:fqgJT0MGcGpPgpWU7VRdRjuArfcOvC4AoJmILihzhDg=
 golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs=
+golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -466,15 +470,15 @@ k8s.io/kube-openapi v0.0.0-20190816220812-743ec37842bf/go.mod h1:1TqjTSzOxsLGIKf
 k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a h1:UcxjrRMyNx/i/y8G7kPvLyy7rfbeuf1PYyBf973pgyU=
 k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E=
 k8s.io/utils v0.0.0-20190801114015-581e00157fb1/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
-k8s.io/utils v0.0.0-20190809000727-6c36bc71fc4a h1:uy5HAgt4Ha5rEMbhZA+aM1j2cq5LmR6LQ71EYC2sVH4=
-k8s.io/utils v0.0.0-20190809000727-6c36bc71fc4a/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
+k8s.io/utils v0.0.0-20191030222137-2b95a09bc58d h1:1P0iBJsBzxRmR+dIFnM+Iu4aLxnoa7lBqozW/0uHbT8=
+k8s.io/utils v0.0.0-20191030222137-2b95a09bc58d/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
 modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw=
 modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk=
 modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k=
 modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs=
 modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I=
-sigs.k8s.io/cluster-api v0.2.6-0.20191209170203-ccb217449658 h1:M251xbjyu+gofGEDuwHP17N+Qw2kfeamdbm1oVAglYE=
-sigs.k8s.io/cluster-api v0.2.6-0.20191209170203-ccb217449658/go.mod h1:2I/Kv7Em5Xp6xDK9VGz4PKqnura42WMzOAscsBesd0o=
+sigs.k8s.io/cluster-api v0.2.6-0.20191209220803-5ea5faa9d9ba h1:9bE0HNiA25d5h/bIp6cgYJMJgg4pCKXeb6VMSL29cf0=
+sigs.k8s.io/cluster-api v0.2.6-0.20191209220803-5ea5faa9d9ba/go.mod h1:Oslq3qK4vVBwVVPHcbKGCXKFio+SJXuFysYOM1xYUgk=
 sigs.k8s.io/controller-runtime v0.4.0 h1:wATM6/m+3w8lj8FXNaO6Fs/rq/vqoOjO1Q116Z9NPsg=
 sigs.k8s.io/controller-runtime v0.4.0/go.mod h1:ApC79lpY3PHW9xj/w9pj+lYkLgwAAUZwfXkME1Lajns=
 sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
diff --git a/pkg/cloud/scope/machine.go b/pkg/cloud/scope/machine.go
index 34aa48f38..b70a1ae98 100644
--- a/pkg/cloud/scope/machine.go
+++ b/pkg/cloud/scope/machine.go
@@ -22,6 +22,7 @@ import (
 	"github.com/go-logr/logr"
 	"github.com/pkg/errors"
 	corev1 "k8s.io/api/core/v1"
+	"k8s.io/apimachinery/pkg/types"
 	"k8s.io/klog/klogr"
 	"k8s.io/utils/pointer"
 	infrav1 "sigs.k8s.io/cluster-api-provider-aws/api/v1alpha3"
@@ -183,6 +184,26 @@ func (m *MachineScope) SetAddresses(addrs []corev1.NodeAddress) {
 	m.AWSMachine.Status.Addresses = addrs
 }
 
+// GetBootstrapData returns the bootstrap data from the secret in the Machine's bootstrap.dataSecretName.
+func (m *MachineScope) GetBootstrapData() (string, error) {
+	if m.Machine.Spec.Bootstrap.DataSecretName == nil {
+		return "", errors.New("error retrieving bootstrap data: linked Machine's bootstrap.dataSecretName is nil")
+	}
+
+	secret := &corev1.Secret{}
+	key := types.NamespacedName{Namespace: m.Namespace(), Name: *m.Machine.Spec.Bootstrap.DataSecretName}
+	if err := m.client.Get(context.TODO(), key, secret); err != nil {
+		return "", errors.Wrapf(err, "failed to retrieve bootstrap data secret for AWSMachine %s/%s", m.Namespace(), m.Name())
+	}
+
+	value, ok := secret.Data["value"]
+	if !ok {
+		return "", errors.New("error retrieving bootstrap data: secret value key is missing")
+	}
+
+	return string(value), nil
+}
+
 // Close the MachineScope by updating the machine spec, machine status.
 func (m *MachineScope) Close() error {
 	return m.patchHelper.Patch(context.TODO(), m.AWSMachine)
diff --git a/pkg/cloud/services/ec2/instances.go b/pkg/cloud/services/ec2/instances.go
index d4e77e6ab..2df1f6b5f 100644
--- a/pkg/cloud/services/ec2/instances.go
+++ b/pkg/cloud/services/ec2/instances.go
@@ -30,6 +30,7 @@ import (
 	"github.com/go-logr/logr"
 	"github.com/pkg/errors"
 	corev1 "k8s.io/api/core/v1"
+	"k8s.io/utils/pointer"
 	infrav1 "sigs.k8s.io/cluster-api-provider-aws/api/v1alpha3"
 	"sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/awserrors"
 	"sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/converters"
@@ -178,7 +179,12 @@ func (s *Service) CreateInstance(scope *scope.MachineScope) (*infrav1.Instance,
 	}
 
 	// Set userdata.
-	input.UserData = aws.String(*scope.Machine.Spec.Bootstrap.Data)
+	userData, err := scope.GetBootstrapData()
+	if err != nil {
+		record.Warnf(scope.AWSMachine, corev1.EventTypeWarning, "FailedGetBootstrapData", err.Error())
+		return nil, err
+	}
+	input.UserData = pointer.StringPtr(userData)
 
 	// Set security groups.
 	ids, err := s.GetCoreSecurityGroups(scope)


Test patch:
diff --git a/controllers/awsmachine_controller_test.go b/controllers/awsmachine_controller_test.go
index c26f0c2e2..89a716ee2 100644
--- a/controllers/awsmachine_controller_test.go
+++ b/controllers/awsmachine_controller_test.go
@@ -71,7 +71,7 @@ var _ = Describe("AWSMachineReconciler", func() {
 				Machine: &clusterv1.Machine{
 					Spec: clusterv1.MachineSpec{
 						Bootstrap: clusterv1.Bootstrap{
-							Data: pointer.StringPtr("best pony: all of them"),
+							DataSecretName: pointer.StringPtr("bootstrap-data"),
 						},
 					},
 				},
@@ -144,15 +144,15 @@ var _ = Describe("AWSMachineReconciler", func() {
 				Expect(buf.String()).To(ContainSubstring("Cluster infrastructure is not ready yet"))
 			})
 
-			It("should exit immediately if bootstrap data isn't available", func() {
-				ms.Machine.Spec.Bootstrap.Data = nil
+			It("should exit immediately if bootstrap data secret reference isn't available", func() {
+				ms.Machine.Spec.Bootstrap.DataSecretName = nil
 
 				buf := new(bytes.Buffer)
 				klog.SetOutput(buf)
 
 				_, err := reconciler.reconcileNormal(context.Background(), ms, cs)
 				Expect(err).To(BeNil())
-				Expect(buf.String()).To(ContainSubstring("Bootstrap data is not yet available"))
+				Expect(buf.String()).To(ContainSubstring("Bootstrap data secret reference is not yet available"))
 			})
 
 			It("should return an error when we can't list instances by tags", func() {
diff --git a/pkg/cloud/services/ec2/instances_test.go b/pkg/cloud/services/ec2/instances_test.go
index be9aae578..0f0aaae2b 100644
--- a/pkg/cloud/services/ec2/instances_test.go
+++ b/pkg/cloud/services/ec2/instances_test.go
@@ -23,6 +23,7 @@ import (
 	"github.com/aws/aws-sdk-go/service/ec2"
 	"github.com/golang/mock/gomock"
 	"github.com/pkg/errors"
+	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/utils/pointer"
 	infrav1 "sigs.k8s.io/cluster-api-provider-aws/api/v1alpha3"
@@ -229,6 +230,15 @@ func TestTerminateInstance(t *testing.T) {
 }
 
 func TestCreateInstance(t *testing.T) {
+	secret := &corev1.Secret{
+		ObjectMeta: metav1.ObjectMeta{
+			Name: "bootstrap-data",
+		},
+		Data: map[string][]byte{
+			"value": []byte("data"),
+		},
+	}
+
 	testcases := []struct {
 		name          string
 		machine       clusterv1.Machine
@@ -245,8 +255,7 @@ func TestCreateInstance(t *testing.T) {
 				},
 				Spec: clusterv1.MachineSpec{
 					Bootstrap: clusterv1.Bootstrap{
-						// echo "user-data" | base64
-						Data: pointer.StringPtr("dXNlci1kYXRhCg=="),
+						DataSecretName: pointer.StringPtr("bootstrap-data"),
 					},
 				},
 			},
@@ -334,8 +343,7 @@ func TestCreateInstance(t *testing.T) {
 				},
 				Spec: clusterv1.MachineSpec{
 					Bootstrap: clusterv1.Bootstrap{
-						// echo "user-data" | base64
-						Data: pointer.StringPtr("dXNlci1kYXRhCg=="),
+						DataSecretName: pointer.StringPtr("bootstrap-data"),
 					},
 				},
 			},
@@ -443,8 +451,7 @@ func TestCreateInstance(t *testing.T) {
 				},
 				Spec: clusterv1.MachineSpec{
 					Bootstrap: clusterv1.Bootstrap{
-						// echo "user-data" | base64
-						Data: pointer.StringPtr("dXNlci1kYXRhCg=="),
+						DataSecretName: pointer.StringPtr("bootstrap-data"),
 					},
 					Version: pointer.StringPtr("v1.16.1"),
 				},
@@ -556,8 +563,7 @@ func TestCreateInstance(t *testing.T) {
 				},
 				Spec: clusterv1.MachineSpec{
 					Bootstrap: clusterv1.Bootstrap{
-						// echo "user-data" | base64
-						Data: pointer.StringPtr("dXNlci1kYXRhCg=="),
+						DataSecretName: pointer.StringPtr("bootstrap-data"),
 					},
 					Version: pointer.StringPtr("v1.16.1"),
 				},
@@ -669,8 +675,7 @@ func TestCreateInstance(t *testing.T) {
 				},
 				Spec: clusterv1.MachineSpec{
 					Bootstrap: clusterv1.Bootstrap{
-						// echo "user-data" | base64
-						Data: pointer.StringPtr("dXNlci1kYXRhCg=="),
+						DataSecretName: pointer.StringPtr("bootstrap-data"),
 					},
 					Version: pointer.StringPtr("v1.16.1"),
 				},
@@ -780,7 +785,6 @@ func TestCreateInstance(t *testing.T) {
 	for _, tc := range testcases {
 		t.Run(tc.name, func(t *testing.T) {
 			mockCtrl := gomock.NewController(t)
-			// defer mockCtrl.Finish()
 			ec2Mock := mock_ec2iface.NewMockEC2API(mockCtrl)
 			elbMock := mock_elbiface.NewMockELBAPI(mockCtrl)
 
@@ -807,6 +811,7 @@ func TestCreateInstance(t *testing.T) {
 
 			awsMachine := &infrav1.AWSMachine{
 				ObjectMeta: metav1.ObjectMeta{
+					Name: "aws-test1",
 					OwnerReferences: []metav1.OwnerReference{
 						{
 							APIVersion: clusterv1.GroupVersion.String(),
@@ -817,8 +822,10 @@ func TestCreateInstance(t *testing.T) {
 				},
 			}
 
+			client := fake.NewFakeClient(secret, cluster, machine)
+
 			machineScope, err := scope.NewMachineScope(scope.MachineScopeParams{
-				Client: fake.NewFakeClient(cluster, machine),
+				Client: client,
 				AWSClients: scope.AWSClients{
 					EC2: ec2Mock,
 					ELB: elbMock,
@@ -835,7 +842,7 @@ func TestCreateInstance(t *testing.T) {
 			tc.expect(ec2Mock.EXPECT())
 
 			clusterScope, err := scope.NewClusterScope(scope.ClusterScopeParams{
-				Client: fake.NewFakeClient(cluster, machine),
+				Client: client,
 				AWSClients: scope.AWSClients{
 					EC2: ec2Mock,
 					ELB: elbMock,
diff --git a/scripts/ci-test.sh b/scripts/ci-test.sh
index b6a3b96ff..8fde415a6 100755
--- a/scripts/ci-test.sh
+++ b/scripts/ci-test.sh
@@ -26,4 +26,4 @@ cd "${REPO_ROOT}" && \
 	source ./scripts/fetch_ext_bins.sh && \
 	fetch_tools && \
 	setup_envs && \
-	make test
+	make generate lint test