Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/pbp_b_autoscaling_alb_target_grp…
Browse files Browse the repository at this point in the history
…s' into paybyphone
  • Loading branch information
Chris Marchesi committed Nov 20, 2016
2 parents 449d04a + b6585d4 commit 7317919
Show file tree
Hide file tree
Showing 3 changed files with 229 additions and 5 deletions.
36 changes: 34 additions & 2 deletions builtin/providers/aws/resource_aws_autoscaling_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/autoscaling"
"github.com/aws/aws-sdk-go/service/elb"
"github.com/aws/aws-sdk-go/service/elbv2"
)

func resourceAwsAutoscalingGroup() *schema.Resource {
Expand Down Expand Up @@ -800,11 +801,13 @@ func updateASGMetricsCollection(d *schema.ResourceData, conn *autoscaling.AutoSc
return nil
}

// Returns a mapping of the instance states of all the ELBs attached to the
// getELBInstanceStates returns a mapping of the instance states of all the ELBs attached to the
// provided ASG.
//
// Note that this is the instance state function for ELB Classic.
//
// Nested like: lbName -> instanceId -> instanceState
func getLBInstanceStates(g *autoscaling.Group, meta interface{}) (map[string]map[string]string, error) {
func getELBInstanceStates(g *autoscaling.Group, meta interface{}) (map[string]map[string]string, error) {
lbInstanceStates := make(map[string]map[string]string)
elbconn := meta.(*AWSClient).elbconn

Expand All @@ -826,6 +829,35 @@ func getLBInstanceStates(g *autoscaling.Group, meta interface{}) (map[string]map
return lbInstanceStates, nil
}

// getTargetGroupInstanceStates returns a mapping of the instance states of
// all the ALB target groups attached to the provided ASG.
//
// Note that this is the instance state function for Application Load
// Balancing (aka ELBv2).
//
// Nested like: targetGroupARN -> instanceId -> instanceState
func getTargetGroupInstanceStates(g *autoscaling.Group, meta interface{}) (map[string]map[string]string, error) {
targetInstanceStates := make(map[string]map[string]string)
elbv2conn := meta.(*AWSClient).elbv2conn

for _, targetGroupARN := range g.TargetGroupARNs {
targetInstanceStates[*targetGroupARN] = make(map[string]string)
opts := &elbv2.DescribeTargetHealthInput{TargetGroupArn: targetGroupARN}
r, err := elbv2conn.DescribeTargetHealth(opts)
if err != nil {
return nil, err
}
for _, desc := range r.TargetHealthDescriptions {
if desc.Target == nil || desc.Target.Id == nil || desc.TargetHealth == nil || desc.TargetHealth.State == nil {
continue
}
targetInstanceStates[*targetGroupARN][*desc.Target.Id] = *desc.TargetHealth.State
}
}

return targetInstanceStates, nil
}

func expandVpcZoneIdentifiers(list []interface{}) *string {
strs := make([]string, len(list))
for _, s := range list {
Expand Down
185 changes: 185 additions & 0 deletions builtin/providers/aws/resource_aws_autoscaling_group_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package aws

import (
"errors"
"fmt"
"reflect"
"regexp"
Expand Down Expand Up @@ -430,6 +431,27 @@ func TestAccAWSAutoScalingGroup_initialLifecycleHook(t *testing.T) {
})
}

func TestAccAWSAutoScalingGroup_ALB_TargetGroups_ELBCapacity(t *testing.T) {
var group autoscaling.Group
var tg elbv2.TargetGroup

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSAutoScalingGroupDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccAWSAutoScalingGroupConfig_ALB_TargetGroup_ELBCapacity,
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckAWSAutoScalingGroupExists("aws_autoscaling_group.bar", &group),
testAccCheckAWSALBTargetGroupExists("aws_alb_target_group.test", &tg),
testAccCheckAWSALBTargetGroupHealthy(&tg),
),
},
},
})
}

func testAccCheckAWSAutoScalingGroupDestroy(s *terraform.State) error {
conn := testAccProvider.Meta().(*AWSClient).autoscalingconn

Expand Down Expand Up @@ -648,6 +670,30 @@ func testAccCheckAWSAutoScalingGroupAttributesVPCZoneIdentifer(group *autoscalin
}
}

// testAccCheckAWSALBTargetGroupHealthy checks an *elbv2.TargetGroup to make
// sure that all instances in it are healthy.
func testAccCheckAWSALBTargetGroupHealthy(res *elbv2.TargetGroup) resource.TestCheckFunc {
return func(s *terraform.State) error {
conn := testAccProvider.Meta().(*AWSClient).elbv2conn

resp, err := conn.DescribeTargetHealth(&elbv2.DescribeTargetHealthInput{
TargetGroupArn: res.TargetGroupArn,
})

if err != nil {
return err
}

for _, target := range resp.TargetHealthDescriptions {
if target.TargetHealth == nil || target.TargetHealth.State == nil || *target.TargetHealth.State != "healthy" {
return errors.New("Not all instances in target group are healthy yet, but should be")
}
}

return nil
}
}

const testAccAWSAutoScalingGroupConfig_autoGeneratedName = `
resource "aws_launch_configuration" "foobar" {
image_id = "ami-21f78e11"
Expand Down Expand Up @@ -1302,3 +1348,142 @@ resource "aws_autoscaling_group" "bar" {
}
`, name)
}

