From 7f9360797cc7106f322eafb079c4f137c1424178 Mon Sep 17 00:00:00 2001 From: Paul Hinze Date: Mon, 16 Nov 2015 18:16:22 -0600 Subject: [PATCH] provider/aws: wait for ASG capacity on update It's a bit confusing to have Terraform poll until instances come up on ASG creation but not on update. This changes update to also poll if min_size or desired_capacity are changed. This changes the waiting behavior to wait for precisely the desired number of instances instead of that number as a "minimum". I believe this shouldn't have any undue side effects, and the behavior can still be opted out of by setting `wait_for_capacity_timeout` to 0. --- .../aws/resource_aws_autoscaling_group.go | 30 +++++++++++++++---- .../resource_aws_autoscaling_group_test.go | 2 +- .../aws/r/autoscaling_group.html.markdown | 22 +++++++++----- 3 files changed, 40 insertions(+), 14 deletions(-) diff --git a/builtin/providers/aws/resource_aws_autoscaling_group.go b/builtin/providers/aws/resource_aws_autoscaling_group.go index d5a87e33b..d9a9d7bab 100644 --- a/builtin/providers/aws/resource_aws_autoscaling_group.go +++ b/builtin/providers/aws/resource_aws_autoscaling_group.go @@ -51,8 +51,9 @@ func resourceAwsAutoscalingGroup() *schema.Resource { }, "min_elb_capacity": &schema.Schema{ - Type: schema.TypeInt, - Optional: true, + Type: schema.TypeInt, + Optional: true, + Deprecated: "Please use 'wait_for_elb_capacity' instead.", }, "min_size": &schema.Schema{ @@ -136,6 +137,11 @@ func resourceAwsAutoscalingGroup() *schema.Resource { }, }, + "wait_for_elb_capacity": &schema.Schema{ + Type: schema.TypeInt, + Optional: true, + }, + "tag": autoscalingTagsSchema(), }, } @@ -242,6 +248,7 @@ func resourceAwsAutoscalingGroupRead(d *schema.ResourceData, meta interface{}) e func resourceAwsAutoscalingGroupUpdate(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).autoscalingconn + shouldWaitForCapacity := false opts := autoscaling.UpdateAutoScalingGroupInput{ AutoScalingGroupName: aws.String(d.Id()), @@ -253,6 +260,7 @@ func resourceAwsAutoscalingGroupUpdate(d *schema.ResourceData, meta interface{}) if d.HasChange("desired_capacity") { opts.DesiredCapacity = aws.Int64(int64(d.Get("desired_capacity").(int))) + shouldWaitForCapacity = true } if d.HasChange("launch_configuration") { @@ -261,6 +269,7 @@ func resourceAwsAutoscalingGroupUpdate(d *schema.ResourceData, meta interface{}) if d.HasChange("min_size") { opts.MinSize = aws.Int64(int64(d.Get("min_size").(int))) + shouldWaitForCapacity = true } if d.HasChange("max_size") { @@ -353,6 +362,10 @@ func resourceAwsAutoscalingGroupUpdate(d *schema.ResourceData, meta interface{}) } } + if shouldWaitForCapacity { + waitForASGCapacity(d, meta) + } + return resourceAwsAutoscalingGroupRead(d, meta) } @@ -490,7 +503,7 @@ func resourceAwsAutoscalingGroupDrain(d *schema.ResourceData, meta interface{}) // ASG before continuing. Waits up to `waitForASGCapacityTimeout` for // "desired_capacity", or "min_size" if desired capacity is not specified. // -// If "min_elb_capacity" is specified, will also wait for that number of +// If "wait_for_elb_capacity" is specified, will also wait for that number of // instances to show up InService in all attached ELBs. See "Waiting for // Capacity" in docs for more discussion of the feature. func waitForASGCapacity(d *schema.ResourceData, meta interface{}) error { @@ -498,7 +511,10 @@ func waitForASGCapacity(d *schema.ResourceData, meta interface{}) error { if v := d.Get("desired_capacity").(int); v > 0 { wantASG = v } - wantELB := d.Get("min_elb_capacity").(int) + wantELB := d.Get("wait_for_elb_capacity").(int) + + // Covers deprecated field support + wantELB += d.Get("min_elb_capacity").(int) wait, err := time.ParseDuration(d.Get("wait_for_capacity_timeout").(string)) if err != nil { @@ -561,11 +577,13 @@ func waitForASGCapacity(d *schema.ResourceData, meta interface{}) error { log.Printf("[DEBUG] %q Capacity: %d/%d ASG, %d/%d ELB", d.Id(), haveASG, wantASG, haveELB, wantELB) - if haveASG >= wantASG && haveELB >= wantELB { + if haveASG == wantASG && haveELB == wantELB { return nil } - return fmt.Errorf("Still need to wait for more healthy instances. This could mean instances failed to launch. See Scaling History for more information.") + return fmt.Errorf( + "Still waiting for %q instances. Current/Desired: %d/%d ASG, %d/%d ELB", + d.Id(), haveASG, wantASG, haveELB, wantELB) }) } diff --git a/builtin/providers/aws/resource_aws_autoscaling_group_test.go b/builtin/providers/aws/resource_aws_autoscaling_group_test.go index 5f87bc3d0..673bae867 100644 --- a/builtin/providers/aws/resource_aws_autoscaling_group_test.go +++ b/builtin/providers/aws/resource_aws_autoscaling_group_test.go @@ -526,7 +526,7 @@ resource "aws_autoscaling_group" "bar" { min_size = 2 health_check_grace_period = 300 health_check_type = "ELB" - min_elb_capacity = 2 + wait_for_elb_capacity = 2 force_delete = true launch_configuration = "${aws_launch_configuration.foobar.name}" diff --git a/website/source/docs/providers/aws/r/autoscaling_group.html.markdown b/website/source/docs/providers/aws/r/autoscaling_group.html.markdown index 6f2b0e511..1a0a22e77 100644 --- a/website/source/docs/providers/aws/r/autoscaling_group.html.markdown +++ b/website/source/docs/providers/aws/r/autoscaling_group.html.markdown @@ -53,9 +53,6 @@ The following arguments are supported: * `desired_capacity` - (Optional) The number of Amazon EC2 instances that should be running in the group. (See also [Waiting for Capacity](#waiting-for-capacity) below.) -* `min_elb_capacity` - (Optional) Setting this will cause Terraform to wait - for this number of healthy instances all attached load balancers. - (See also [Waiting for Capacity](#waiting-for-capacity) below.) * `force_delete` - (Optional) Allows deleting the autoscaling group without waiting for all instances in the pool to terminate. You can force an autoscaling group to delete even if it's in the process of scaling a resource. Normally, Terraform @@ -71,6 +68,9 @@ The following arguments are supported: wait for ASG instances to be healthy before timing out. (See also [Waiting for Capacity](#waiting-for-capacity) below.) Setting this to "0" causes Terraform to skip all Capacity Waiting behavior. +* `wait_for_elb_capacity` - (Optional) Setting this will cause Terraform to wait + for this number of healthy instances all attached load balancers. + (See also [Waiting for Capacity](#waiting-for-capacity) below.) Tags support the following: @@ -79,6 +79,10 @@ Tags support the following: * `propagate_at_launch` - (Required) Enables propagation of the tag to Amazon EC2 instances launched via this ASG +The following fields are deprecated: + +* `min_elb_capacity` - Please use `wait_for_elb_capacity` instead. + ## Attributes Reference The following attributes are exported: @@ -96,7 +100,7 @@ The following attributes are exported: * `vpc_zone_identifier` - The VPC zone identifier * `load_balancers` (Optional) The load balancer names associated with the autoscaling group. - + ~> **NOTE:** When using `ELB` as the health_check_type, `health_check_grace_period` is required. @@ -115,6 +119,10 @@ The first is default behavior. Terraform waits after ASG creation for `min_size` (or `desired_capacity`, if specified) healthy instances to show up in the ASG before continuing. +If `min_size` or `desired_capacity` are changed in a subsequent update, +Terraform will also wait for the correct number of healthy instances before +continuing. + Terraform considers an instance "healthy" when the ASG reports `HealthStatus: "Healthy"` and `LifecycleState: "InService"`. See the [AWS AutoScaling Docs](https://docs.aws.amazon.com/AutoScaling/latest/DeveloperGuide/AutoScalingGroupLifecycle.html) @@ -130,9 +138,9 @@ Setting `wait_for_capacity_timeout` to `"0"` disables ASG Capacity waiting. #### Waiting for ELB Capacity The second mechanism is optional, and affects ASGs with attached Load -Balancers. If `min_elb_capacity` is set, Terraform will wait for that number of -Instances to be `"InService"` in all attached `load_balancers`. This can be -used to ensure that service is being provided before Terraform moves on. +Balancers. If `wait_for_elb_capacity` is set, Terraform will wait for that +number of Instances to be `"InService"` in all attached `load_balancers`. This +can be used to ensure that service is being provided before Terraform moves on. As with ASG Capacity, Terraform will wait for up to `wait_for_capacity_timeout` (for `"InService"` instances. If ASG creation takes more than a few minutes,