Skip to content

Commit

Permalink
Move functions dealing with instances under instances.go file
Browse files Browse the repository at this point in the history
  • Loading branch information
ingvagabund committed Nov 27, 2018
1 parent 3948ae6 commit 7a54ec0
Show file tree
Hide file tree
Showing 4 changed files with 253 additions and 228 deletions.
152 changes: 1 addition & 151 deletions pkg/cloud/aws/actuators/machine/actuator.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,21 +82,6 @@ type codec interface {
EncodeProviderStatus(runtime.Object) (*runtime.RawExtension, error)
}

// Scan machine tags, and return a deduped tags list
func removeDuplicatedTags(tags []*ec2.Tag) []*ec2.Tag {
m := make(map[string]bool)
result := []*ec2.Tag{}

// look for duplicates
for _, entry := range tags {
if _, value := m[*entry.Key]; !value {
m[*entry.Key] = true
result = append(result, entry)
}
}
return result
}

// NewActuator returns a new AWS Actuator
func NewActuator(params ActuatorParams) (*Actuator, error) {
actuator := &Actuator{
Expand Down Expand Up @@ -178,141 +163,6 @@ func (a *Actuator) updateMachineProviderConditions(machine *clusterv1.Machine, c
return nil
}

// removeStoppedMachine removes all instances of a specific machine that are in a stopped state.
func (a *Actuator) removeStoppedMachine(machine *clusterv1.Machine, client awsclient.Client) error {
instances, err := GetStoppedInstances(machine, client)
if err != nil {
glog.Errorf("error getting stopped instances: %v", err)
return fmt.Errorf("error getting stopped instances: %v", err)
}

if len(instances) == 0 {
glog.Infof("no stopped instances found for machine %v", machine.Name)
return nil
}

return TerminateInstances(client, instances)
}

func buildEC2Filters(inputFilters []providerconfigv1.Filter) []*ec2.Filter {
filters := make([]*ec2.Filter, len(inputFilters))
for i, f := range inputFilters {
values := make([]*string, len(f.Values))
for j, v := range f.Values {
values[j] = aws.String(v)
}
filters[i] = &ec2.Filter{
Name: aws.String(f.Name),
Values: values,
}
}
return filters
}

func getSecurityGroupsIDs(securityGroups []providerconfigv1.AWSResourceReference, client awsclient.Client) ([]*string, error) {
var securityGroupIDs []*string
for _, g := range securityGroups {
// ID has priority
if g.ID != nil {
securityGroupIDs = append(securityGroupIDs, g.ID)
} else if g.Filters != nil {
glog.Info("Describing security groups based on filters")
// Get groups based on filters
describeSecurityGroupsRequest := ec2.DescribeSecurityGroupsInput{
Filters: buildEC2Filters(g.Filters),
}
describeSecurityGroupsResult, err := client.DescribeSecurityGroups(&describeSecurityGroupsRequest)
if err != nil {
glog.Errorf("error describing security groups: %v", err)
return nil, fmt.Errorf("error describing security groups: %v", err)
}
for _, g := range describeSecurityGroupsResult.SecurityGroups {
groupID := *g.GroupId
securityGroupIDs = append(securityGroupIDs, &groupID)
}
}
}

if len(securityGroups) == 0 {
glog.Info("No security group found")
}

return securityGroupIDs, nil
}

func getSubnetIDs(subnet providerconfigv1.AWSResourceReference, availabilityZone string, client awsclient.Client) ([]*string, error) {
var subnetIDs []*string
// ID has priority
if subnet.ID != nil {
subnetIDs = append(subnetIDs, subnet.ID)
} else {
var filters []providerconfigv1.Filter
if availabilityZone != "" {
filters = append(filters, providerconfigv1.Filter{Name: "availabilityZone", Values: []string{availabilityZone}})
}
filters = append(filters, subnet.Filters...)
glog.Info("Describing subnets based on filters")
describeSubnetRequest := ec2.DescribeSubnetsInput{
Filters: buildEC2Filters(filters),
}
describeSubnetResult, err := client.DescribeSubnets(&describeSubnetRequest)
if err != nil {
glog.Errorf("error describing subnetes: %v", err)
return nil, fmt.Errorf("error describing subnets: %v", err)
}
for _, n := range describeSubnetResult.Subnets {
subnetID := *n.SubnetId
subnetIDs = append(subnetIDs, &subnetID)
}
}
if len(subnetIDs) == 0 {
return nil, fmt.Errorf("no subnet IDs were found")
}
return subnetIDs, nil
}

func getAMI(AMI providerconfigv1.AWSResourceReference, client awsclient.Client) (*string, error) {
if AMI.ID != nil {
amiID := AMI.ID
glog.Infof("Using AMI %s", *amiID)
return amiID, nil
}
if len(AMI.Filters) > 0 {
glog.Info("Describing AMI based on filters")
describeImagesRequest := ec2.DescribeImagesInput{
Filters: buildEC2Filters(AMI.Filters),
}
describeAMIResult, err := client.DescribeImages(&describeImagesRequest)
if err != nil {
glog.Errorf("error describing AMI: %v", err)
return nil, fmt.Errorf("error describing AMI: %v", err)
}
if len(describeAMIResult.Images) < 1 {
glog.Errorf("no image for given filters not found")
return nil, fmt.Errorf("no image for given filters not found")
}
latestImage := describeAMIResult.Images[0]
latestTime, err := time.Parse(time.RFC3339, *latestImage.CreationDate)
if err != nil {
glog.Errorf("unable to parse time for %q AMI: %v", *latestImage.ImageId, err)
return nil, fmt.Errorf("unable to parse time for %q AMI: %v", *latestImage.ImageId, err)
}
for _, image := range describeAMIResult.Images[1:] {
imageTime, err := time.Parse(time.RFC3339, *image.CreationDate)
if err != nil {
glog.Errorf("unable to parse time for %q AMI: %v", *image.ImageId, err)
return nil, fmt.Errorf("unable to parse time for %q AMI: %v", *image.ImageId, err)
}
if latestTime.Before(imageTime) {
latestImage = image
latestTime = imageTime
}
}
return latestImage.ImageId, nil
}
return nil, fmt.Errorf("AMI ID or AMI filters need to be specified")
}

// CreateMachine starts a new AWS instance as described by the cluster and machine resources
func (a *Actuator) CreateMachine(cluster *clusterv1.Cluster, machine *clusterv1.Machine) (*ec2.Instance, error) {
machineProviderConfig, err := ProviderConfigFromMachine(machine)
Expand All @@ -334,7 +184,7 @@ func (a *Actuator) CreateMachine(cluster *clusterv1.Cluster, machine *clusterv1.
// We explicitly do NOT want to remove stopped masters.
if !IsMaster(machine) {
// Prevent having a lot of stopped nodes sitting around.
err = a.removeStoppedMachine(machine, client)
err = removeStoppedMachine(machine, client)
if err != nil {
glog.Errorf("unable to remove stopped machines: %v", err)
return nil, fmt.Errorf("unable to remove stopped nodes: %v", err)
Expand Down
77 changes: 0 additions & 77 deletions pkg/cloud/aws/actuators/machine/actuator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package machine
import (
"errors"
"fmt"
"reflect"
"strings"
"testing"
"time"
Expand Down Expand Up @@ -346,82 +345,6 @@ func mockRegisterInstancesWithLoadBalancer(mockAWSClient *mockaws.MockClient, cr
}
}

func TestRemoveDuplicatedTags(t *testing.T) {
cases := []struct {
tagList []*ec2.Tag
expected []*ec2.Tag
}{
{
// empty tags
tagList: []*ec2.Tag{},
expected: []*ec2.Tag{},
},
{
// no duplicate tags
tagList: []*ec2.Tag{
{Key: aws.String("clusterID"), Value: aws.String("test-ClusterIDValue")},
},
expected: []*ec2.Tag{
{Key: aws.String("clusterID"), Value: aws.String("test-ClusterIDValue")},
},
},
{
// multiple duplicate tags
tagList: []*ec2.Tag{
{Key: aws.String("clusterID"), Value: aws.String("test-ClusterIDValue")},
{Key: aws.String("clusterSize"), Value: aws.String("test-ClusterSizeValue")},
{Key: aws.String("clusterSize"), Value: aws.String("test-ClusterSizeDuplicatedValue")},
},
expected: []*ec2.Tag{
{Key: aws.String("clusterID"), Value: aws.String("test-ClusterIDValue")},
{Key: aws.String("clusterSize"), Value: aws.String("test-ClusterSizeValue")},
},
},
}

for i, c := range cases {
actual := removeDuplicatedTags(c.tagList)
if !reflect.DeepEqual(c.expected, actual) {
t.Errorf("test #%d: expected %+v, got %+v", i, c.expected, actual)
}
}
}

func TestBuildEC2Filters(t *testing.T) {
filter1 := "filter1"
filter2 := "filter2"
value1 := "A"
value2 := "B"
value3 := "C"

inputFilters := []providerconfigv1.Filter{
{
Name: filter1,
Values: []string{value1, value2},
},
{
Name: filter2,
Values: []string{value3},
},
}

expected := []*ec2.Filter{
{
Name: &filter1,
Values: []*string{&value1, &value2},
},
{
Name: &filter2,
Values: []*string{&value3},
},
}

got := buildEC2Filters(inputFilters)
if !reflect.DeepEqual(expected, got) {
t.Errorf("failed to buildEC2Filters. Expected: %+v, got: %+v", expected, got)
}
}

func TestAvailabiltyZone(t *testing.T) {
cases := []struct {
name string
Expand Down
86 changes: 86 additions & 0 deletions pkg/cloud/aws/actuators/machine/instaces_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package machine

import (
"reflect"
"testing"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
providerconfigv1 "sigs.k8s.io/cluster-api-provider-aws/pkg/apis/awsproviderconfig/v1alpha1"
)

func TestRemoveDuplicatedTags(t *testing.T) {
cases := []struct {
tagList []*ec2.Tag
expected []*ec2.Tag
}{
{
// empty tags
tagList: []*ec2.Tag{},
expected: []*ec2.Tag{},
},
{
// no duplicate tags
tagList: []*ec2.Tag{
{Key: aws.String("clusterID"), Value: aws.String("test-ClusterIDValue")},
},
expected: []*ec2.Tag{
{Key: aws.String("clusterID"), Value: aws.String("test-ClusterIDValue")},
},
},
{
// multiple duplicate tags
tagList: []*ec2.Tag{
{Key: aws.String("clusterID"), Value: aws.String("test-ClusterIDValue")},
{Key: aws.String("clusterSize"), Value: aws.String("test-ClusterSizeValue")},
{Key: aws.String("clusterSize"), Value: aws.String("test-ClusterSizeDuplicatedValue")},
},
expected: []*ec2.Tag{
{Key: aws.String("clusterID"), Value: aws.String("test-ClusterIDValue")},
{Key: aws.String("clusterSize"), Value: aws.String("test-ClusterSizeValue")},
},
},
}

for i, c := range cases {
actual := removeDuplicatedTags(c.tagList)
if !reflect.DeepEqual(c.expected, actual) {
t.Errorf("test #%d: expected %+v, got %+v", i, c.expected, actual)
}
}
}

func TestBuildEC2Filters(t *testing.T) {
filter1 := "filter1"
filter2 := "filter2"
value1 := "A"
value2 := "B"
value3 := "C"

inputFilters := []providerconfigv1.Filter{
{
Name: filter1,
Values: []string{value1, value2},
},
{
Name: filter2,
Values: []string{value3},
},
}

expected := []*ec2.Filter{
{
Name: &filter1,
Values: []*string{&value1, &value2},
},
{
Name: &filter2,
Values: []*string{&value3},
},
}

got := buildEC2Filters(inputFilters)
if !reflect.DeepEqual(expected, got) {
t.Errorf("failed to buildEC2Filters. Expected: %+v, got: %+v", expected, got)
}
}
Loading

0 comments on commit 7a54ec0

Please sign in to comment.