Skip to content

Commit

Permalink
Use DescribeInstance to retrieve filtered AWS instances
Browse files Browse the repository at this point in the history
initial implementation for issue #28
  • Loading branch information
trjstewart committed Sep 24, 2019
1 parent f06d6ab commit 52959aa
Show file tree
Hide file tree
Showing 9 changed files with 41 additions and 14,497 deletions.
8 changes: 2 additions & 6 deletions Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

104 changes: 37 additions & 67 deletions cmd/sync/aws.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,17 @@ import (
"time"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/aws/ec2metadata"
"github.com/aws/aws-sdk-go/service/autoscaling"
"github.com/aws/aws-sdk-go/service/autoscaling/autoscalingiface"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/ec2/ec2iface"
yaml "gopkg.in/yaml.v2"
)

// AWSClient allows you to get the list of IP addresses of instanes of an Auto Scaling group. It implements the CloudProvider interface
type AWSClient struct {
svcEC2 ec2iface.EC2API
svcAutoscaling autoscalingiface.AutoScalingAPI
config *awsConfig
svcEC2 ec2iface.EC2API
config *awsConfig
}

// NewAWSClient creates and configures an AWSClient
Expand All @@ -38,7 +35,7 @@ func NewAWSClient(data []byte) (*AWSClient, error) {
if err != nil {
return nil, err
}

metaClient := ec2metadata.New(metaSession)
if !metaClient.Available() {
return nil, fmt.Errorf("ec2metadata service is unavailable")
Expand Down Expand Up @@ -86,10 +83,8 @@ func (client *AWSClient) configure() error {
return err
}

svcAutoscaling := autoscaling.New(session)
svcEC2 := ec2.New(session)
client.svcEC2 = svcEC2
client.svcAutoscaling = svcAutoscaling
return nil
}

Expand All @@ -111,79 +106,54 @@ func parseAWSConfig(data []byte) (*awsConfig, error) {

// CheckIfScalingGroupExists checks if the Auto Scaling group exists
func (client *AWSClient) CheckIfScalingGroupExists(name string) (bool, error) {
_, exists, err := client.getAutoscalingGroup(name)
if err != nil {
return exists, fmt.Errorf("couldn't check if an AutoScaling group exists: %v", err)
}
return exists, nil
}

// GetPrivateIPsForScalingGroup returns the list of IP addresses of instances of the Auto Scaling group
func (client *AWSClient) GetPrivateIPsForScalingGroup(name string) ([]string, error) {
group, exists, err := client.getAutoscalingGroup(name)
if err != nil {
return nil, err
}

if !exists {
return nil, fmt.Errorf("autoscaling group %v doesn't exist", name)
params := &ec2.DescribeInstancesInput{
Filters: []*ec2.Filter{
&ec2.Filter{
Name: aws.String("tag:aws:autoscaling:groupName"),
Values: []*string{
aws.String(name),
},
},
},
}

instances, err := client.getInstancesOfAutoscalingGroup(group)
response, err := client.svcEC2.DescribeInstances(params)
if err != nil {
return nil, err
}

var result []string
for _, ins := range instances {
if len(ins.NetworkInterfaces) > 0 && ins.NetworkInterfaces[0].PrivateIpAddress != nil {
result = append(result, *ins.NetworkInterfaces[0].PrivateIpAddress)
}
return false, fmt.Errorf("couldn't check if an AutoScaling group exists: %v", err)
}

return result, nil
return len(response.Reservations) > 0, nil
}

func (client *AWSClient) getAutoscalingGroup(name string) (*autoscaling.Group, bool, error) {
params := &autoscaling.DescribeAutoScalingGroupsInput{
AutoScalingGroupNames: []*string{
aws.String(name),
// GetPrivateIPsForScalingGroup returns the list of IP addresses of instances of the Auto Scaling group
func (client *AWSClient) GetPrivateIPsForScalingGroup(name string) ([]string, error) {
params := &ec2.DescribeInstancesInput{
Filters: []*ec2.Filter{
&ec2.Filter{
Name: aws.String("tag:aws:autoscaling:groupName"),
Values: []*string{
aws.String(name),
},
},
},
}

resp, err := client.svcAutoscaling.DescribeAutoScalingGroups(params)
response, err := client.svcEC2.DescribeInstances(params)
if err != nil {
return nil, false, err
}

if len(resp.AutoScalingGroups) != 1 {
return nil, false, nil
}

return resp.AutoScalingGroups[0], true, nil
}

func (client *AWSClient) getInstancesOfAutoscalingGroup(group *autoscaling.Group) ([]*ec2.Instance, error) {
var result []*ec2.Instance

if len(group.Instances) == 0 {
return result, nil
return nil, err
}

var ids []*string
for _, ins := range group.Instances {
ids = append(ids, ins.InstanceId)
}
params := &ec2.DescribeInstancesInput{
InstanceIds: ids,
if len(response.Reservations) == 0 {
return nil, fmt.Errorf("autoscaling group %v doesn't exist", name)
}

resp, err := client.svcEC2.DescribeInstances(params)
if err != nil {
return result, err
}
for _, res := range resp.Reservations {
result = append(result, res.Instances...)
var result []string
for _, res := range response.Reservations {
for _, ins := range res.Instances {
if len(ins.NetworkInterfaces) > 0 && ins.NetworkInterfaces[0].PrivateIpAddress != nil {
result = append(result, *ins.NetworkInterfaces[0].PrivateIpAddress)
}
}
}

return result, nil
Expand Down
4 changes: 2 additions & 2 deletions examples/aws.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,6 @@ upstreams:
* The `region` key defines the AWS region where we deploy NGINX Plus and the Auto Scaling groups. Setting `region` to `self` will use the EC2 Metadata service to retreive the region of the current instance.
* The `upstreams` key defines the list of upstream groups. For each upstream group we specify:
* `name` – The name we specified for the upstream block in the NGINX Plus configuration.
* `autoscaling_group` – The name of the corresponding Auto Scaling group.
* `autoscaling_group` – The name of the corresponding Auto Scaling group. Use of wildcards is supported. For example, `backend-*`.
* `port` – The port on which our backend applications are exposed.
* `kind` – The protocol of the traffic NGINX Plus load balances to the backend application, here `http`. If the application uses TCP/UDP, specify `stream` instead.
* `kind` – The protocol of the traffic NGINX Plus load balances to the backend application, here `http`. If the application uses TCP/UDP, specify `stream` instead.
Loading

0 comments on commit 52959aa

Please sign in to comment.