const testAccAWSAutoScalingGroupConfig_ALB_TargetGroup_ELBCapacity = `
provider "aws" {
region = "us-west-2"
}
resource "aws_vpc" "default" {
cidr_block = "10.0.0.0/16"
enable_dns_hostnames = "true"
enable_dns_support = "true"
tags {
Name = "testAccAWSAutoScalingGroupConfig_ALB_TargetGroup_ELBCapacity"
}
}
resource "aws_alb" "test_lb" {
subnets = ["${aws_subnet.main.id}", "${aws_subnet.alt.id}"]
tags {
Name = "testAccAWSAutoScalingGroupConfig_ALB_TargetGroup_ELBCapacity"
}
}
resource "aws_alb_listener" "test_listener" {
load_balancer_arn = "${aws_alb.test_lb.arn}"
port = "80"
default_action {
target_group_arn = "${aws_alb_target_group.test.arn}"
type = "forward"
}
}
resource "aws_alb_target_group" "test" {
name = "tf-example-alb-tg"
port = 80
protocol = "HTTP"
vpc_id = "${aws_vpc.default.id}"
health_check {
path = "/"
healthy_threshold = "2"
timeout = "2"
interval = "5"
}
}
resource "aws_subnet" "main" {
vpc_id = "${aws_vpc.default.id}"
cidr_block = "10.0.1.0/24"
availability_zone = "us-west-2a"
tags {
Name = "testAccAWSAutoScalingGroupConfig_ALB_TargetGroup_ELBCapacity"
}
}
resource "aws_subnet" "alt" {
vpc_id = "${aws_vpc.default.id}"
cidr_block = "10.0.2.0/24"
availability_zone = "us-west-2b"
tags {
Name = "testAccAWSAutoScalingGroupConfig_ALB_TargetGroup_ELBCapacity"
}
}
resource "aws_internet_gateway" "internet_gateway" {
vpc_id = "${aws_vpc.default.id}"
}
resource "aws_route_table" "route_table" {
vpc_id = "${aws_vpc.default.id}"
}
resource "aws_route_table_association" "route_table_association_main" {
subnet_id = "${aws_subnet.main.id}"
route_table_id = "${aws_route_table.route_table.id}"
}
resource "aws_route_table_association" "route_table_association_alt" {
subnet_id = "${aws_subnet.alt.id}"
route_table_id = "${aws_route_table.route_table.id}"
}
resource "aws_route" "public_default_route" {
route_table_id = "${aws_route_table.route_table.id}"
destination_cidr_block = "0.0.0.0/0"
gateway_id = "${aws_internet_gateway.internet_gateway.id}"
}
data "aws_ami" "test_ami" {
most_recent = true
filter {
name = "owner-alias"
values = ["amazon"]
}
filter {
name = "name"
values = ["amzn-ami-hvm-*-x86_64-gp2"]
}
}
resource "aws_launch_configuration" "foobar" {
image_id = "${data.aws_ami.test_ami.id}"
instance_type = "t2.micro"
associate_public_ip_address = "true"
user_data = <<EOS
#!/bin/bash
yum -y install httpd
echo "hello world" > /var/www/html/index.html
chkconfig httpd on
service httpd start
EOS
}
resource "aws_autoscaling_group" "bar" {
vpc_zone_identifier = [
"${aws_subnet.main.id}",
"${aws_subnet.alt.id}",
]
target_group_arns = ["${aws_alb_target_group.test.arn}"]
max_size = 2
min_size = 2
health_check_grace_period = 300
health_check_type = "ELB"
desired_capacity = 2
wait_for_elb_capacity = 2
force_delete = true
termination_policies = ["OldestInstance"]
launch_configuration = "${aws_launch_configuration.foobar.name}"
}
`
13 changes: 10 additions & 3 deletions builtin/providers/aws/resource_aws_autoscaling_group_waiting.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ func waitForASGCapacity(
d.SetId("")
return nil
}
lbis, err := getLBInstanceStates(g, meta)
elbis, err := getELBInstanceStates(g, meta)
albis, err := getTargetGroupInstanceStates(g, meta)
if err != nil {
return resource.NonRetryableError(err)
}
Expand All @@ -66,20 +67,26 @@ func waitForASGCapacity(
haveASG++

inAllLbs := true
for _, states := range lbis {
for _, states := range elbis {
state, ok := states[*i.InstanceId]
if !ok || !strings.EqualFold(state, "InService") {
inAllLbs = false
}
}
for _, states := range albis {
state, ok := states[*i.InstanceId]
if !ok || !strings.EqualFold(state, "healthy") {
inAllLbs = false
}
}
if inAllLbs {
haveELB++
}
}

satisfied, reason := satisfiedFunc(d, haveASG, haveELB)

log.Printf("[DEBUG] %q Capacity: %d ASG, %d ELB, satisfied: %t, reason: %q",
log.Printf("[DEBUG] %q Capacity: %d ASG, %d ELB/ALB, satisfied: %t, reason: %q",
d.Id(), haveASG, haveELB, satisfied, reason)

if satisfied {
Expand Down

0 comments on commit 7317919

Please sign in to comment.