Merge pull request #1772 from ctiwald/ct/add-vpn-connection
Add support for AWS VPN connections.
This commit is contained in:
commit
199dabaf75
|
@ -107,6 +107,7 @@ func Provider() terraform.ResourceProvider {
|
||||||
"aws_vpc_peering_connection": resourceAwsVpcPeeringConnection(),
|
"aws_vpc_peering_connection": resourceAwsVpcPeeringConnection(),
|
||||||
"aws_vpc_dhcp_options": resourceAwsVpcDhcpOptions(),
|
"aws_vpc_dhcp_options": resourceAwsVpcDhcpOptions(),
|
||||||
"aws_vpc_dhcp_options_association": resourceAwsVpcDhcpOptionsAssociation(),
|
"aws_vpc_dhcp_options_association": resourceAwsVpcDhcpOptionsAssociation(),
|
||||||
|
"aws_vpn_connection": resourceAwsVpnConnection(),
|
||||||
"aws_vpn_gateway": resourceAwsVpnGateway(),
|
"aws_vpn_gateway": resourceAwsVpnGateway(),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,356 @@
|
||||||
|
package aws
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/awslabs/aws-sdk-go/aws"
|
||||||
|
"github.com/awslabs/aws-sdk-go/service/ec2"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/hashcode"
|
||||||
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
)
|
||||||
|
|
||||||
|
func resourceAwsVpnConnection() *schema.Resource {
|
||||||
|
return &schema.Resource{
|
||||||
|
Create: resourceAwsVpnConnectionCreate,
|
||||||
|
Read: resourceAwsVpnConnectionRead,
|
||||||
|
Update: resourceAwsVpnConnectionUpdate,
|
||||||
|
Delete: resourceAwsVpnConnectionDelete,
|
||||||
|
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"vpn_gateway_id": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"customer_gateway_id": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"type": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"static_routes_only": &schema.Schema{
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"tags": tagsSchema(),
|
||||||
|
|
||||||
|
// Begin read only attributes
|
||||||
|
"customer_gateway_configuration": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"routes": &schema.Schema{
|
||||||
|
Type: schema.TypeSet,
|
||||||
|
Computed: true,
|
||||||
|
Optional: true,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"destination_cidr_block": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"source": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"state": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Set: func(v interface{}) int {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
m := v.(map[string]interface{})
|
||||||
|
buf.WriteString(fmt.Sprintf("%s-", m["destination_cidr_block"].(string)))
|
||||||
|
buf.WriteString(fmt.Sprintf("%s-", m["source"].(string)))
|
||||||
|
buf.WriteString(fmt.Sprintf("%s-", m["state"].(string)))
|
||||||
|
return hashcode.String(buf.String())
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
"vgw_telemetry": &schema.Schema{
|
||||||
|
Type: schema.TypeSet,
|
||||||
|
Computed: true,
|
||||||
|
Optional: true,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"accepted_route_count": &schema.Schema{
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Computed: true,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"last_status_change": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"outside_ip_address": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"status": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"status_message": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Set: func(v interface{}) int {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
m := v.(map[string]interface{})
|
||||||
|
buf.WriteString(fmt.Sprintf("%s-", m["outside_ip_address"].(string)))
|
||||||
|
return hashcode.String(buf.String())
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceAwsVpnConnectionCreate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
conn := meta.(*AWSClient).ec2conn
|
||||||
|
|
||||||
|
connectOpts := &ec2.VPNConnectionOptionsSpecification{
|
||||||
|
StaticRoutesOnly: aws.Boolean(d.Get("static_routes_only").(bool)),
|
||||||
|
}
|
||||||
|
|
||||||
|
createOpts := &ec2.CreateVPNConnectionInput{
|
||||||
|
CustomerGatewayID: aws.String(d.Get("customer_gateway_id").(string)),
|
||||||
|
Options: connectOpts,
|
||||||
|
Type: aws.String(d.Get("type").(string)),
|
||||||
|
VPNGatewayID: aws.String(d.Get("vpn_gateway_id").(string)),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the VPN Connection
|
||||||
|
log.Printf("[DEBUG] Creating vpn connection")
|
||||||
|
resp, err := conn.CreateVPNConnection(createOpts)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error creating vpn connection: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store the ID
|
||||||
|
vpnConnection := resp.VPNConnection
|
||||||
|
d.SetId(*vpnConnection.VPNConnectionID)
|
||||||
|
log.Printf("[INFO] VPN connection ID: %s", *vpnConnection.VPNConnectionID)
|
||||||
|
|
||||||
|
// Wait for the connection to become available. This has an obscenely
|
||||||
|
// high default timeout because AWS VPN connections are notoriously
|
||||||
|
// slow at coming up or going down. There's also no point in checking
|
||||||
|
// more frequently than every ten seconds.
|
||||||
|
stateConf := &resource.StateChangeConf{
|
||||||
|
Pending: []string{"pending"},
|
||||||
|
Target: "available",
|
||||||
|
Refresh: vpnConnectionRefreshFunc(conn, *vpnConnection.VPNConnectionID),
|
||||||
|
Timeout: 30 * time.Minute,
|
||||||
|
Delay: 10 * time.Second,
|
||||||
|
MinTimeout: 10 * time.Second,
|
||||||
|
}
|
||||||
|
|
||||||
|
_, stateErr := stateConf.WaitForState()
|
||||||
|
if stateErr != nil {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"Error waiting for VPN connection (%s) to become ready: %s",
|
||||||
|
*vpnConnection.VPNConnectionID, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create tags.
|
||||||
|
if err := setTagsSDK(conn, d); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read off the API to populate our RO fields.
|
||||||
|
return resourceAwsVpnConnectionRead(d, meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
func vpnConnectionRefreshFunc(conn *ec2.EC2, connectionId string) resource.StateRefreshFunc {
|
||||||
|
return func() (interface{}, string, error) {
|
||||||
|
resp, err := conn.DescribeVPNConnections(&ec2.DescribeVPNConnectionsInput{
|
||||||
|
VPNConnectionIDs: []*string{aws.String(connectionId)},
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
if ec2err, ok := err.(aws.APIError); ok && ec2err.Code == "InvalidVpnConnectionID.NotFound" {
|
||||||
|
resp = nil
|
||||||
|
} else {
|
||||||
|
log.Printf("Error on VPNConnectionRefresh: %s", err)
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp == nil || len(resp.VPNConnections) == 0 {
|
||||||
|
return nil, "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
connection := resp.VPNConnections[0]
|
||||||
|
return connection, *connection.State, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceAwsVpnConnectionRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
conn := meta.(*AWSClient).ec2conn
|
||||||
|
|
||||||
|
resp, err := conn.DescribeVPNConnections(&ec2.DescribeVPNConnectionsInput{
|
||||||
|
VPNConnectionIDs: []*string{aws.String(d.Id())},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
if ec2err, ok := err.(aws.APIError); ok && ec2err.Code == "InvalidVpnConnectionID.NotFound" {
|
||||||
|
d.SetId("")
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
log.Printf("[ERROR] Error finding VPN connection: %s", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(resp.VPNConnections) != 1 {
|
||||||
|
return fmt.Errorf("[ERROR] Error finding VPN connection: %s", d.Id())
|
||||||
|
}
|
||||||
|
|
||||||
|
vpnConnection := resp.VPNConnections[0]
|
||||||
|
|
||||||
|
// Set attributes under the user's control.
|
||||||
|
d.Set("vpn_gateway_id", vpnConnection.VPNGatewayID)
|
||||||
|
d.Set("customer_gateway_id", vpnConnection.CustomerGatewayID)
|
||||||
|
d.Set("type", vpnConnection.Type)
|
||||||
|
d.Set("tags", tagsToMapSDK(vpnConnection.Tags))
|
||||||
|
|
||||||
|
if vpnConnection.Options != nil {
|
||||||
|
if err := d.Set("static_routes_only", vpnConnection.Options.StaticRoutesOnly); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set read only attributes.
|
||||||
|
d.Set("customer_gateway_configuration", vpnConnection.CustomerGatewayConfiguration)
|
||||||
|
if err := d.Set("vgw_telemetry", telemetryToMapList(vpnConnection.VGWTelemetry)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if vpnConnection.Routes != nil {
|
||||||
|
if err := d.Set("routes", routesToMapList(vpnConnection.Routes)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceAwsVpnConnectionUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
conn := meta.(*AWSClient).ec2conn
|
||||||
|
|
||||||
|
// Update tags if required.
|
||||||
|
if err := setTagsSDK(conn, d); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
d.SetPartial("tags")
|
||||||
|
|
||||||
|
return resourceAwsVpnConnectionRead(d, meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceAwsVpnConnectionDelete(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
conn := meta.(*AWSClient).ec2conn
|
||||||
|
|
||||||
|
_, err := conn.DeleteVPNConnection(&ec2.DeleteVPNConnectionInput{
|
||||||
|
VPNConnectionID: aws.String(d.Id()),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
if ec2err, ok := err.(aws.APIError); ok && ec2err.Code == "InvalidVpnConnectionID.NotFound" {
|
||||||
|
d.SetId("")
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
log.Printf("[ERROR] Error deleting VPN connection: %s", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// These things can take quite a while to tear themselves down and any
|
||||||
|
// attempt to modify resources they reference (e.g. CustomerGateways or
|
||||||
|
// VPN Gateways) before deletion will result in an error. Furthermore,
|
||||||
|
// they don't just disappear. The go into "deleted" state. We need to
|
||||||
|
// wait to ensure any other modifications the user might make to their
|
||||||
|
// VPC stack can safely run.
|
||||||
|
stateConf := &resource.StateChangeConf{
|
||||||
|
Pending: []string{"deleting"},
|
||||||
|
Target: "deleted",
|
||||||
|
Refresh: vpnConnectionRefreshFunc(conn, d.Id()),
|
||||||
|
Timeout: 30 * time.Minute,
|
||||||
|
Delay: 10 * time.Second,
|
||||||
|
MinTimeout: 10 * time.Second,
|
||||||
|
}
|
||||||
|
|
||||||
|
_, stateErr := stateConf.WaitForState()
|
||||||
|
if stateErr != nil {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"Error waiting for VPN connection (%s) to delete: %s", d.Id(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// routesToMapList turns the list of routes into a list of maps.
|
||||||
|
func routesToMapList(routes []*ec2.VPNStaticRoute) []map[string]interface{} {
|
||||||
|
result := make([]map[string]interface{}, 0, len(routes))
|
||||||
|
for _, r := range routes {
|
||||||
|
staticRoute := make(map[string]interface{})
|
||||||
|
staticRoute["destination_cidr_block"] = *r.DestinationCIDRBlock
|
||||||
|
staticRoute["state"] = *r.State
|
||||||
|
|
||||||
|
if r.Source != nil {
|
||||||
|
staticRoute["source"] = *r.Source
|
||||||
|
}
|
||||||
|
|
||||||
|
result = append(result, staticRoute)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// telemetryToMapList turns the VGW telemetry into a list of maps.
|
||||||
|
func telemetryToMapList(telemetry []*ec2.VGWTelemetry) []map[string]interface{} {
|
||||||
|
result := make([]map[string]interface{}, 0, len(telemetry))
|
||||||
|
for _, t := range telemetry {
|
||||||
|
vgw := make(map[string]interface{})
|
||||||
|
vgw["accepted_route_count"] = *t.AcceptedRouteCount
|
||||||
|
vgw["outside_ip_address"] = *t.OutsideIPAddress
|
||||||
|
vgw["status"] = *t.Status
|
||||||
|
vgw["status_message"] = *t.StatusMessage
|
||||||
|
|
||||||
|
// LastStatusChange is a time.Time(). Convert it into a string
|
||||||
|
// so it can be handled by schema's type system.
|
||||||
|
vgw["last_status_change"] = t.LastStatusChange.String()
|
||||||
|
result = append(result, vgw)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
|
@ -0,0 +1,138 @@
|
||||||
|
package aws
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/awslabs/aws-sdk-go/aws"
|
||||||
|
"github.com/awslabs/aws-sdk-go/service/ec2"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAccAwsVpnConnection(t *testing.T) {
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccAwsVpnConnectionDestroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccAwsVpnConnectionConfig,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccAwsVpnConnection(
|
||||||
|
"aws_vpc.vpc",
|
||||||
|
"aws_vpn_gateway.vpn_gateway",
|
||||||
|
"aws_customer_gateway.customer_gateway",
|
||||||
|
"aws_vpn_connection.foo",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccAwsVpnConnectionConfigUpdate,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccAwsVpnConnection(
|
||||||
|
"aws_vpc.vpc",
|
||||||
|
"aws_vpn_gateway.vpn_gateway",
|
||||||
|
"aws_customer_gateway.customer_gateway",
|
||||||
|
"aws_vpn_connection.bar",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccAwsVpnConnectionDestroy(s *terraform.State) error {
|
||||||
|
if len(s.RootModule().Resources) > 0 {
|
||||||
|
return fmt.Errorf("Expected all resources to be gone, but found: %#v", s.RootModule().Resources)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccAwsVpnConnection(
|
||||||
|
vpcResource string,
|
||||||
|
vpnGatewayResource string,
|
||||||
|
customerGatewayResource string,
|
||||||
|
vpnConnectionResource string) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
rs, ok := s.RootModule().Resources[vpnConnectionResource]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("Not found: %s", vpnConnectionResource)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rs.Primary.ID == "" {
|
||||||
|
return fmt.Errorf("No ID is set")
|
||||||
|
}
|
||||||
|
connection, ok := s.RootModule().Resources[vpnConnectionResource]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("Not found: %s", vpnConnectionResource)
|
||||||
|
}
|
||||||
|
|
||||||
|
ec2conn := testAccProvider.Meta().(*AWSClient).ec2conn
|
||||||
|
|
||||||
|
_, err := ec2conn.DescribeVPNConnections(&ec2.DescribeVPNConnectionsInput{
|
||||||
|
VPNConnectionIDs: []*string{aws.String(connection.Primary.ID)},
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const testAccAwsVpnConnectionConfig = `
|
||||||
|
resource "aws_vpc" "vpc" {
|
||||||
|
cidr_block = "10.0.0.0/16"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_vpn_gateway" "vpn_gateway" {
|
||||||
|
vpc_id = "${aws_vpc.vpc.id}"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_customer_gateway" "customer_gateway" {
|
||||||
|
bgp_asn = 60000
|
||||||
|
ip_address = "172.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
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
const testAccAwsVpnConnectionConfigUpdate = `
|
||||||
|
resource "aws_vpc" "vpc" {
|
||||||
|
cidr_block = "10.0.0.0/16"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_vpn_gateway" "vpn_gateway" {
|
||||||
|
vpc_id = "${aws_vpc.vpc.id}"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_customer_gateway" "customer_gateway" {
|
||||||
|
bgp_asn = 60000
|
||||||
|
ip_address = "172.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
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_vpn_connection" "bar" {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
`
|
|
@ -0,0 +1,58 @@
|
||||||
|
---
|
||||||
|
layout: "aws"
|
||||||
|
page_title: "AWS: aws_vpn_connection"
|
||||||
|
sidebar_current: "docs-aws-vpn-connection"
|
||||||
|
description: |-
|
||||||
|
Provides a VPN connection connected to a VPC. These objects can be connected to customer gateways, and allow you to establish tunnels between your network and the VPC.
|
||||||
|
---
|
||||||
|
|
||||||
|
# aws\_vpn\_connection
|
||||||
|
|
||||||
|
|
||||||
|
Provides a VPN connection connected to a VPC. These objects can be connected to customer gateways, and allow you to establish tunnels between your network and the VPC.
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
```
|
||||||
|
resource "aws_vpc" "vpc" {
|
||||||
|
cidr_block = "10.0.0.0/16"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_vpn_gateway" "vpn_gateway" {
|
||||||
|
vpc_id = "${aws_vpc.vpc.id}"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_customer_gateway" "customer_gateway" {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Argument Reference
|
||||||
|
|
||||||
|
The following arguments are supported:
|
||||||
|
|
||||||
|
* `customer_gateway_id` - (Required) The ID of the customer gateway.
|
||||||
|
* `static_routes_only` - (Required) Whether the VPN connection uses static routes exclusively. Static routes must be used for devices that don't support BGP. * `tags` - (Optional) Tags to apply to the connection.
|
||||||
|
* `type` - (Required) The type of VPN connection. The only type AWS supports at this time is "ipsec.1".
|
||||||
|
* `vpn_gateway_id` - (Required) The ID of the virtual private gateway.
|
||||||
|
|
||||||
|
## Attrubute Reference
|
||||||
|
|
||||||
|
The following attributes are exported:
|
||||||
|
|
||||||
|
* `id` - The amazon-assigned ID of the VPN connection.
|
||||||
|
* `customer_gateway_configuration` - The configuration information for the VPN connection's customer gateway (in the native XML format).
|
||||||
|
* `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.
|
||||||
|
* `type` - The type of VPN connection.
|
||||||
|
* `vpn_gateway_id` - The ID of the virtual private gateway to which the connection is attached.
|
|
@ -118,6 +118,13 @@
|
||||||
|
|
||||||
<li<%= sidebar_current("docs-aws-resource-vpc-dhcp-options-association") %>>
|
<li<%= sidebar_current("docs-aws-resource-vpc-dhcp-options-association") %>>
|
||||||
<a href="/docs/providers/aws/r/vpc_dhcp_options_association.html">aws_vpc_dhcp_options_association</a>
|
<a href="/docs/providers/aws/r/vpc_dhcp_options_association.html">aws_vpc_dhcp_options_association</a>
|
||||||
|
|
||||||
|
<li<%= sidebar_current("docs-aws-resource-vpn-connection") %>>
|
||||||
|
<a href="/docs/providers/aws/r/vpn_connection.html">aws_vpn_connection</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li<%= sidebar_current("docs-aws-resource-vpn-gateway") %>>
|
||||||
|
<a href="/docs/providers/aws/r/vpn_gateway.html">aws_vpn_gateway</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li<%= sidebar_current("docs-aws-resource-vpn-gateway") %>>
|
<li<%= sidebar_current("docs-aws-resource-vpn-gateway") %>>
|
||||||
|
|
Loading…
Reference in New Issue