providers/aws: drain autoscale groups before deleting [GH-435]
This commit is contained in:
parent
7c89fb06cc
commit
f5c2aba215
|
@ -16,6 +16,7 @@ BUG FIXES:
|
||||||
* providers/aws: Retry deleting security groups for some amount of time
|
* providers/aws: Retry deleting security groups for some amount of time
|
||||||
if there is a dependency violation since it is probably just eventual
|
if there is a dependency violation since it is probably just eventual
|
||||||
consistency. [GH-436]
|
consistency. [GH-436]
|
||||||
|
* providers/aws: Drain autoscale groups before deleting. [GH-435]
|
||||||
|
|
||||||
## 0.3.0 (October 14, 2014)
|
## 0.3.0 (October 14, 2014)
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,10 @@ package aws
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/helper/hashcode"
|
"github.com/hashicorp/terraform/helper/hashcode"
|
||||||
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
"github.com/hashicorp/terraform/helper/schema"
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
"github.com/mitchellh/goamz/autoscaling"
|
"github.com/mitchellh/goamz/autoscaling"
|
||||||
)
|
)
|
||||||
|
@ -196,6 +198,22 @@ func resourceAwsAutoscalingGroupDelete(d *schema.ResourceData, meta interface{})
|
||||||
p := meta.(*ResourceProvider)
|
p := meta.(*ResourceProvider)
|
||||||
autoscalingconn := p.autoscalingconn
|
autoscalingconn := p.autoscalingconn
|
||||||
|
|
||||||
|
// Read the autoscaling group first. If it doesn't exist, we're done.
|
||||||
|
// We need the group in order to check if there are instances attached.
|
||||||
|
// If so, we need to remove those first.
|
||||||
|
g, err := getAwsAutoscalingGroup(d, meta)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if g == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if len(g.Instances) > 0 || g.DesiredCapacity > 0 {
|
||||||
|
if err := resourceAwsAutoscalingGroupDrain(d, meta); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
log.Printf("[DEBUG] AutoScaling Group destroy: %v", d.Id())
|
log.Printf("[DEBUG] AutoScaling Group destroy: %v", d.Id())
|
||||||
deleteopts := autoscaling.DeleteAutoScalingGroup{Name: d.Id()}
|
deleteopts := autoscaling.DeleteAutoScalingGroup{Name: d.Id()}
|
||||||
|
|
||||||
|
@ -208,8 +226,7 @@ func resourceAwsAutoscalingGroupDelete(d *schema.ResourceData, meta interface{})
|
||||||
deleteopts.ForceDelete = true
|
deleteopts.ForceDelete = true
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := autoscalingconn.DeleteAutoScalingGroup(&deleteopts)
|
if _, err := autoscalingconn.DeleteAutoScalingGroup(&deleteopts); err != nil {
|
||||||
if err != nil {
|
|
||||||
autoscalingerr, ok := err.(*autoscaling.Error)
|
autoscalingerr, ok := err.(*autoscaling.Error)
|
||||||
if ok && autoscalingerr.Code == "InvalidGroup.NotFound" {
|
if ok && autoscalingerr.Code == "InvalidGroup.NotFound" {
|
||||||
return nil
|
return nil
|
||||||
|
@ -222,35 +239,14 @@ func resourceAwsAutoscalingGroupDelete(d *schema.ResourceData, meta interface{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func resourceAwsAutoscalingGroupRead(d *schema.ResourceData, meta interface{}) error {
|
func resourceAwsAutoscalingGroupRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
p := meta.(*ResourceProvider)
|
g, err := getAwsAutoscalingGroup(d, meta)
|
||||||
autoscalingconn := p.autoscalingconn
|
|
||||||
|
|
||||||
describeOpts := autoscaling.DescribeAutoScalingGroups{
|
|
||||||
Names: []string{d.Id()},
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Printf("[DEBUG] AutoScaling Group describe configuration: %#v", describeOpts)
|
|
||||||
describeGroups, err := autoscalingconn.DescribeAutoScalingGroups(&describeOpts)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
autoscalingerr, ok := err.(*autoscaling.Error)
|
return err
|
||||||
if ok && autoscalingerr.Code == "InvalidGroup.NotFound" {
|
}
|
||||||
d.SetId("")
|
if g == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Errorf("Error retrieving AutoScaling groups: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify AWS returned our sg
|
|
||||||
if len(describeGroups.AutoScalingGroups) != 1 ||
|
|
||||||
describeGroups.AutoScalingGroups[0].Name != d.Id() {
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Unable to find AutoScaling group: %#v", describeGroups.AutoScalingGroups)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
g := describeGroups.AutoScalingGroups[0]
|
|
||||||
|
|
||||||
d.Set("availability_zones", g.AvailabilityZones)
|
d.Set("availability_zones", g.AvailabilityZones)
|
||||||
d.Set("default_cooldown", g.DefaultCooldown)
|
d.Set("default_cooldown", g.DefaultCooldown)
|
||||||
d.Set("desired_capacity", g.DesiredCapacity)
|
d.Set("desired_capacity", g.DesiredCapacity)
|
||||||
|
@ -265,3 +261,76 @@ func resourceAwsAutoscalingGroupRead(d *schema.ResourceData, meta interface{}) e
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getAwsAutoscalingGroup(
|
||||||
|
d *schema.ResourceData,
|
||||||
|
meta interface{}) (*autoscaling.AutoScalingGroup, error) {
|
||||||
|
p := meta.(*ResourceProvider)
|
||||||
|
autoscalingconn := p.autoscalingconn
|
||||||
|
|
||||||
|
describeOpts := autoscaling.DescribeAutoScalingGroups{
|
||||||
|
Names: []string{d.Id()},
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("[DEBUG] AutoScaling Group describe configuration: %#v", describeOpts)
|
||||||
|
describeGroups, err := autoscalingconn.DescribeAutoScalingGroups(&describeOpts)
|
||||||
|
if err != nil {
|
||||||
|
autoscalingerr, ok := err.(*autoscaling.Error)
|
||||||
|
if ok && autoscalingerr.Code == "InvalidGroup.NotFound" {
|
||||||
|
d.SetId("")
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, fmt.Errorf("Error retrieving AutoScaling groups: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify AWS returned our sg
|
||||||
|
if len(describeGroups.AutoScalingGroups) != 1 ||
|
||||||
|
describeGroups.AutoScalingGroups[0].Name != d.Id() {
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf(
|
||||||
|
"Unable to find AutoScaling group: %#v",
|
||||||
|
describeGroups.AutoScalingGroups)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &describeGroups.AutoScalingGroups[0], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceAwsAutoscalingGroupDrain(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
p := meta.(*ResourceProvider)
|
||||||
|
autoscalingconn := p.autoscalingconn
|
||||||
|
|
||||||
|
// First, set the capacity to zero so the group will drain
|
||||||
|
log.Printf("[DEBUG] Reducing autoscaling group capacity to zero")
|
||||||
|
opts := autoscaling.UpdateAutoScalingGroup{
|
||||||
|
Name: d.Id(),
|
||||||
|
DesiredCapacity: 0,
|
||||||
|
MinSize: 0,
|
||||||
|
MaxSize: 0,
|
||||||
|
SetDesiredCapacity: true,
|
||||||
|
SetMinSize: true,
|
||||||
|
SetMaxSize: true,
|
||||||
|
}
|
||||||
|
if _, err := autoscalingconn.UpdateAutoScalingGroup(&opts); err != nil {
|
||||||
|
return fmt.Errorf("Error setting capacity to zero to drain: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next, wait for the autoscale group to drain
|
||||||
|
log.Printf("[DEBUG] Waiting for group to have zero instances")
|
||||||
|
return resource.Retry(10*time.Minute, func() error {
|
||||||
|
g, err := getAwsAutoscalingGroup(d, meta)
|
||||||
|
if err != nil {
|
||||||
|
return resource.RetryError{err}
|
||||||
|
}
|
||||||
|
if g == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(g.Instances) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf("group still has %d instances", len(g.Instances))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue