Skip to content

Commit

Permalink
Merge pull request #8070 from terraform-providers/f-aws_vpn_connectio…
Browse files Browse the repository at this point in the history
…n-transit_gateway_attachment_id

resource/aws_vpn_connection: Add transit_gateway_attachment_id attribute
  • Loading branch information
bflad authored Mar 25, 2019
2 parents 61dbbbd + 55a59e8 commit b89693a
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 12 deletions.
71 changes: 60 additions & 11 deletions aws/resource_aws_vpn_connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,11 @@ func resourceAwsVpnConnection() *schema.Resource {
ForceNew: true,
},

"transit_gateway_attachment_id": {
Type: schema.TypeString,
Computed: true,
},

"transit_gateway_id": {
Type: schema.TypeString,
Optional: true,
Expand Down Expand Up @@ -375,27 +380,70 @@ func resourceAwsVpnConnectionRead(d *schema.ResourceData, meta interface{}) erro
resp, err := conn.DescribeVpnConnections(&ec2.DescribeVpnConnectionsInput{
VpnConnectionIds: []*string{aws.String(d.Id())},
})

if isAWSErr(err, "InvalidVpnConnectionID.NotFound", "") {
log.Printf("[WARN] EC2 VPN Connection (%s) not found, removing from state", d.Id())
d.SetId("")
return nil
}

if err != nil {
if ec2err, ok := err.(awserr.Error); ok && ec2err.Code() == "InvalidVpnConnectionID.NotFound" {
d.SetId("")
return nil
} else {
log.Printf("[ERROR] Error finding VPN connection: %s", err)
return err
}
return fmt.Errorf("error reading EC2 VPN Connection (%s): %s", d.Id(), err)
}

if resp == nil || len(resp.VpnConnections) == 0 || resp.VpnConnections[0] == nil {
return fmt.Errorf("error reading EC2 VPN Connection (%s): empty response", d.Id())
}

if len(resp.VpnConnections) != 1 {
return fmt.Errorf("Error finding VPN connection: %s", d.Id())
if len(resp.VpnConnections) > 1 {
return fmt.Errorf("error reading EC2 VPN Connection (%s): multiple responses", d.Id())
}

vpnConnection := resp.VpnConnections[0]
if vpnConnection == nil || *vpnConnection.State == "deleted" {
// Seems we have lost our VPN Connection

if aws.StringValue(vpnConnection.State) == ec2.VpnStateDeleted {
log.Printf("[WARN] EC2 VPN Connection (%s) already deleted, removing from state", d.Id())
d.SetId("")
return nil
}

var transitGatewayAttachmentID string
if vpnConnection.TransitGatewayId != nil {
input := &ec2.DescribeTransitGatewayAttachmentsInput{
Filters: []*ec2.Filter{
{
Name: aws.String("resource-id"),
Values: []*string{vpnConnection.VpnConnectionId},
},
{
Name: aws.String("resource-type"),
Values: []*string{aws.String(ec2.TransitGatewayAttachmentResourceTypeVpn)},
},
{
Name: aws.String("transit-gateway-id"),
Values: []*string{vpnConnection.TransitGatewayId},
},
},
}

log.Printf("[DEBUG] Finding EC2 VPN Connection Transit Gateway Attachment: %s", input)
output, err := conn.DescribeTransitGatewayAttachments(input)

if err != nil {
return fmt.Errorf("error finding EC2 VPN Connection (%s) Transit Gateway Attachment: %s", d.Id(), err)
}

if output == nil || len(output.TransitGatewayAttachments) == 0 || output.TransitGatewayAttachments[0] == nil {
return fmt.Errorf("error finding EC2 VPN Connection (%s) Transit Gateway Attachment: empty response", d.Id())
}

if len(output.TransitGatewayAttachments) > 1 {
return fmt.Errorf("error reading EC2 VPN Connection (%s) Transit Gateway Attachment: multiple responses", d.Id())
}

transitGatewayAttachmentID = aws.StringValue(output.TransitGatewayAttachments[0].TransitGatewayAttachmentId)
}

// Set attributes under the user's control.
d.Set("vpn_gateway_id", vpnConnection.VpnGatewayId)
d.Set("customer_gateway_id", vpnConnection.CustomerGatewayId)
Expand All @@ -414,6 +462,7 @@ func resourceAwsVpnConnectionRead(d *schema.ResourceData, meta interface{}) erro

// Set read only attributes.
d.Set("customer_gateway_configuration", vpnConnection.CustomerGatewayConfiguration)
d.Set("transit_gateway_attachment_id", transitGatewayAttachmentID)

if vpnConnection.CustomerGatewayConfiguration != nil {
if tunnelInfo, err := xmlConfigToTunnelInfo(*vpnConnection.CustomerGatewayConfiguration); err != nil {
Expand Down
9 changes: 8 additions & 1 deletion aws/resource_aws_vpn_connection_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ func TestAccAWSVpnConnection_basic(t *testing.T) {
Config: testAccAwsVpnConnectionConfig(rBgpAsn),
Check: resource.ComposeTestCheckFunc(
testAccAwsVpnConnectionExists("aws_vpn_connection.foo", &vpn),
resource.TestCheckResourceAttr("aws_vpn_connection.foo", "transit_gateway_attachment_id", ""),
),
},
{
Expand All @@ -66,17 +67,23 @@ func TestAccAWSVpnConnection_basic(t *testing.T) {
func TestAccAWSVpnConnection_TransitGatewayID(t *testing.T) {
var vpn ec2.VpnConnection
rBgpAsn := acctest.RandIntRange(64512, 65534)
transitGatewayResourceName := "aws_ec2_transit_gateway.test"
resourceName := "aws_vpn_connection.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
PreCheck: func() {
testAccPreCheck(t)
testAccPreCheckAWSEc2TransitGateway(t)
},
Providers: testAccProviders,
CheckDestroy: testAccAwsVpnConnectionDestroy,
Steps: []resource.TestStep{
{
Config: testAccAwsVpnConnectionConfigTransitGatewayID(rBgpAsn),
Check: resource.ComposeTestCheckFunc(
testAccAwsVpnConnectionExists(resourceName, &vpn),
resource.TestMatchResourceAttr(resourceName, "transit_gateway_attachment_id", regexp.MustCompile(`tgw-attach-.+`)),
resource.TestCheckResourceAttrPair(resourceName, "transit_gateway_id", transitGatewayResourceName, "id"),
),
},
},
Expand Down
1 change: 1 addition & 0 deletions website/docs/r/vpn_connection.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ In addition to all arguments above, the following attributes are exported:
* `customer_gateway_id` - The ID of the customer gateway to which the connection is attached.
* `static_routes_only` - Whether the VPN connection uses static routes exclusively.
* `tags` - Tags applied to the connection.
* `transit_gateway_attachment_id` - When associated with an EC2 Transit Gateway (`transit_gateway_id` argument), the attachment ID.
* `tunnel1_address` - The public IP address of the first VPN tunnel.
* `tunnel1_cgw_inside_address` - The RFC 6890 link-local address of the first VPN tunnel (Customer Gateway Side).
* `tunnel1_vgw_inside_address` - The RFC 6890 link-local address of the first VPN tunnel (VPN Gateway Side).
Expand Down

0 comments on commit b89693a

Please sign in to comment.