From 8d964901231fcc887e9fa95e48e4109972f43024 Mon Sep 17 00:00:00 2001 From: Radek Simko Date: Fri, 30 Jun 2017 13:48:32 +0100 Subject: [PATCH] r/internet_gateway: Retry properly on DependencyViolation --- aws/resource_aws_internet_gateway.go | 35 ++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/aws/resource_aws_internet_gateway.go b/aws/resource_aws_internet_gateway.go index 3834aa58e4bd..a86f11670cbe 100644 --- a/aws/resource_aws_internet_gateway.go +++ b/aws/resource_aws_internet_gateway.go @@ -265,23 +265,50 @@ func detachIGStateRefreshFunc(conn *ec2.EC2, gatewayID, vpcID string) resource.S switch ec2err.Code() { case "InvalidInternetGatewayID.NotFound": log.Printf("[TRACE] Error detaching Internet Gateway '%s' from VPC '%s': %s", gatewayID, vpcID, err) - return nil, "Not Found", nil + return nil, "", nil case "Gateway.NotAttached": - return "detached", "detached", nil + return 42, "detached", nil case "DependencyViolation": - return nil, "detaching", nil + // This can be caused by associated public IPs left (e.g. by ELBs) + // and here we find and log which ones are to blame + out, err := findPublicNetworkInterfacesForVpcID(conn, vpcID) + if err != nil { + return 42, "detaching", err + } + if len(out.NetworkInterfaces) > 0 { + log.Printf("[DEBUG] Waiting for the following %d ENIs to be gone: %s", + len(out.NetworkInterfaces), out.NetworkInterfaces) + } + + return 42, "detaching", nil } } + return 42, "", err } // DetachInternetGateway only returns an error, so if it's nil, assume we're // detached - return "detached", "detached", nil + return 42, "detached", nil } } +func findPublicNetworkInterfacesForVpcID(conn *ec2.EC2, vpcID string) (*ec2.DescribeNetworkInterfacesOutput, error) { + return conn.DescribeNetworkInterfaces(&ec2.DescribeNetworkInterfacesInput{ + Filters: []*ec2.Filter{ + { + Name: aws.String("vpc-id"), + Values: []*string{aws.String(vpcID)}, + }, + { + Name: aws.String("association.public-ip"), + Values: []*string{aws.String("*")}, + }, + }, + }) +} + // IGStateRefreshFunc returns a resource.StateRefreshFunc that is used to watch // an internet gateway. func IGStateRefreshFunc(conn *ec2.EC2, id string) resource.StateRefreshFunc {