mirror of
https://github.com/opentofu/opentofu.git
synced 2025-01-08 15:13:56 -06:00
provider/aws: aws_autoscaling_group ALB target group support (#10243)
This update adds ALB support to the wait_for_elb_capacity/min_elb_capacity options. Target groups are handled in nearly the same way as Classic ELBs, so the change should be transparent. This supports both ALB target groups and classic ELBs being attached to the ASG at the same time.
This commit is contained in:
parent
fa892adf72
commit
67d162a126
@ -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 {
|
||||
@ -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
|
||||
|
||||
@ -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 {
|
||||
|
@ -1,6 +1,7 @@
|
||||
package aws
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"regexp"
|
||||
@ -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
|
||||
|
||||
@ -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"
|
||||
@ -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}"
|
||||
}
|
||||
`
|
||||
|
@ -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)
|
||||
}
|
||||
@ -66,12 +67,18 @@ 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++
|
||||
}
|
||||
@ -79,7 +86,7 @@ func waitForASGCapacity(
|
||||
|
||||
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 {
|
||||
|
Loading…
Reference in New Issue
Block a user