Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

provider/aws: Expose additional VPN Connection attributes. #5032

Merged
merged 3 commits into from
Feb 12, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 75 additions & 0 deletions builtin/providers/aws/resource_aws_vpn_connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ package aws

import (
"bytes"
"encoding/xml"
"fmt"
"log"
"sort"
"time"

"github.com/aws/aws-sdk-go/aws"
Expand All @@ -15,6 +17,34 @@ import (
"github.com/hashicorp/terraform/helper/schema"
)

type XmlVpnConnectionConfig struct {
Tunnels []XmlIpsecTunnel `xml:"ipsec_tunnel"`
}

type XmlIpsecTunnel struct {
OutsideAddress string `xml:"vpn_gateway>tunnel_outside_address>ip_address"`
PreSharedKey string `xml:"ike>pre_shared_key"`
}

type TunnelInfo struct {
Tunnel1Address string
Tunnel1PreSharedKey string
Tunnel2Address string
Tunnel2PreSharedKey string
}

func (slice XmlVpnConnectionConfig) Len() int {
return len(slice.Tunnels)
}

func (slice XmlVpnConnectionConfig) Less(i, j int) bool {
return slice.Tunnels[i].OutsideAddress < slice.Tunnels[j].OutsideAddress
}

func (slice XmlVpnConnectionConfig) Swap(i, j int) {
slice.Tunnels[i], slice.Tunnels[j] = slice.Tunnels[j], slice.Tunnels[i]
}

func resourceAwsVpnConnection() *schema.Resource {
return &schema.Resource{
Create: resourceAwsVpnConnectionCreate,
Expand Down Expand Up @@ -56,6 +86,26 @@ func resourceAwsVpnConnection() *schema.Resource {
Optional: true,
},

"tunnel1_address": &schema.Schema{
Type: schema.TypeString,
Computed: true,
},

"tunnel1_preshared_key": &schema.Schema{
Type: schema.TypeString,
Computed: true,
},

"tunnel2_address": &schema.Schema{
Type: schema.TypeString,
Computed: true,
},

"tunnel2_preshared_key": &schema.Schema{
Type: schema.TypeString,
Computed: true,
},

"routes": &schema.Schema{
Type: schema.TypeSet,
Computed: true,
Expand Down Expand Up @@ -254,6 +304,13 @@ func resourceAwsVpnConnectionRead(d *schema.ResourceData, meta interface{}) erro

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

tunnelInfo := xmlConfigToTunnelInfo(*vpnConnection.CustomerGatewayConfiguration)
d.Set("tunnel1_address", tunnelInfo.Tunnel1Address)
d.Set("tunnel1_preshared_key", tunnelInfo.Tunnel1PreSharedKey)
d.Set("tunnel2_address", tunnelInfo.Tunnel2Address)
d.Set("tunnel2_preshared_key", tunnelInfo.Tunnel2PreSharedKey)

if err := d.Set("vgw_telemetry", telemetryToMapList(vpnConnection.VgwTelemetry)); err != nil {
return err
}
Expand Down Expand Up @@ -355,3 +412,21 @@ func telemetryToMapList(telemetry []*ec2.VgwTelemetry) []map[string]interface{}

return result
}

func xmlConfigToTunnelInfo(xmlConfig string) TunnelInfo {
var vpnConfig XmlVpnConnectionConfig
xml.Unmarshal([]byte(xmlConfig), &vpnConfig)

// don't expect consistent ordering from the XML
sort.Sort(vpnConfig)

tunnelInfo := TunnelInfo{
Tunnel1Address: vpnConfig.Tunnels[0].OutsideAddress,
Tunnel1PreSharedKey: vpnConfig.Tunnels[0].PreSharedKey,

Tunnel2Address: vpnConfig.Tunnels[1].OutsideAddress,
Tunnel2PreSharedKey: vpnConfig.Tunnels[1].PreSharedKey,
}

return tunnelInfo
}
82 changes: 62 additions & 20 deletions builtin/providers/aws/resource_aws_vpn_connection_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,45 +117,87 @@ func testAccAwsVpnConnection(
}
}

func TestAccAWSVpnConnection_xmlconfig(t *testing.T) {
tunnelInfo := xmlConfigToTunnelInfo(testAccAwsVpnTunnelInfoXML)
if tunnelInfo.Tunnel1Address != "FIRST_ADDRESS" {
t.Fatalf("First address from tunnel XML was incorrect.")
}
if tunnelInfo.Tunnel1PreSharedKey != "FIRST_KEY" {
t.Fatalf("First key from tunnel XML was incorrect.")
}
if tunnelInfo.Tunnel2Address != "SECOND_ADDRESS" {
t.Fatalf("Second address from tunnel XML was incorrect.")
}
if tunnelInfo.Tunnel2PreSharedKey != "SECOND_KEY" {
t.Fatalf("Second key from tunnel XML was incorrect.")
}
}

const testAccAwsVpnConnectionConfig = `
resource "aws_vpn_gateway" "vpn_gateway" {
tags {
Name = "vpn_gateway"
}
tags {
Name = "vpn_gateway"
}
}

resource "aws_customer_gateway" "customer_gateway" {
bgp_asn = 60000
ip_address = "178.0.0.1"
type = "ipsec.1"
bgp_asn = 60000
ip_address = "178.0.0.1"
type = "ipsec.1"
}

resource "aws_vpn_connection" "foo" {
vpn_gateway_id = "${aws_vpn_gateway.vpn_gateway.id}"
customer_gateway_id = "${aws_customer_gateway.customer_gateway.id}"
type = "ipsec.1"
static_routes_only = true
vpn_gateway_id = "${aws_vpn_gateway.vpn_gateway.id}"
customer_gateway_id = "${aws_customer_gateway.customer_gateway.id}"
type = "ipsec.1"
static_routes_only = true
}
`

// Change static_routes_only to be false, forcing a refresh.
const testAccAwsVpnConnectionConfigUpdate = `
resource "aws_vpn_gateway" "vpn_gateway" {
tags {
Name = "vpn_gateway"
}
tags {
Name = "vpn_gateway"
}
}

resource "aws_customer_gateway" "customer_gateway" {
bgp_asn = 60000
ip_address = "178.0.0.1"
type = "ipsec.1"
bgp_asn = 60000
ip_address = "178.0.0.1"
type = "ipsec.1"
}

resource "aws_vpn_connection" "foo" {
vpn_gateway_id = "${aws_vpn_gateway.vpn_gateway.id}"
customer_gateway_id = "${aws_customer_gateway.customer_gateway.id}"
type = "ipsec.1"
static_routes_only = false
vpn_gateway_id = "${aws_vpn_gateway.vpn_gateway.id}"
customer_gateway_id = "${aws_customer_gateway.customer_gateway.id}"
type = "ipsec.1"
static_routes_only = false
}
`

// Test our VPN tunnel config XML parsing
const testAccAwsVpnTunnelInfoXML = `
<vpn_connection id="vpn-abc123">
<ipsec_tunnel>
<vpn_gateway>
<tunnel_outside_address>
<ip_address>SECOND_ADDRESS</ip_address>
</tunnel_outside_address>
</vpn_gateway>
<ike>
<pre_shared_key>SECOND_KEY</pre_shared_key>
</ike>
</ipsec_tunnel>
<ipsec_tunnel>
<vpn_gateway>
<tunnel_outside_address>
<ip_address>FIRST_ADDRESS</ip_address>
</tunnel_outside_address>
</vpn_gateway>
<ike>
<pre_shared_key>FIRST_KEY</pre_shared_key>
</ike>
</ipsec_tunnel>
</vpn_connection>
`
22 changes: 13 additions & 9 deletions website/source/docs/providers/aws/r/vpn_connection.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,24 @@ Provides a VPN connection connected to a VPC. These objects can be connected to

```
resource "aws_vpc" "vpc" {
cidr_block = "10.0.0.0/16"
cidr_block = "10.0.0.0/16"
}

resource "aws_vpn_gateway" "vpn_gateway" {
vpc_id = "${aws_vpc.vpc.id}"
vpc_id = "${aws_vpc.vpc.id}"
}

resource "aws_customer_gateway" "customer_gateway" {
bgp_asn = 60000
ip_address = "172.0.0.1"
type = "ipsec.1"
bgp_asn = 60000
ip_address = "172.0.0.1"
type = "ipsec.1"
}

resource "aws_vpn_connection" "main" {
vpn_gateway_id = "${aws_vpn_gateway.vpn_gateway.id}"
customer_gateway_id = "${aws_customer_gateway.customer_gateway.id}"
type = "ipsec.1"
static_routes_only = true
vpn_gateway_id = "${aws_vpn_gateway.vpn_gateway.id}"
customer_gateway_id = "${aws_customer_gateway.customer_gateway.id}"
type = "ipsec.1"
static_routes_only = true
}
```

Expand All @@ -55,5 +55,9 @@ 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.
* `tunnel1_address` - The public IP address of the first VPN tunnel.
* `tunnel1_preshared_key` - The preshared key of the first VPN tunnel.
* `tunnel2_address` - The public IP address of the second VPN tunnel.
* `tunnel2_preshared_key` - The preshared key of the second VPN tunnel.
* `type` - The type of VPN connection.
* `vpn_gateway_id` - The ID of the virtual private gateway to which the connection is attached.