Repository: keikoproj/instance-manager (go)

Issue:
EKS: Take resource names in addition to IDs
We should accept resource names according to Name tag in addition to resource ID for the following fields:
- securityGroups
- subnets

Pull request:
Resolve security groups / subnets by Name tag
Fixes #156 

This adds support for using "Name" tag of resource instead of ID for Subnets & Security Groups if provided.

- [x] Functional test passing

Patch:
diff --git a/api/v1alpha1/instancegroup_types.go b/api/v1alpha1/instancegroup_types.go
index 9c07cb0..bf03559 100644
--- a/api/v1alpha1/instancegroup_types.go
+++ b/api/v1alpha1/instancegroup_types.go
@@ -425,6 +425,12 @@ func (c *EKSConfiguration) GetVolumes() []NodeVolume {
 func (c *EKSConfiguration) GetBootstrapArguments() string {
 	return c.BootstrapArguments
 }
+func (c *EKSConfiguration) GetSecurityGroups() []string {
+	if c.NodeSecurityGroups == nil {
+		return []string{}
+	}
+	return c.NodeSecurityGroups
+}
 func (c *EKSConfiguration) GetTags() []map[string]string {
 	if c.Tags == nil {
 		return []map[string]string{}
diff --git a/controllers/providers/aws/aws.go b/controllers/providers/aws/aws.go
index 19ea461..acdb281 100644
--- a/controllers/providers/aws/aws.go
+++ b/controllers/providers/aws/aws.go
@@ -30,6 +30,8 @@ import (
 	"github.com/aws/aws-sdk-go/aws/session"
 	"github.com/aws/aws-sdk-go/service/autoscaling"
 	"github.com/aws/aws-sdk-go/service/autoscaling/autoscalingiface"
+	"github.com/aws/aws-sdk-go/service/ec2"
+	"github.com/aws/aws-sdk-go/service/ec2/ec2iface"
 	"github.com/aws/aws-sdk-go/service/eks"
 	"github.com/aws/aws-sdk-go/service/eks/eksiface"
 	"github.com/aws/aws-sdk-go/service/iam"
@@ -45,7 +47,7 @@ var (
 )
 
 const (
-	CacheDefaultTTL                 time.Duration = time.Second * 0
+	CacheDefaultTTL                 time.Duration = 0 * time.Second
 	DescribeAutoScalingGroupsTTL    time.Duration = 60 * time.Second
 	DescribeLaunchConfigurationsTTL time.Duration = 60 * time.Second
 	ListAttachedRolePoliciesTTL     time.Duration = 60 * time.Second
@@ -53,6 +55,8 @@ const (
 	GetInstanceProfileTTL           time.Duration = 60 * time.Second
 	DescribeNodegroupTTL            time.Duration = 60 * time.Second
 	DescribeClusterTTL              time.Duration = 180 * time.Second
+	DescribeSecurityGroupsTTL       time.Duration = 180 * time.Second
+	DescribeSubnetsTTL              time.Duration = 180 * time.Second
 	CacheMaxItems                   int64         = 5000
 	CacheItemsToPrune               uint32        = 500
 )
@@ -61,6 +65,7 @@ type AwsWorker struct {
 	AsgClient  autoscalingiface.AutoScalingAPI
 	EksClient  eksiface.EKSAPI
 	IamClient  iamiface.IAMAPI
+	Ec2Client  ec2iface.EC2API
 	Parameters map[string]interface{}
 }
 
@@ -617,6 +622,84 @@ func (w *AwsWorker) compactTags(tags []map[string]string) map[string]string {
 	return compacted
 }
 
+func (w *AwsWorker) SubnetByName(name, vpc string) (*ec2.Subnet, error) {
+	subnets := []*ec2.Subnet{}
+	filteredSubnets := []*ec2.Subnet{}
+
+	err := w.Ec2Client.DescribeSubnetsPages(
+		&ec2.DescribeSubnetsInput{
+			Filters: []*ec2.Filter{
+				{
+					Name:   aws.String("vpc-id"),
+					Values: []*string{aws.String(vpc)},
+				},
+			},
+		},
+		func(page *ec2.DescribeSubnetsOutput, lastPage bool) bool {
+			for _, p := range page.Subnets {
+				subnets = append(subnets, p)
+			}
+			return page.NextToken != nil
+		},
+	)
+	if err != nil {
+		return nil, err
+	}
+
+	for _, s := range subnets {
+		for _, tag := range s.Tags {
+			k := aws.StringValue(tag.Key)
+			v := aws.StringValue(tag.Value)
+			if strings.EqualFold(k, "Name") && strings.EqualFold(v, name) {
+				filteredSubnets = append(filteredSubnets, s)
+			}
+		}
+	}
+
+	if len(filteredSubnets) == 0 {
+		return nil, nil
+	}
+	return filteredSubnets[0], nil
+}
+
+func (w *AwsWorker) SecurityGroupByName(name, vpc string) (*ec2.SecurityGroup, error) {
+	groups := []*ec2.SecurityGroup{}
+	filteredGroups := []*ec2.SecurityGroup{}
+	err := w.Ec2Client.DescribeSecurityGroupsPages(
+		&ec2.DescribeSecurityGroupsInput{
+			Filters: []*ec2.Filter{
+				{
+					Name:   aws.String("vpc-id"),
+					Values: []*string{aws.String(vpc)},
+				},
+			},
+		},
+		func(page *ec2.DescribeSecurityGroupsOutput, lastPage bool) bool {
+			for _, p := range page.SecurityGroups {
+				groups = append(groups, p)
+			}
+			return page.NextToken != nil
+		},
+	)
+	if err != nil {
+		return nil, err
+	}
+
+	for _, g := range groups {
+		for _, tag := range g.Tags {
+			k := aws.StringValue(tag.Key)
+			v := aws.StringValue(tag.Value)
+			if strings.EqualFold(k, "Name") && strings.EqualFold(v, name) {
+				filteredGroups = append(filteredGroups, g)
+			}
+		}
+	}
+	if len(filteredGroups) == 0 {
+		return nil, nil
+	}
+	return filteredGroups[0], nil
+}
+
 func (w *AwsWorker) DescribeAutoscalingGroups() ([]*autoscaling.Group, error) {
 	scalingGroups := []*autoscaling.Group{}
 	err := w.AsgClient.DescribeAutoScalingGroupsPages(&autoscaling.DescribeAutoScalingGroupsInput{}, func(page *autoscaling.DescribeAutoScalingGroupsOutput, lastPage bool) bool {
@@ -738,6 +821,29 @@ func GetAwsAsgClient(region string, cacheCfg *cache.Config, maxRetries int) auto
 	return autoscaling.New(sess)
 }
 
+// GetAwsEc2Client returns an EC2 client
+func GetAwsEc2Client(region string, cacheCfg *cache.Config, maxRetries int) ec2iface.EC2API {
+	config := aws.NewConfig().WithRegion(region).WithCredentialsChainVerboseErrors(true)
+	config = request.WithRetryer(config, NewRetryLogger(maxRetries))
+	sess, err := session.NewSession(config)
+	if err != nil {
+		panic(err)
+	}
+
+	cache.AddCaching(sess, cacheCfg)
+	cacheCfg.SetCacheTTL("ec2", "DescribeSecurityGroups", DescribeSecurityGroupsTTL)
+	cacheCfg.SetCacheTTL("ec2", "DescribeSubnets", DescribeSubnetsTTL)
+	sess.Handlers.Complete.PushFront(func(r *request.Request) {
+		ctx := r.HTTPRequest.Context()
+		log.V(1).Info("AWS API call",
+			"cacheHit", cache.IsCacheHit(ctx),
+			"service", r.ClientInfo.ServiceName,
+			"operation", r.Operation.Name,
+		)
+	})
+	return ec2.New(sess)
+}
+
 // GetAwsEksClient returns an EKS client
 func GetAwsEksClient(region string, cacheCfg *cache.Config, maxRetries int) eksiface.EKSAPI {
 	config := aws.NewConfig().WithRegion(region).WithCredentialsChainVerboseErrors(true)
diff --git a/controllers/provisioners/eks/cloud.go b/controllers/provisioners/eks/cloud.go
index 44c978d..03515d3 100644
--- a/controllers/provisioners/eks/cloud.go
+++ b/controllers/provisioners/eks/cloud.go
@@ -45,6 +45,7 @@ type DiscoveredState struct {
 	InstanceProfile               *iam.InstanceProfile
 	Publisher                     kubeprovider.EventPublisher
 	Cluster                       *eks.Cluster
+	VPCId                         string
 }
 
 func (ctx *EksInstanceGroupContext) CloudDiscovery() error {
@@ -108,6 +109,9 @@ func (ctx *EksInstanceGroupContext) CloudDiscovery() error {
 	}
 	state.SetCluster(cluster)
 
+	vpcId := aws.StringValue(cluster.ResourcesVpcConfig.VpcId)
+	state.SetVPCId(vpcId)
+
 	// find all owned scaling groups
 	ownedScalingGroups := ctx.findOwnedScalingGroups(scalingGroups)
 	state.SetOwnedScalingGroups(ownedScalingGroups)
@@ -201,6 +205,14 @@ func (d *DiscoveredState) SetCluster(cluster *eks.Cluster) {
 	d.Cluster = cluster
 }
 
+func (d *DiscoveredState) SetVPCId(id string) {
+	d.VPCId = id
+}
+
+func (d *DiscoveredState) GetVPCId() string {
+	return d.VPCId
+}
+
 func (d *DiscoveredState) GetClusterVersion() string {
 	if d.Cluster == nil {
 		return ""
diff --git a/controllers/provisioners/eks/create.go b/controllers/provisioners/eks/create.go
index cccec81..c111993 100644
--- a/controllers/provisioners/eks/create.go
+++ b/controllers/provisioners/eks/create.go
@@ -65,7 +65,6 @@ func (ctx *EksInstanceGroupContext) CreateScalingGroup(lcName string) error {
 	var (
 		instanceGroup = ctx.GetInstanceGroup()
 		spec          = instanceGroup.GetEKSSpec()
-		configuration = instanceGroup.GetEKSConfiguration()
 		state         = ctx.GetDiscoveredState()
 		asgName       = ctx.ResourcePrefix
 		tags          = ctx.GetAddedTags(asgName)
@@ -81,7 +80,7 @@ func (ctx *EksInstanceGroupContext) CreateScalingGroup(lcName string) error {
 		LaunchConfigurationName: aws.String(lcName),
 		MinSize:                 aws.Int64(spec.GetMinSize()),
 		MaxSize:                 aws.Int64(spec.GetMaxSize()),
-		VPCZoneIdentifier:       aws.String(common.ConcatenateList(configuration.GetSubnets(), ",")),
+		VPCZoneIdentifier:       aws.String(common.ConcatenateList(ctx.ResolveSubnets(), ",")),
 		Tags:                    tags,
 	})
 	if err != nil {
diff --git a/controllers/provisioners/eks/helpers.go b/controllers/provisioners/eks/helpers.go
index de751f8..34a7150 100644
--- a/controllers/provisioners/eks/helpers.go
+++ b/controllers/provisioners/eks/helpers.go
@@ -46,6 +46,7 @@ func (ctx *EksInstanceGroupContext) GetLaunchConfigurationInput(name string) *au
 		args                  = ctx.GetBootstrapArgs()
 		preScript, postScript = ctx.GetUserDataStages()
 		userData              = ctx.AwsWorker.GetBasicUserData(clusterName, args, preScript, postScript)
+		sgs                   = ctx.ResolveSecurityGroups()
 	)
 
 	input := &autoscaling.CreateLaunchConfigurationInput{
@@ -54,7 +55,7 @@ func (ctx *EksInstanceGroupContext) GetLaunchConfigurationInput(name string) *au
 		ImageId:                 aws.String(configuration.Image),
 		InstanceType:            aws.String(configuration.InstanceType),
 		KeyName:                 aws.String(configuration.KeyPairName),
-		SecurityGroups:          aws.StringSlice(configuration.NodeSecurityGroups),
+		SecurityGroups:          aws.StringSlice(sgs),
 		BlockDeviceMappings:     devices,
 		UserData:                aws.String(userData),
 	}
@@ -66,7 +67,66 @@ func (ctx *EksInstanceGroupContext) GetLaunchConfigurationInput(name string) *au
 	return input
 }
 
+func (ctx *EksInstanceGroupContext) ResolveSubnets() []string {
+	var (
+		instanceGroup = ctx.GetInstanceGroup()
+		configuration = instanceGroup.GetEKSConfiguration()
+		state         = ctx.GetDiscoveredState()
+		resolved      = make([]string, 0)
+	)
+
+	for _, s := range configuration.GetSubnets() {
+		if strings.HasPrefix(s, "subnet-") {
+			resolved = append(resolved, s)
+			continue
+		}
+
+		sn, err := ctx.AwsWorker.SubnetByName(s, state.GetVPCId())
+		if err != nil {
+			ctx.Log.Error(err, "failed to resolve subnet id by name", "subnet", s)
+			continue
+		}
+		if sn == nil {
+			ctx.Log.Error(errors.New("subnet not found"), "failed to resolve subnet by name", "subnet", s)
+			continue
+		}
+		resolved = append(resolved, aws.StringValue(sn.SubnetId))
+	}
+
+	return resolved
+}
+
+func (ctx *EksInstanceGroupContext) ResolveSecurityGroups() []string {
+	var (
+		instanceGroup = ctx.GetInstanceGroup()
+		configuration = instanceGroup.GetEKSConfiguration()
+		state         = ctx.GetDiscoveredState()
+		resolved      = make([]string, 0)
+	)
+
+	for _, g := range configuration.GetSecurityGroups() {
+		if strings.HasPrefix(g, "sg-") {
+			resolved = append(resolved, g)
+			continue
+		}
+
+		sg, err := ctx.AwsWorker.SecurityGroupByName(g, state.GetVPCId())
+		if err != nil {
+			ctx.Log.Error(err, "failed to resolve security group by name", "security-group", g)
+			continue
+		}
+		if sg == nil {
+			ctx.Log.Error(errors.New("security group not found"), "failed to resolve security group by name", "security-group", g)
+			continue
+		}
+		resolved = append(resolved, aws.StringValue(sg.GroupId))
+	}
+
+	return resolved
+}
+
 func (ctx *EksInstanceGroupContext) GetUserDataStages() ([]string, []string) {
+
 	var (
 		instanceGroup = ctx.GetInstanceGroup()
 		configuration = instanceGroup.GetEKSConfiguration()
diff --git a/controllers/provisioners/eks/update.go b/controllers/provisioners/eks/update.go
index 753f6e9..c9e0aca 100644
--- a/controllers/provisioners/eks/update.go
+++ b/controllers/provisioners/eks/update.go
@@ -84,7 +84,6 @@ func (ctx *EksInstanceGroupContext) UpdateScalingGroup() error {
 	var (
 		instanceGroup = ctx.GetInstanceGroup()
 		spec          = instanceGroup.GetEKSSpec()
-		configuration = instanceGroup.GetEKSConfiguration()
 		status        = instanceGroup.GetStatus()
 		state         = ctx.GetDiscoveredState()
 		scalingGroup  = state.GetScalingGroup()
@@ -99,7 +98,7 @@ func (ctx *EksInstanceGroupContext) UpdateScalingGroup() error {
 			LaunchConfigurationName: aws.String(state.GetActiveLaunchConfigurationName()),
 			MinSize:                 aws.Int64(spec.GetMinSize()),
 			MaxSize:                 aws.Int64(spec.GetMaxSize()),
-			VPCZoneIdentifier:       aws.String(common.ConcatenateList(configuration.GetSubnets(), ",")),
+			VPCZoneIdentifier:       aws.String(common.ConcatenateList(ctx.ResolveSubnets(), ",")),
 		})
 		if err != nil {
 			return err
@@ -186,12 +185,11 @@ func (ctx *EksInstanceGroupContext) ScalingGroupUpdateNeeded() bool {
 	var (
 		instanceGroup  = ctx.GetInstanceGroup()
 		spec           = instanceGroup.GetEKSSpec()
-		configuration  = instanceGroup.GetEKSConfiguration()
 		state          = ctx.GetDiscoveredState()
 		scalingGroup   = state.GetScalingGroup()
 		zoneIdentifier = aws.StringValue(scalingGroup.VPCZoneIdentifier)
 		groupSubnets   = strings.Split(zoneIdentifier, ",")
-		specSubnets    = configuration.GetSubnets()
+		specSubnets    = ctx.ResolveSubnets()
 	)
 
 	if state.GetActiveLaunchConfigurationName() != aws.StringValue(scalingGroup.LaunchConfigurationName) {
diff --git a/docs/EKS.md b/docs/EKS.md
index 970ba8c..4ff20a2 100644
--- a/docs/EKS.md
+++ b/docs/EKS.md
@@ -25,8 +25,8 @@ spec:
       keyPairName: <string> : must match the name of an EC2 Key Pair (required)
       image: <string> : must match the ID of an EKS AMI (required)
       instanceType: <string> : must match the type of an EC2 instance (required)
-      securityGroups: <[]string> : must match existing security group IDs (required)
-      subnets: <[]string> : must match existing subnet IDs (required)
+      securityGroups: <[]string> : must match existing security group IDs or Name (by value of tag "Name") (required)
+      subnets: <[]string> : must match existing subnet IDs or Name (by value of tag "Name") (required)
 
       # customize EBS volumes
       volumes: <[]NodeVolume> : list of NodeVolume objects
diff --git a/docs/INSTALL.md b/docs/INSTALL.md
index 3bc5ef9..55702fb 100644
--- a/docs/INSTALL.md
+++ b/docs/INSTALL.md
@@ -51,6 +51,8 @@ The below are the minimum required policies needed to run the basic operations o
 iam:GetRole
 iam:GetInstanceProfile
 iam:PassRole
+ec2:DescribeSecurityGroups
+ec2:DescribeSubnets
 autoscaling:DescribeAutoScalingGroups
 autoscaling:UpdateAutoScalingGroup
 autoscaling:TerminateInstanceInAutoScalingGroup
diff --git a/main.go b/main.go
index 80d3e04..66cdcbd 100644
--- a/main.go
+++ b/main.go
@@ -113,6 +113,7 @@ func main() {
 	cacheCfg := cache.NewConfig(aws.CacheDefaultTTL, aws.CacheMaxItems, aws.CacheItemsToPrune)
 
 	awsWorker := aws.AwsWorker{
+		Ec2Client: aws.GetAwsEc2Client(awsRegion, cacheCfg, maxAPIRetries),
 		IamClient: aws.GetAwsIamClient(awsRegion, cacheCfg, maxAPIRetries),
 		AsgClient: aws.GetAwsAsgClient(awsRegion, cacheCfg, maxAPIRetries),
 		EksClient: aws.GetAwsEksClient(awsRegion, cacheCfg, maxAPIRetries),


Test patch:
diff --git a/controllers/provisioners/eks/cloud_test.go b/controllers/provisioners/eks/cloud_test.go
index fe381a1..5df7268 100644
--- a/controllers/provisioners/eks/cloud_test.go
+++ b/controllers/provisioners/eks/cloud_test.go
@@ -22,6 +22,7 @@ import (
 
 	"github.com/aws/aws-sdk-go/aws"
 	"github.com/aws/aws-sdk-go/service/autoscaling"
+	"github.com/aws/aws-sdk-go/service/eks"
 	"github.com/aws/aws-sdk-go/service/iam"
 	"github.com/keikoproj/instance-manager/controllers/provisioners"
 	"github.com/onsi/gomega"
@@ -35,9 +36,10 @@ func TestCloudDiscoveryPositive(t *testing.T) {
 		asgMock = NewAutoScalingMocker()
 		iamMock = NewIamMocker()
 		eksMock = NewEksMocker()
+		ec2Mock = NewEc2Mocker()
 	)
 
-	w := MockAwsWorker(asgMock, iamMock, eksMock)
+	w := MockAwsWorker(asgMock, iamMock, eksMock, ec2Mock)
 	ctx := MockContext(ig, k, w)
 	state := ctx.GetDiscoveredState()
 	status := ig.GetStatus()
@@ -58,6 +60,7 @@ func TestCloudDiscoveryPositive(t *testing.T) {
 		resourceNamespace     = "default"
 		launchConfigName      = "some-launch-configuration"
 		ownedScalingGroupName = "scaling-group-1"
+		vpcId                 = "vpc-1234567890"
 		ownershipTag          = MockTagDescription(provisioners.TagClusterName, clusterName)
 		nameTag               = MockTagDescription(provisioners.TagInstanceGroupName, resourceName)
 		namespaceTag          = MockTagDescription(provisioners.TagInstanceGroupNamespace, resourceNamespace)
@@ -81,6 +84,12 @@ func TestCloudDiscoveryPositive(t *testing.T) {
 		launchConfig,
 	}
 
+	eksMock.EksCluster = &eks.Cluster{
+		ResourcesVpcConfig: &eks.VpcConfigResponse{
+			VpcId: aws.String(vpcId),
+		},
+	}
+
 	err := ctx.CloudDiscovery()
 	g.Expect(err).NotTo(gomega.HaveOccurred())
 	g.Expect(state.GetRole()).To(gomega.Equal(iamMock.Role))
@@ -90,6 +99,7 @@ func TestCloudDiscoveryPositive(t *testing.T) {
 	g.Expect(state.GetScalingGroup()).To(gomega.Equal(ownedScalingGroup))
 	g.Expect(state.GetLaunchConfiguration()).To(gomega.Equal(launchConfig))
 	g.Expect(state.GetActiveLaunchConfigurationName()).To(gomega.Equal(launchConfigName))
+	g.Expect(state.GetVPCId()).To(gomega.Equal(vpcId))
 	g.Expect(status.GetNodesArn()).To(gomega.Equal(aws.StringValue(iamMock.Role.Arn)))
 	g.Expect(status.GetActiveScalingGroupName()).To(gomega.Equal(ownedScalingGroupName))
 	g.Expect(status.GetActiveLaunchConfigurationName()).To(gomega.Equal(launchConfigName))
@@ -105,9 +115,10 @@ func TestCloudDiscoveryExistingRole(t *testing.T) {
 		asgMock = NewAutoScalingMocker()
 		iamMock = NewIamMocker()
 		eksMock = NewEksMocker()
+		ec2Mock = NewEc2Mocker()
 	)
 
-	w := MockAwsWorker(asgMock, iamMock, eksMock)
+	w := MockAwsWorker(asgMock, iamMock, eksMock, ec2Mock)
 	ctx := MockContext(ig, k, w)
 	configuration := ig.GetEKSConfiguration()
 	state := ctx.GetDiscoveredState()
@@ -138,9 +149,10 @@ func TestCloudDiscoverySpotPrice(t *testing.T) {
 		asgMock = NewAutoScalingMocker()
 		iamMock = NewIamMocker()
 		eksMock = NewEksMocker()
+		ec2Mock = NewEc2Mocker()
 	)
 
-	w := MockAwsWorker(asgMock, iamMock, eksMock)
+	w := MockAwsWorker(asgMock, iamMock, eksMock, ec2Mock)
 	ctx := MockContext(ig, k, w)
 	status := ig.GetStatus()
 	configuration := ig.GetEKSConfiguration()
@@ -215,9 +227,10 @@ func TestLaunchConfigDeletion(t *testing.T) {
 		asgMock = NewAutoScalingMocker()
 		iamMock = NewIamMocker()
 		eksMock = NewEksMocker()
+		ec2Mock = NewEc2Mocker()
 	)
 
-	w := MockAwsWorker(asgMock, iamMock, eksMock)
+	w := MockAwsWorker(asgMock, iamMock, eksMock, ec2Mock)
 	ctx := MockContext(ig, k, w)
 	configuration := ig.GetEKSConfiguration()
 
diff --git a/controllers/provisioners/eks/create_test.go b/controllers/provisioners/eks/create_test.go
index adde1be..c3280c5 100644
--- a/controllers/provisioners/eks/create_test.go
+++ b/controllers/provisioners/eks/create_test.go
@@ -40,9 +40,10 @@ func TestCreateManagedRolePositive(t *testing.T) {
 		asgMock = NewAutoScalingMocker()
 		iamMock = NewIamMocker()
 		eksMock = NewEksMocker()
+		ec2Mock = NewEc2Mocker()
 	)
 
-	w := MockAwsWorker(asgMock, iamMock, eksMock)
+	w := MockAwsWorker(asgMock, iamMock, eksMock, ec2Mock)
 	ctx := MockContext(ig, k, w)
 	state := ctx.GetDiscoveredState()
 	state.SetCluster(&eks.Cluster{Version: aws.String("1.15")})
@@ -76,9 +77,10 @@ func TestCreateLaunchConfigurationPositive(t *testing.T) {
 		asgMock = NewAutoScalingMocker()
 		iamMock = NewIamMocker()
 		eksMock = NewEksMocker()
+		ec2Mock = NewEc2Mocker()
 	)
 
-	w := MockAwsWorker(asgMock, iamMock, eksMock)
+	w := MockAwsWorker(asgMock, iamMock, eksMock, ec2Mock)
 	ctx := MockContext(ig, k, w)
 
 	// Skip role creation
@@ -118,9 +120,10 @@ func TestCreateScalingGroupPositive(t *testing.T) {
 		asgMock = NewAutoScalingMocker()
 		iamMock = NewIamMocker()
 		eksMock = NewEksMocker()
+		ec2Mock = NewEc2Mocker()
 	)
 
-	w := MockAwsWorker(asgMock, iamMock, eksMock)
+	w := MockAwsWorker(asgMock, iamMock, eksMock, ec2Mock)
 	ctx := MockContext(ig, k, w)
 
 	// skip role creation
@@ -159,9 +162,10 @@ func TestCreateNoOp(t *testing.T) {
 		asgMock = NewAutoScalingMocker()
 		iamMock = NewIamMocker()
 		eksMock = NewEksMocker()
+		ec2Mock = NewEc2Mocker()
 	)
 
-	w := MockAwsWorker(asgMock, iamMock, eksMock)
+	w := MockAwsWorker(asgMock, iamMock, eksMock, ec2Mock)
 	ctx := MockContext(ig, k, w)
 
 	// skip role creation
@@ -199,9 +203,10 @@ func TestCreateManagedRoleNegative(t *testing.T) {
 		asgMock = NewAutoScalingMocker()
 		iamMock = NewIamMocker()
 		eksMock = NewEksMocker()
+		ec2Mock = NewEc2Mocker()
 	)
 
-	w := MockAwsWorker(asgMock, iamMock, eksMock)
+	w := MockAwsWorker(asgMock, iamMock, eksMock, ec2Mock)
 	ctx := MockContext(ig, k, w)
 
 	// Mock role/profile do not exist so they are always created
@@ -247,9 +252,10 @@ func TestCreateLaunchConfigNegative(t *testing.T) {
 		asgMock = NewAutoScalingMocker()
 		iamMock = NewIamMocker()
 		eksMock = NewEksMocker()
+		ec2Mock = NewEc2Mocker()
 	)
 
-	w := MockAwsWorker(asgMock, iamMock, eksMock)
+	w := MockAwsWorker(asgMock, iamMock, eksMock, ec2Mock)
 	ctx := MockContext(ig, k, w)
 
 	ig.GetEKSConfiguration().SetRoleName("some-role")
@@ -287,9 +293,10 @@ func TestCreateAutoScalingGroupNegative(t *testing.T) {
 		asgMock = NewAutoScalingMocker()
 		iamMock = NewIamMocker()
 		eksMock = NewEksMocker()
+		ec2Mock = NewEc2Mocker()
 	)
 
-	w := MockAwsWorker(asgMock, iamMock, eksMock)
+	w := MockAwsWorker(asgMock, iamMock, eksMock, ec2Mock)
 	ctx := MockContext(ig, k, w)
 
 	ig.GetEKSConfiguration().SetRoleName("some-role")
diff --git a/controllers/provisioners/eks/delete_test.go b/controllers/provisioners/eks/delete_test.go
index 74ba035..65aaa40 100644
--- a/controllers/provisioners/eks/delete_test.go
+++ b/controllers/provisioners/eks/delete_test.go
@@ -39,9 +39,10 @@ func TestDeletePositive(t *testing.T) {
 		asgMock = NewAutoScalingMocker()
 		iamMock = NewIamMocker()
 		eksMock = NewEksMocker()
+		ec2Mock = NewEc2Mocker()
 	)
 
-	w := MockAwsWorker(asgMock, iamMock, eksMock)
+	w := MockAwsWorker(asgMock, iamMock, eksMock, ec2Mock)
 	ctx := MockContext(ig, k, w)
 
 	ctx.SetDiscoveredState(&DiscoveredState{
@@ -67,9 +68,10 @@ func TestDeleteManagedRoleNegative(t *testing.T) {
 		asgMock       = NewAutoScalingMocker()
 		iamMock       = NewIamMocker()
 		eksMock       = NewEksMocker()
+		ec2Mock       = NewEc2Mocker()
 	)
 
-	w := MockAwsWorker(asgMock, iamMock, eksMock)
+	w := MockAwsWorker(asgMock, iamMock, eksMock, ec2Mock)
 	ctx := MockContext(ig, k, w)
 
 	ctx.SetDiscoveredState(&DiscoveredState{
@@ -99,9 +101,10 @@ func TestDeleteLaunchConfigurationNegative(t *testing.T) {
 		asgMock = NewAutoScalingMocker()
 		iamMock = NewIamMocker()
 		eksMock = NewEksMocker()
+		ec2Mock = NewEc2Mocker()
 	)
 
-	w := MockAwsWorker(asgMock, iamMock, eksMock)
+	w := MockAwsWorker(asgMock, iamMock, eksMock, ec2Mock)
 	ctx := MockContext(ig, k, w)
 
 	ctx.SetDiscoveredState(&DiscoveredState{
@@ -129,9 +132,10 @@ func TestDeleteAutoScalingGroupNegative(t *testing.T) {
 		asgMock = NewAutoScalingMocker()
 		iamMock = NewIamMocker()
 		eksMock = NewEksMocker()
+		ec2Mock = NewEc2Mocker()
 	)
 
-	w := MockAwsWorker(asgMock, iamMock, eksMock)
+	w := MockAwsWorker(asgMock, iamMock, eksMock, ec2Mock)
 	ctx := MockContext(ig, k, w)
 
 	ctx.SetDiscoveredState(&DiscoveredState{
@@ -157,9 +161,10 @@ func TestRemoveAuthRoleNegative(t *testing.T) {
 		asgMock = NewAutoScalingMocker()
 		iamMock = NewIamMocker()
 		eksMock = NewEksMocker()
+		ec2Mock = NewEc2Mocker()
 	)
 
-	w := MockAwsWorker(asgMock, iamMock, eksMock)
+	w := MockAwsWorker(asgMock, iamMock, eksMock, ec2Mock)
 	ctx := MockContext(ig, k, w)
 
 	// two instancegroups with same role arn
diff --git a/controllers/provisioners/eks/eks_test.go b/controllers/provisioners/eks/eks_test.go
index 54a140c..4a83831 100644
--- a/controllers/provisioners/eks/eks_test.go
+++ b/controllers/provisioners/eks/eks_test.go
@@ -23,6 +23,8 @@ import (
 	"github.com/aws/aws-sdk-go/aws"
 	"github.com/aws/aws-sdk-go/service/autoscaling"
 	"github.com/aws/aws-sdk-go/service/autoscaling/autoscalingiface"
+	"github.com/aws/aws-sdk-go/service/ec2"
+	"github.com/aws/aws-sdk-go/service/ec2/ec2iface"
 	"github.com/aws/aws-sdk-go/service/eks"
 	"github.com/aws/aws-sdk-go/service/eks/eksiface"
 	"github.com/aws/aws-sdk-go/service/iam"
@@ -61,11 +63,21 @@ func NewIamMocker() *MockIamClient {
 }
 
 func NewEksMocker() *MockEksClient {
-	return &MockEksClient{}
+	mock := &MockEksClient{
+		EksCluster: &eks.Cluster{
+			ResourcesVpcConfig: &eks.VpcConfigResponse{},
+		},
+	}
+	return mock
+}
+
+func NewEc2Mocker() *MockEc2Client {
+	return &MockEc2Client{}
 }
 
-func MockAwsWorker(asgClient *MockAutoScalingClient, iamClient *MockIamClient, eksClient *MockEksClient) awsprovider.AwsWorker {
+func MockAwsWorker(asgClient *MockAutoScalingClient, iamClient *MockIamClient, eksClient *MockEksClient, ec2Client *MockEc2Client) awsprovider.AwsWorker {
 	return awsprovider.AwsWorker{
+		Ec2Client: ec2Client,
 		AsgClient: asgClient,
 		IamClient: iamClient,
 		EksClient: eksClient,
@@ -195,6 +207,36 @@ func MockScalingGroup(name string, t ...*autoscaling.TagDescription) *autoscalin
 	}
 }
 
+func MockSecurityGroup(id string, withTag bool, name string) *ec2.SecurityGroup {
+	sg := &ec2.SecurityGroup{
+		GroupId: aws.String(id),
+	}
+	if withTag {
+		sg.Tags = []*ec2.Tag{
+			{
+				Key:   aws.String("Name"),
+				Value: aws.String(name),
+			},
+		}
+	}
+	return sg
+}
+
+func MockSubnet(id string, withTag bool, name string) *ec2.Subnet {
+	sn := &ec2.Subnet{
+		SubnetId: aws.String(id),
+	}
+	if withTag {
+		sn.Tags = []*ec2.Tag{
+			{
+				Key:   aws.String("Name"),
+				Value: aws.String(name),
+			},
+		}
+	}
+	return sn
+}
+
 func MockAwsCRDStrategy(spec string) v1alpha1.AwsUpgradeStrategy {
 	return v1alpha1.AwsUpgradeStrategy{
 		Type: kubeprovider.CRDStrategyName,
@@ -380,6 +422,40 @@ func (a *MockAutoScalingClient) ResumeProcesses(input *autoscaling.ScalingProces
 	return &autoscaling.ResumeProcessesOutput{}, a.UpdateSuspendProcessesErr
 }
 
+type MockEc2Client struct {
+	ec2iface.EC2API
+	DescribeSubnetsErr        error
+	DescribeSecurityGroupsErr error
+	Subnets                   []*ec2.Subnet
+	SecurityGroups            []*ec2.SecurityGroup
+}
+
+func (c *MockEc2Client) DescribeSecurityGroupsPages(input *ec2.DescribeSecurityGroupsInput, callback func(*ec2.DescribeSecurityGroupsOutput, bool) bool) error {
+	page, err := c.DescribeSecurityGroups(input)
+	if err != nil {
+		return err
+	}
+	callback(page, false)
+	return nil
+}
+
+func (c *MockEc2Client) DescribeSubnetsPages(input *ec2.DescribeSubnetsInput, callback func(*ec2.DescribeSubnetsOutput, bool) bool) error {
+	page, err := c.DescribeSubnets(input)
+	if err != nil {
+		return err
+	}
+	callback(page, false)
+	return nil
+}
+
+func (c *MockEc2Client) DescribeSecurityGroups(input *ec2.DescribeSecurityGroupsInput) (*ec2.DescribeSecurityGroupsOutput, error) {
+	return &ec2.DescribeSecurityGroupsOutput{SecurityGroups: c.SecurityGroups}, c.DescribeSecurityGroupsErr
+}
+
+func (c *MockEc2Client) DescribeSubnets(input *ec2.DescribeSubnetsInput) (*ec2.DescribeSubnetsOutput, error) {
+	return &ec2.DescribeSubnetsOutput{Subnets: c.Subnets}, c.DescribeSubnetsErr
+}
+
 type MockEksClient struct {
 	eksiface.EKSAPI
 	DescribeClusterErr error
diff --git a/controllers/provisioners/eks/helpers_test.go b/controllers/provisioners/eks/helpers_test.go
index c96eda4..7941d4c 100644
--- a/controllers/provisioners/eks/helpers_test.go
+++ b/controllers/provisioners/eks/helpers_test.go
@@ -22,13 +22,97 @@ import (
 
 	"github.com/aws/aws-sdk-go/aws"
 	"github.com/aws/aws-sdk-go/service/autoscaling"
+	"github.com/aws/aws-sdk-go/service/ec2"
 	"github.com/aws/aws-sdk-go/service/eks"
 	"github.com/keikoproj/instance-manager/api/v1alpha1"
 	awsprovider "github.com/keikoproj/instance-manager/controllers/providers/aws"
 	kubeprovider "github.com/keikoproj/instance-manager/controllers/providers/kubernetes"
 	"github.com/onsi/gomega"
+	"github.com/pkg/errors"
 )
 
+func TestResolveSecurityGroups(t *testing.T) {
+	var (
+		g       = gomega.NewGomegaWithT(t)
+		k       = MockKubernetesClientSet()
+		ig      = MockInstanceGroup()
+		config  = ig.GetEKSConfiguration()
+		asgMock = NewAutoScalingMocker()
+		iamMock = NewIamMocker()
+		eksMock = NewEksMocker()
+		ec2Mock = NewEc2Mocker()
+	)
+
+	w := MockAwsWorker(asgMock, iamMock, eksMock, ec2Mock)
+	ctx := MockContext(ig, k, w)
+
+	tests := []struct {
+		requested []string
+		groups    []*ec2.SecurityGroup
+		result    []string
+		withErr   bool
+	}{
+		{requested: []string{"sg-111", "sg-222"}, groups: []*ec2.SecurityGroup{MockSecurityGroup("sg-111", false, ""), MockSecurityGroup("sg-222", false, "")}, result: []string{"sg-111", "sg-222"}, withErr: false},
+		{requested: []string{"my-sg-1", "sg-222"}, groups: []*ec2.SecurityGroup{MockSecurityGroup("sg-111", true, "my-sg-1"), MockSecurityGroup("sg-222", false, "")}, result: []string{"sg-111", "sg-222"}, withErr: false},
+		{requested: []string{"my-sg-1", "my-sg-2"}, groups: []*ec2.SecurityGroup{MockSecurityGroup("sg-111", true, "my-sg-1"), MockSecurityGroup("sg-222", true, "my-sg-2")}, result: []string{"sg-111", "sg-222"}, withErr: false},
+		{requested: []string{"my-sg-1"}, groups: []*ec2.SecurityGroup{MockSecurityGroup("sg-111", true, "my-sg-1")}, result: []string{}, withErr: true},
+		{requested: []string{"my-sg-1", "my-sg-2"}, groups: []*ec2.SecurityGroup{MockSecurityGroup("sg-111", true, "my-sg-2")}, result: []string{"sg-111"}, withErr: false},
+	}
+
+	for i, tc := range tests {
+		t.Logf("Test #%v - %+v", i, tc)
+		config.NodeSecurityGroups = tc.requested
+		ec2Mock.DescribeSecurityGroupsErr = nil
+		ec2Mock.SecurityGroups = tc.groups
+		if tc.withErr {
+			ec2Mock.DescribeSecurityGroupsErr = errors.New("an error occured")
+		}
+		groups := ctx.ResolveSecurityGroups()
+		g.Expect(groups).To(gomega.Equal(tc.result))
+	}
+}
+
+func TestResolveSubnets(t *testing.T) {
+	var (
+		g       = gomega.NewGomegaWithT(t)
+		k       = MockKubernetesClientSet()
+		ig      = MockInstanceGroup()
+		config  = ig.GetEKSConfiguration()
+		asgMock = NewAutoScalingMocker()
+		iamMock = NewIamMocker()
+		eksMock = NewEksMocker()
+		ec2Mock = NewEc2Mocker()
+	)
+
+	w := MockAwsWorker(asgMock, iamMock, eksMock, ec2Mock)
+	ctx := MockContext(ig, k, w)
+
+	tests := []struct {
+		requested []string
+		subnets   []*ec2.Subnet
+		result    []string
+		withErr   bool
+	}{
+		{requested: []string{"subnet-111", "subnet-222"}, subnets: []*ec2.Subnet{MockSubnet("subnet-111", false, ""), MockSubnet("subnet-222", false, "")}, result: []string{"subnet-111", "subnet-222"}, withErr: false},
+		{requested: []string{"my-subnet-1", "subnet-222"}, subnets: []*ec2.Subnet{MockSubnet("subnet-111", true, "my-subnet-1"), MockSubnet("subnet-222", false, "")}, result: []string{"subnet-111", "subnet-222"}, withErr: false},
+		{requested: []string{"my-subnet-1", "my-subnet-2"}, subnets: []*ec2.Subnet{MockSubnet("subnet-111", true, "my-subnet-1"), MockSubnet("subnet-222", true, "my-subnet-2")}, result: []string{"subnet-111", "subnet-222"}, withErr: false},
+		{requested: []string{"my-subnet-1"}, subnets: []*ec2.Subnet{MockSubnet("subnet-111", true, "my-subnet-1")}, result: []string{}, withErr: true},
+		{requested: []string{"my-subnet-1", "my-subnet-2"}, subnets: []*ec2.Subnet{MockSubnet("subnet-111", true, "my-subnet-2")}, result: []string{"subnet-111"}, withErr: false},
+	}
+
+	for i, tc := range tests {
+		t.Logf("Test #%v - %+v", i, tc)
+		config.Subnets = tc.requested
+		ec2Mock.Subnets = tc.subnets
+		ec2Mock.DescribeSubnetsErr = nil
+		if tc.withErr {
+			ec2Mock.DescribeSubnetsErr = errors.New("an error occured")
+		}
+		groups := ctx.ResolveSubnets()
+		g.Expect(groups).To(gomega.Equal(tc.result))
+	}
+}
+
 func TestGetDisabledMetrics(t *testing.T) {
 	var (
 		g       = gomega.NewGomegaWithT(t)
@@ -37,9 +121,10 @@ func TestGetDisabledMetrics(t *testing.T) {
 		asgMock = NewAutoScalingMocker()
 		iamMock = NewIamMocker()
 		eksMock = NewEksMocker()
+		ec2Mock = NewEc2Mocker()
 	)
 
-	w := MockAwsWorker(asgMock, iamMock, eksMock)
+	w := MockAwsWorker(asgMock, iamMock, eksMock, ec2Mock)
 	ctx := MockContext(ig, k, w)
 
 	// No disable required
@@ -96,9 +181,10 @@ func TestGetEnabledMetrics(t *testing.T) {
 		asgMock = NewAutoScalingMocker()
 		iamMock = NewIamMocker()
 		eksMock = NewEksMocker()
+		ec2Mock = NewEc2Mocker()
 	)
 
-	w := MockAwsWorker(asgMock, iamMock, eksMock)
+	w := MockAwsWorker(asgMock, iamMock, eksMock, ec2Mock)
 	ctx := MockContext(ig, k, w)
 
 	// Enable all metrics
@@ -141,6 +227,7 @@ func TestGetLabelList(t *testing.T) {
 		asgMock                    = NewAutoScalingMocker()
 		iamMock                    = NewIamMocker()
 		eksMock                    = NewEksMocker()
+		ec2Mock                    = NewEc2Mocker()
 		expectedLabels115          = []string{"node-role.kubernetes.io/instance-group-1=\"\"", "node.kubernetes.io/role=instance-group-1"}
 		expectedLabels116          = []string{"node.kubernetes.io/role=instance-group-1"}
 		expectedLabelsWithCustom   = []string{"custom.kubernetes.io=customlabel", "node.kubernetes.io/role=instance-group-1"}
@@ -150,7 +237,7 @@ func TestGetLabelList(t *testing.T) {
 		defaultLifecycleLable      = "instancemgr.keikoproj.io/lifecycle=normal"
 	)
 
-	w := MockAwsWorker(asgMock, iamMock, eksMock)
+	w := MockAwsWorker(asgMock, iamMock, eksMock, ec2Mock)
 	ctx := MockContext(ig, k, w)
 
 	tests := []struct {
@@ -204,9 +291,10 @@ func TestGetUserDataStages(t *testing.T) {
 		asgMock       = NewAutoScalingMocker()
 		iamMock       = NewIamMocker()
 		eksMock       = NewEksMocker()
+		ec2Mock       = NewEc2Mocker()
 	)
 
-	w := MockAwsWorker(asgMock, iamMock, eksMock)
+	w := MockAwsWorker(asgMock, iamMock, eksMock, ec2Mock)
 	ctx := MockContext(ig, k, w)
 
 	tests := []struct {
diff --git a/controllers/provisioners/eks/state_test.go b/controllers/provisioners/eks/state_test.go
index 6003cbc..dcb4a01 100644
--- a/controllers/provisioners/eks/state_test.go
+++ b/controllers/provisioners/eks/state_test.go
@@ -35,9 +35,10 @@ func TestStateDiscovery(t *testing.T) {
 		asgMock = NewAutoScalingMocker()
 		iamMock = NewIamMocker()
 		eksMock = NewEksMocker()
+		ec2Mock = NewEc2Mocker()
 	)
 
-	w := MockAwsWorker(asgMock, iamMock, eksMock)
+	w := MockAwsWorker(asgMock, iamMock, eksMock, ec2Mock)
 	ctx := MockContext(ig, k, w)
 
 	tests := []struct {
@@ -85,9 +86,10 @@ func TestIsReady(t *testing.T) {
 		asgMock = NewAutoScalingMocker()
 		iamMock = NewIamMocker()
 		eksMock = NewEksMocker()
+		ec2Mock = NewEc2Mocker()
 	)
 
-	w := MockAwsWorker(asgMock, iamMock, eksMock)
+	w := MockAwsWorker(asgMock, iamMock, eksMock, ec2Mock)
 	ctx := MockContext(ig, k, w)
 
 	tests := []struct {
diff --git a/controllers/provisioners/eks/update_test.go b/controllers/provisioners/eks/update_test.go
index 899a0c1..7a0cddd 100644
--- a/controllers/provisioners/eks/update_test.go
+++ b/controllers/provisioners/eks/update_test.go
@@ -39,9 +39,10 @@ func TestUpdateScalingGroupPositive(t *testing.T) {
 		asgMock = NewAutoScalingMocker()
 		iamMock = NewIamMocker()
 		eksMock = NewEksMocker()
+		ec2Mock = NewEc2Mocker()
 	)
 
-	w := MockAwsWorker(asgMock, iamMock, eksMock)
+	w := MockAwsWorker(asgMock, iamMock, eksMock, ec2Mock)
 	ctx := MockContext(ig, k, w)
 
 	ctx.SetDiscoveredState(&DiscoveredState{
@@ -137,9 +138,10 @@ func TestUpdateWithDriftRotationPositive(t *testing.T) {
 		asgMock = NewAutoScalingMocker()
 		iamMock = NewIamMocker()
 		eksMock = NewEksMocker()
+		ec2Mock = NewEc2Mocker()
 	)
 
-	w := MockAwsWorker(asgMock, iamMock, eksMock)
+	w := MockAwsWorker(asgMock, iamMock, eksMock, ec2Mock)
 	ctx := MockContext(ig, k, w)
 
 	mockScalingGroup := &autoscaling.Group{
@@ -210,9 +212,10 @@ func TestUpdateWithRotationPositive(t *testing.T) {
 		asgMock = NewAutoScalingMocker()
 		iamMock = NewIamMocker()
 		eksMock = NewEksMocker()
+		ec2Mock = NewEc2Mocker()
 	)
 
-	w := MockAwsWorker(asgMock, iamMock, eksMock)
+	w := MockAwsWorker(asgMock, iamMock, eksMock, ec2Mock)
 	ctx := MockContext(ig, k, w)
 
 	ctx.SetDiscoveredState(&DiscoveredState{
@@ -287,9 +290,10 @@ func TestLaunchConfigurationDrifted(t *testing.T) {
 		asgMock = NewAutoScalingMocker()
 		iamMock = NewIamMocker()
 		eksMock = NewEksMocker()
+		ec2Mock = NewEc2Mocker()
 	)
 
-	w := MockAwsWorker(asgMock, iamMock, eksMock)
+	w := MockAwsWorker(asgMock, iamMock, eksMock, ec2Mock)
 	ctx := MockContext(ig, k, w)
 
 	ctx.SetDiscoveredState(&DiscoveredState{
@@ -363,9 +367,10 @@ func TestUpdateScalingGroupNegative(t *testing.T) {
 		asgMock = NewAutoScalingMocker()
 		iamMock = NewIamMocker()
 		eksMock = NewEksMocker()
+		ec2Mock = NewEc2Mocker()
 	)
 
-	w := MockAwsWorker(asgMock, iamMock, eksMock)
+	w := MockAwsWorker(asgMock, iamMock, eksMock, ec2Mock)
 	ctx := MockContext(ig, k, w)
 	ig.GetEKSConfiguration().SetMetricsCollection([]string{"GroupMinSize", "GroupMaxSize", "GroupDesiredCapacity"})
 
@@ -436,9 +441,10 @@ func TestScalingGroupUpdatePredicate(t *testing.T) {
 		asgMock       = NewAutoScalingMocker()
 		iamMock       = NewIamMocker()
 		eksMock       = NewEksMocker()
+		ec2Mock       = NewEc2Mocker()
 	)
 
-	w := MockAwsWorker(asgMock, iamMock, eksMock)
+	w := MockAwsWorker(asgMock, iamMock, eksMock, ec2Mock)
 	ctx := MockContext(ig, k, w)
 	spec.MinSize = int64(3)
 	spec.MaxSize = int64(6)
@@ -486,9 +492,10 @@ func TestUpdateManagedPolicies(t *testing.T) {
 		asgMock       = NewAutoScalingMocker()
 		iamMock       = NewIamMocker()
 		eksMock       = NewEksMocker()
+		ec2Mock       = NewEc2Mocker()
 	)
 
-	w := MockAwsWorker(asgMock, iamMock, eksMock)
+	w := MockAwsWorker(asgMock, iamMock, eksMock, ec2Mock)
 	ctx := MockContext(ig, k, w)
 
 	tests := []struct {
diff --git a/controllers/provisioners/eks/upgrade_test.go b/controllers/provisioners/eks/upgrade_test.go
index 620d368..4da1995 100644
--- a/controllers/provisioners/eks/upgrade_test.go
+++ b/controllers/provisioners/eks/upgrade_test.go
@@ -112,9 +112,10 @@ func TestUpgradeInvalidStrategy(t *testing.T) {
 		asgMock = NewAutoScalingMocker()
 		iamMock = NewIamMocker()
 		eksMock = NewEksMocker()
+		ec2Mock = NewEc2Mocker()
 	)
 
-	w := MockAwsWorker(asgMock, iamMock, eksMock)
+	w := MockAwsWorker(asgMock, iamMock, eksMock, ec2Mock)
 	ctx := MockContext(ig, k, w)
 
 	// assume initial state of modifying
@@ -134,9 +135,10 @@ func TestBootstrapNodes(t *testing.T) {
 		asgMock = NewAutoScalingMocker()
 		iamMock = NewIamMocker()
 		eksMock = NewEksMocker()
+		ec2Mock = NewEc2Mocker()
 	)
 
-	w := MockAwsWorker(asgMock, iamMock, eksMock)
+	w := MockAwsWorker(asgMock, iamMock, eksMock, ec2Mock)
 	ctx := MockContext(ig, k, w)
 
 	// assume initial state of modifying
@@ -155,9 +157,10 @@ func TestUpgradeCRDStrategy(t *testing.T) {
 		asgMock = NewAutoScalingMocker()
 		iamMock = NewIamMocker()
 		eksMock = NewEksMocker()
+		ec2Mock = NewEc2Mocker()
 	)
 
-	w := MockAwsWorker(asgMock, iamMock, eksMock)
+	w := MockAwsWorker(asgMock, iamMock, eksMock, ec2Mock)
 	ctx := MockContext(ig, k, w)
 	ctx.SetDiscoveredState(&DiscoveredState{
 		Publisher: kubeprovider.EventPublisher{
@@ -219,9 +222,10 @@ func TestUpgradeRollingUpdateStrategyPositive(t *testing.T) {
 		asgMock = NewAutoScalingMocker()
 		iamMock = NewIamMocker()
 		eksMock = NewEksMocker()
+		ec2Mock = NewEc2Mocker()
 	)
 
-	w := MockAwsWorker(asgMock, iamMock, eksMock)
+	w := MockAwsWorker(asgMock, iamMock, eksMock, ec2Mock)
 	ctx := MockContext(ig, k, w)
 
 	tests := []struct {