From fae6e221ab7ccf2e78eb28e73b0952931c11a717 Mon Sep 17 00:00:00 2001 From: Enxebre Date: Wed, 29 Aug 2018 19:44:31 +0200 Subject: [PATCH] add support for filters on sg and subnet --- cloud/aws/actuators/machine/actuator.go | 101 +++++++++++++++++++----- examples/machine-with-filters.yaml | 44 +++++++++++ 2 files changed, 125 insertions(+), 20 deletions(-) create mode 100644 examples/machine-with-filters.yaml diff --git a/cloud/aws/actuators/machine/actuator.go b/cloud/aws/actuators/machine/actuator.go index 3120f1e27e..9ef6a4c43f 100644 --- a/cloud/aws/actuators/machine/actuator.go +++ b/cloud/aws/actuators/machine/actuator.go @@ -104,6 +104,73 @@ func (a *Actuator) removeStoppedMachine(machine *clusterv1.Machine, client awscl return TerminateInstances(client, instances, mLog) } +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, mLog log.FieldLogger) ([]*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 { + mLog.Debug("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 { + mLog.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) + } + } + } + return securityGroupIDs, nil +} + +func getSubnetIDs(subnet providerconfigv1.AWSResourceReference, client awsclient.Client, mLog log.FieldLogger) ([]*string, error) { + var subnetIDs []*string + // ID has priority + if subnet.ID != nil { + subnetIDs = append(subnetIDs, subnet.ID) + } else { + mLog.Debug("Describing subnets based on filters") + describeSubnetRequest := ec2.DescribeSubnetsInput{ + Filters: buildEc2Filters(subnet.Filters), + } + describeSubnetResult, err := client.DescribeSubnets(&describeSubnetRequest) + if err != nil { + mLog.Errorf("error describing security groups: %v", err) + return nil, fmt.Errorf("error describing security groups: %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 +} + // 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) { mLog := clustoplog.WithMachine(a.logger, machine) @@ -140,21 +207,9 @@ func (a *Actuator) CreateMachine(cluster *clusterv1.Cluster, machine *clusterv1. amiID = machineProviderConfig.AMI.ID mLog.Debugf("Using AMI %s", *amiID) } else if len(machineProviderConfig.AMI.Filters) > 0 { - filters := make([]*ec2.Filter, len(machineProviderConfig.AMI.Filters)) mLog.Debug("Describing AMI based on filters") - for i, f := range machineProviderConfig.AMI.Filters { - values := make([]*string, len(f.Values)) - for j, v := range f.Values { - values[j] = aws.String(v) - } - filters[i] = &ec2.Filter{ - Name: aws.String(fmt.Sprintf("tag:%v", f.Name)), - Values: values, - } - } - describeImagesRequest := ec2.DescribeImagesInput{ - Filters: filters, + Filters: buildEc2Filters(machineProviderConfig.AMI.Filters), } describeAMIResult, err := client.DescribeImages(&describeImagesRequest) if err != nil { @@ -187,10 +242,16 @@ func (a *Actuator) CreateMachine(cluster *clusterv1.Cluster, machine *clusterv1. return nil, fmt.Errorf("AMI ID or AMI filters need to be specified") } - var securityGroupIds []*string - for _, g := range machineProviderConfig.SecurityGroups { - groupID := *g.ID - securityGroupIds = append(securityGroupIds, &groupID) + securityGroupsIDs, err := getSecurityGroupsIDs(machineProviderConfig.SecurityGroups, client, mLog) + if err != nil { + return nil, fmt.Errorf("error getting security groups IDs: %v,", err) + } + subnetIDs, err := getSubnetIDs(machineProviderConfig.Subnet, client, mLog) + if err != nil { + return nil, fmt.Errorf("error getting subnet IDs: %v,", err) + } + if len(subnetIDs) > 1 { + mLog.Warnf("More than one subnet id returned, only first one will be used") } // build list of networkInterfaces (just 1 for now) @@ -198,8 +259,8 @@ func (a *Actuator) CreateMachine(cluster *clusterv1.Cluster, machine *clusterv1. { DeviceIndex: aws.Int64(machineProviderConfig.DeviceIndex), AssociatePublicIpAddress: machineProviderConfig.PublicIP, - SubnetId: machineProviderConfig.Subnet.ID, - Groups: securityGroupIds, + SubnetId: subnetIDs[0], + Groups: securityGroupsIDs, }, } @@ -210,7 +271,7 @@ func (a *Actuator) CreateMachine(cluster *clusterv1.Cluster, machine *clusterv1. } tagList = append(tagList, []*ec2.Tag{ {Key: aws.String("clusterid"), Value: aws.String(cluster.Name)}, - {Key: aws.String("kubernetes.io/cluster/" + cluster.Name), Value: aws.String(cluster.Name)}, + {Key: aws.String("kubernetes.io/cluster/" + cluster.Name), Value: aws.String("owned")}, {Key: aws.String("Name"), Value: aws.String(machine.Name)}, }...) diff --git a/examples/machine-with-filters.yaml b/examples/machine-with-filters.yaml new file mode 100644 index 0000000000..a7d279e37d --- /dev/null +++ b/examples/machine-with-filters.yaml @@ -0,0 +1,44 @@ +--- +apiVersion: "cluster.k8s.io/v1alpha1" +kind: Machine +metadata: + name: aws-actuator-testing-machine + namespace: test + generateName: vs-worker- + labels: + sigs.k8s.io/cluster-api-cluster: tb-asg-35 + sigs.k8s.io/cluster-api-machine-role: compute + sigs.k8s.io/cluster-api-machine-type: worker +spec: + providerConfig: + value: + apiVersion: aws.cluster.k8s.io/v1alpha1 + kind: AWSMachineProviderConfig + ami: + id: ami-0518e1ac70d8a3389 + instanceType: m4.large + placement: + region: eu-west-1 + availabilityZone: eu-west-1c + subnet: + filters: + - name: "tag:Name" + values: + - "meh-worker-eu-west-1c" + publicIp: true + iamInstanceProfile: + id: meh-master-profile + keyName: tectonic + tags: + - name: "kubernetes.io/cluster/meh" + value: owned + securityGroups: + - filters: + - name: "tag:Name" + values: + - "meh_worker_sg" + userDataSecret: + name: ignition-worker + versions: + kubelet: "" + controlPlane: ""