Skip to content

Commit

Permalink
Merge pull request #10435 from beezly/feature/add_tg_api_limits
Browse files Browse the repository at this point in the history
Batch up requests with more than 10 target group changes
  • Loading branch information
bflad authored Oct 10, 2019
2 parents c36b56c + d4fe206 commit 9dfcf44
Show file tree
Hide file tree
Showing 2 changed files with 229 additions and 12 deletions.
129 changes: 117 additions & 12 deletions aws/resource_aws_autoscaling_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -767,6 +767,78 @@ func resourceAwsAutoscalingGroupRead(d *schema.ResourceData, meta interface{}) e
return nil
}

func waitUntilAutoscalingGroupLoadBalancerTargetGroupsRemoved(conn *autoscaling.AutoScaling, asgName string) error {
input := &autoscaling.DescribeLoadBalancerTargetGroupsInput{
AutoScalingGroupName: aws.String(asgName),
}
var tgRemoving bool

for {
output, err := conn.DescribeLoadBalancerTargetGroups(input)

if err != nil {
return err
}

for _, tg := range output.LoadBalancerTargetGroups {
if aws.StringValue(tg.State) == "Removing" {
tgRemoving = true
break
}
}

if tgRemoving {
tgRemoving = false
input.NextToken = nil
continue
}

if aws.StringValue(output.NextToken) == "" {
break
}

input.NextToken = output.NextToken
}

return nil
}

func waitUntilAutoscalingGroupLoadBalancerTargetGroupsAdded(conn *autoscaling.AutoScaling, asgName string) error {
input := &autoscaling.DescribeLoadBalancerTargetGroupsInput{
AutoScalingGroupName: aws.String(asgName),
}
var tgAdding bool

for {
output, err := conn.DescribeLoadBalancerTargetGroups(input)

if err != nil {
return err
}

for _, tg := range output.LoadBalancerTargetGroups {
if aws.StringValue(tg.State) == "Adding" {
tgAdding = true
break
}
}

if tgAdding {
tgAdding = false
input.NextToken = nil
continue
}

if aws.StringValue(output.NextToken) == "" {
break
}

input.NextToken = output.NextToken
}

return nil
}

func resourceAwsAutoscalingGroupUpdate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).autoscalingconn
shouldWaitForCapacity := false
Expand Down Expand Up @@ -920,22 +992,55 @@ func resourceAwsAutoscalingGroupUpdate(d *schema.ResourceData, meta interface{})
add := expandStringList(ns.Difference(os).List())

if len(remove) > 0 {
_, err := conn.DetachLoadBalancerTargetGroups(&autoscaling.DetachLoadBalancerTargetGroupsInput{
AutoScalingGroupName: aws.String(d.Id()),
TargetGroupARNs: remove,
})
if err != nil {
return fmt.Errorf("Error updating Load Balancers Target Groups for AutoScaling Group (%s), error: %s", d.Id(), err)
// AWS API only supports adding/removing 10 at a time
var batches [][]*string

batchSize := 10

for batchSize < len(remove) {
remove, batches = remove[batchSize:], append(batches, remove[0:batchSize:batchSize])
}
batches = append(batches, remove)

for _, batch := range batches {
_, err := conn.DetachLoadBalancerTargetGroups(&autoscaling.DetachLoadBalancerTargetGroupsInput{
AutoScalingGroupName: aws.String(d.Id()),
TargetGroupARNs: batch,
})
if err != nil {
return fmt.Errorf("Error updating Load Balancers Target Groups for AutoScaling Group (%s), error: %s", d.Id(), err)
}

if err := waitUntilAutoscalingGroupLoadBalancerTargetGroupsRemoved(conn, d.Id()); err != nil {
return fmt.Errorf("error describing AutoScaling Group (%s) Load Balancer Target Groups being removed: %s", d.Id(), err)
}
}

}

if len(add) > 0 {
_, err := conn.AttachLoadBalancerTargetGroups(&autoscaling.AttachLoadBalancerTargetGroupsInput{
AutoScalingGroupName: aws.String(d.Id()),
TargetGroupARNs: add,
})
if err != nil {
return fmt.Errorf("Error updating Load Balancers Target Groups for AutoScaling Group (%s), error: %s", d.Id(), err)
batchSize := 10

var batches [][]*string

for batchSize < len(add) {
add, batches = add[batchSize:], append(batches, add[0:batchSize:batchSize])
}
batches = append(batches, add)

for _, batch := range batches {
_, err := conn.AttachLoadBalancerTargetGroups(&autoscaling.AttachLoadBalancerTargetGroupsInput{
AutoScalingGroupName: aws.String(d.Id()),
TargetGroupARNs: batch,
})

if err != nil {
return fmt.Errorf("Error updating Load Balancers Target Groups for AutoScaling Group (%s), error: %s", d.Id(), err)
}

if err := waitUntilAutoscalingGroupLoadBalancerTargetGroupsAdded(conn, d.Id()); err != nil {
return fmt.Errorf("error describing AutoScaling Group (%s) Load Balancer Target Groups being added: %s", d.Id(), err)
}
}
}
}
Expand Down
112 changes: 112 additions & 0 deletions aws/resource_aws_autoscaling_group_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -825,6 +825,118 @@ func TestAccAWSAutoScalingGroup_ALB_TargetGroups(t *testing.T) {
})
}

