From a58650c9803723de0f8ab9fe36124aa22727f27c Mon Sep 17 00:00:00 2001 From: Krzysztof Wilczynski Date: Sun, 25 Sep 2016 15:30:10 +0100 Subject: [PATCH] Make sure that VPC Peering Connection in a failed state returns an error. This commit adds simple logic which allows for a VPC Peering Connection that is in a failed state (e.g. due to an overlapping IP address ranges, etc.), to report such failed state as an error, rather then waiting for the time out to occur. Signed-off-by: Krzysztof Wilczynski --- .../resource_aws_vpc_peering_connection.go | 52 +++++++++++-------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/builtin/providers/aws/resource_aws_vpc_peering_connection.go b/builtin/providers/aws/resource_aws_vpc_peering_connection.go index c6bc632e4b..370300cb4a 100644 --- a/builtin/providers/aws/resource_aws_vpc_peering_connection.go +++ b/builtin/providers/aws/resource_aws_vpc_peering_connection.go @@ -1,6 +1,7 @@ package aws import ( + "errors" "fmt" "log" "time" @@ -24,27 +25,27 @@ func resourceAwsVpcPeeringConnection() *schema.Resource { }, Schema: map[string]*schema.Schema{ - "peer_owner_id": &schema.Schema{ + "peer_owner_id": { Type: schema.TypeString, Optional: true, ForceNew: true, Computed: true, }, - "peer_vpc_id": &schema.Schema{ + "peer_vpc_id": { Type: schema.TypeString, Required: true, ForceNew: true, }, - "vpc_id": &schema.Schema{ + "vpc_id": { Type: schema.TypeString, Required: true, ForceNew: true, }, - "auto_accept": &schema.Schema{ + "auto_accept": { Type: schema.TypeBool, Optional: true, }, - "accept_status": &schema.Schema{ + "accept_status": { Type: schema.TypeString, Computed: true, }, @@ -89,9 +90,9 @@ func resourceAwsVPCPeeringCreate(d *schema.ResourceData, meta interface{}) error Timeout: 1 * time.Minute, } if _, err := stateConf.WaitForState(); err != nil { - return fmt.Errorf( - "Error waiting for VPC Peering Connection (%s) to become available: %s", - d.Id(), err) + return errwrap.Wrapf(fmt.Sprintf( + "Error waiting for VPC Peering Connection (%s) to become available: {{err}}", + d.Id()), err) } return resourceAwsVPCPeeringUpdate(d, meta) @@ -99,8 +100,10 @@ func resourceAwsVPCPeeringCreate(d *schema.ResourceData, meta interface{}) error func resourceAwsVPCPeeringRead(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).ec2conn - pcRaw, _, err := resourceAwsVPCPeeringConnectionStateRefreshFunc(conn, d.Id())() - if err != nil { + pcRaw, status, err := resourceAwsVPCPeeringConnectionStateRefreshFunc(conn, d.Id())() + // Allow a failed VPC Peering Connection to fallthrough, + // to allow rest of the logic below to do its work. + if err != nil && status != "failed" { return err } @@ -139,23 +142,23 @@ func resourceAwsVPCPeeringRead(d *schema.ResourceData, meta interface{}) error { // When the VPC Peering Connection is pending acceptance, // the details about accepter and/or requester peering // options would not be included in the response. - if pc.AccepterVpcInfo != nil && pc.AccepterVpcInfo.PeeringOptions != nil { + if pc.AccepterVpcInfo.PeeringOptions != nil { err := d.Set("accepter", flattenPeeringOptions(pc.AccepterVpcInfo.PeeringOptions)) if err != nil { - log.Printf("[ERR] Error setting VPC Peering connection accepter information: %s", err) + return errwrap.Wrapf("Error setting VPC Peering Connection accepter information: {{err}}", err) } } - if pc.RequesterVpcInfo != nil && pc.RequesterVpcInfo.PeeringOptions != nil { + if pc.RequesterVpcInfo.PeeringOptions != nil { err := d.Set("requester", flattenPeeringOptions(pc.RequesterVpcInfo.PeeringOptions)) if err != nil { - log.Printf("[ERR] Error setting VPC Peering connection requester information: %s", err) + return errwrap.Wrapf("Error setting VPC Peering Connection requester information: {{err}}", err) } } err = d.Set("tags", tagsToMap(pc.Tags)) if err != nil { - return err + return errwrap.Wrapf("Error setting VPC Peering Connection tags: {{err}}", err) } return nil @@ -219,6 +222,7 @@ func resourceAwsVPCPeeringUpdate(d *schema.ResourceData, meta interface{}) error if err != nil { return err } + if pcRaw == nil { d.SetId("") return nil @@ -229,7 +233,7 @@ func resourceAwsVPCPeeringUpdate(d *schema.ResourceData, meta interface{}) error if pc.Status != nil && *pc.Status.Code == "pending-acceptance" { status, err := resourceVPCPeeringConnectionAccept(conn, d.Id()) if err != nil { - return err + return errwrap.Wrapf("Unable to accept VPC Peering Connection: {{err}}", err) } log.Printf("[DEBUG] VPC Peering Connection accept status: %s", status) } @@ -266,7 +270,6 @@ func resourceAwsVPCPeeringDelete(d *schema.ResourceData, meta interface{}) error // a VPCPeeringConnection. func resourceAwsVPCPeeringConnectionStateRefreshFunc(conn *ec2.EC2, id string) resource.StateRefreshFunc { return func() (interface{}, string, error) { - resp, err := conn.DescribeVpcPeeringConnections(&ec2.DescribeVpcPeeringConnectionsInput{ VpcPeeringConnectionIds: []*string{aws.String(id)}, }) @@ -275,7 +278,7 @@ func resourceAwsVPCPeeringConnectionStateRefreshFunc(conn *ec2.EC2, id string) r resp = nil } else { log.Printf("Error reading VPC Peering Connection details: %s", err) - return nil, "", err + return nil, "error", err } } @@ -287,6 +290,13 @@ func resourceAwsVPCPeeringConnectionStateRefreshFunc(conn *ec2.EC2, id string) r pc := resp.VpcPeeringConnections[0] + // A VPC Peering Connection can exist in a failed state due to + // incorrect VPC ID, account ID, or overlapping IP address range, + // thus we short circuit before the time out would occur. + if pc != nil && *pc.Status.Code == "failed" { + return nil, "failed", errors.New(*pc.Status.Message) + } + return pc, *pc.Status.Code, nil } } @@ -299,17 +309,17 @@ func vpcPeeringConnectionOptionsSchema() *schema.Schema { MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "allow_remote_vpc_dns_resolution": &schema.Schema{ + "allow_remote_vpc_dns_resolution": { Type: schema.TypeBool, Optional: true, Default: false, }, - "allow_classic_link_to_remote_vpc": &schema.Schema{ + "allow_classic_link_to_remote_vpc": { Type: schema.TypeBool, Optional: true, Default: false, }, - "allow_vpc_to_remote_classic_link": &schema.Schema{ + "allow_vpc_to_remote_classic_link": { Type: schema.TypeBool, Optional: true, Default: false,