Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use DescribeInstance to retrieve filtered AWS instances #29

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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