// Reference: https://github.com/terraform-providers/terraform-provider-aws/issues/256
func TestAccAWSAutoScalingGroup_TargetGroupArns(t *testing.T) {
var group autoscaling.Group
resourceName := "aws_autoscaling_group.test"
rName := acctest.RandomWithPrefix("tf-acc-test")

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSAutoScalingGroupDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSAutoScalingGroupConfig_TargetGroupArns(rName, 11),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSAutoScalingGroupExists(resourceName, &group),
resource.TestCheckResourceAttr(resourceName, "target_group_arns.#", "11"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{
"force_delete",
"initial_lifecycle_hook",
"name_prefix",
"tag",
"tags",
"wait_for_capacity_timeout",
"wait_for_elb_capacity",
},
},
{
Config: testAccAWSAutoScalingGroupConfig_TargetGroupArns(rName, 0),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSAutoScalingGroupExists(resourceName, &group),
resource.TestCheckResourceAttr(resourceName, "target_group_arns.#", "0"),
),
},
{
Config: testAccAWSAutoScalingGroupConfig_TargetGroupArns(rName, 11),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSAutoScalingGroupExists(resourceName, &group),
resource.TestCheckResourceAttr(resourceName, "target_group_arns.#", "11"),
),
},
},
})
}

func testAccAWSAutoScalingGroupConfig_TargetGroupArns(rName string, tgCount int) string {
return fmt.Sprintf(`
data "aws_ami" "test" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["amzn-ami-hvm-*-x86_64-gp2"]
}
}
data "aws_availability_zones" "available" {
state = "available"
}
resource "aws_launch_template" "test" {
image_id = data.aws_ami.test.id
instance_type = "t3.micro"
name = %[1]q
}
resource "aws_vpc" "test" {
cidr_block = "10.0.0.0/16"
tags = {
Name = %[1]q
}
}
resource "aws_subnet" "test" {
availability_zone = data.aws_availability_zones.available.names[0]
cidr_block = "10.0.0.0/24"
vpc_id = aws_vpc.test.id
tags = {
Name = %[1]q
}
}
resource "aws_lb_target_group" "test" {
count = %[2]d
port = 80
protocol = "HTTP"
vpc_id = "${aws_vpc.test.id}"
}
resource "aws_autoscaling_group" "test" {
force_delete = true
max_size = 0
min_size = 0
target_group_arns = length(aws_lb_target_group.test) > 0 ? aws_lb_target_group.test[*].arn : []
vpc_zone_identifier = [aws_subnet.test.id]
launch_template {
id = aws_launch_template.test.id
}
}
`, rName, tgCount)
}

func TestAccAWSAutoScalingGroup_initialLifecycleHook(t *testing.T) {
var group autoscaling.Group

Expand Down

0 comments on commit 9dfcf44

Please sign in to comment.