diff --git a/CHANGELOG.md b/CHANGELOG.md index 66560bd13..424daec0a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,8 @@ BUG FIXES: * providers/aws: Refreshing EIP from pre-0.2 state file won't error. [GH-258] * providers/aws: Creating EIP without an instance/network won't fail. * providers/aws: Refreshing EIP manually deleted works. + * providers/aws: Retry EIP delete to allow AWS eventual consistency to + detect it isn't attached. [GH-276] * providers/digitalocean: Handle situations when resource was destroyed manually. [GH-279] * providers/digitalocean: Fix a couple scenarios where the diff was diff --git a/builtin/providers/aws/resource_aws_eip.go b/builtin/providers/aws/resource_aws_eip.go index 71732d067..d7c9382b4 100644 --- a/builtin/providers/aws/resource_aws_eip.go +++ b/builtin/providers/aws/resource_aws_eip.go @@ -4,7 +4,9 @@ import ( "fmt" "log" "strings" + "time" + "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/helper/schema" //"github.com/hashicorp/terraform/terraform" "github.com/mitchellh/goamz/ec2" @@ -125,20 +127,14 @@ func resourceAwsEipUpdate(d *schema.ResourceData, meta interface{}) error { } func resourceAwsEipDelete(d *schema.ResourceData, meta interface{}) error { - p := meta.(*ResourceProvider) - ec2conn := p.ec2conn - - domain := resourceAwsEipDomain(d) - - var err error - if domain == "vpc" { - log.Printf("[DEBUG] EIP release (destroy) address allocation: %v", d.Id()) - _, err = ec2conn.ReleaseAddress(d.Id()) - return err + stateConf := &resource.StateChangeConf{ + Pending: []string{"pending"}, + Target: "destroyed", + Refresh: resourceEipDeleteRefreshFunc(d, meta), + Timeout: 3 * time.Minute, + MinTimeout: 1 * time.Second, } - - log.Printf("[DEBUG] EIP release (destroy) address: %v", d.Id()) - _, err = ec2conn.ReleasePublicAddress(d.Id()) + _, err := stateConf.WaitForState() return err } @@ -200,3 +196,38 @@ func resourceAwsEipDomain(d *schema.ResourceData) string { return "standard" } + +func resourceEipDeleteRefreshFunc( + d *schema.ResourceData, + meta interface{}) resource.StateRefreshFunc { + p := meta.(*ResourceProvider) + ec2conn := p.ec2conn + domain := resourceAwsEipDomain(d) + + return func() (interface{}, string, error) { + var err error + if domain == "vpc" { + log.Printf( + "[DEBUG] EIP release (destroy) address allocation: %v", + d.Id()) + _, err = ec2conn.ReleaseAddress(d.Id()) + } else { + log.Printf("[DEBUG] EIP release (destroy) address: %v", d.Id()) + _, err = ec2conn.ReleasePublicAddress(d.Id()) + } + + if err == nil { + return d, "destroyed", nil + } + + ec2err, ok := err.(*ec2.Error) + if !ok { + return d, "error", err + } + if ec2err.Code != "InvalidIPAddress.InUse" { + return d, "error", err + } + + return d, "pending", nil + } +}