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 <krzysztof.wilczynski@linux.com>
This commit is contained in:
Krzysztof Wilczynski 2016-09-25 15:30:10 +01:00
parent 0edb68ef5a
commit a58650c980
No known key found for this signature in database
GPG Key ID: B89F6447B63419A6
1 changed files with 31 additions and 21 deletions

View File

@ -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,