-
Notifications
You must be signed in to change notification settings - Fork 9.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1793 from ctiwald/ct/add-vpn-connection-route
provider/aws: add support for VPN connection routes
- Loading branch information
Showing
5 changed files
with
345 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
package aws | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
"strings" | ||
|
||
"github.com/awslabs/aws-sdk-go/aws" | ||
"github.com/awslabs/aws-sdk-go/service/ec2" | ||
|
||
"github.com/hashicorp/terraform/helper/schema" | ||
) | ||
|
||
func resourceAwsVpnConnectionRoute() *schema.Resource { | ||
return &schema.Resource{ | ||
// You can't update a route. You can just delete one and make | ||
// a new one. | ||
Create: resourceAwsVpnConnectionRouteCreate, | ||
Update: resourceAwsVpnConnectionRouteCreate, | ||
|
||
Read: resourceAwsVpnConnectionRouteRead, | ||
Delete: resourceAwsVpnConnectionRouteDelete, | ||
|
||
Schema: map[string]*schema.Schema{ | ||
"destination_cidr_block": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
}, | ||
|
||
"vpn_connection_id": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func resourceAwsVpnConnectionRouteCreate(d *schema.ResourceData, meta interface{}) error { | ||
conn := meta.(*AWSClient).ec2conn | ||
|
||
createOpts := &ec2.CreateVPNConnectionRouteInput{ | ||
DestinationCIDRBlock: aws.String(d.Get("destination_cidr_block").(string)), | ||
VPNConnectionID: aws.String(d.Get("vpn_connection_id").(string)), | ||
} | ||
|
||
// Create the route. | ||
log.Printf("[DEBUG] Creating VPN connection route") | ||
_, err := conn.CreateVPNConnectionRoute(createOpts) | ||
if err != nil { | ||
return fmt.Errorf("Error creating VPN connection route: %s", err) | ||
} | ||
|
||
// Store the ID by the only two data we have available to us. | ||
d.SetId(fmt.Sprintf("%s:%s", *createOpts.DestinationCIDRBlock, *createOpts.VPNConnectionID)) | ||
|
||
return resourceAwsVpnConnectionRouteRead(d, meta) | ||
} | ||
|
||
func resourceAwsVpnConnectionRouteRead(d *schema.ResourceData, meta interface{}) error { | ||
conn := meta.(*AWSClient).ec2conn | ||
|
||
cidrBlock, vpnConnectionId := resourceAwsVpnConnectionRouteParseId(d.Id()) | ||
|
||
routeFilters := []*ec2.Filter{ | ||
&ec2.Filter{ | ||
Name: aws.String("route.destination-cidr-block"), | ||
Values: []*string{aws.String(cidrBlock)}, | ||
}, | ||
&ec2.Filter{ | ||
Name: aws.String("vpn-connection-id"), | ||
Values: []*string{aws.String(vpnConnectionId)}, | ||
}, | ||
} | ||
|
||
// Technically, we know everything there is to know about the route | ||
// from its ID, but we still want to catch cases where it changes | ||
// outside of terraform and results in a stale state file. Hence, | ||
// conduct a read. | ||
resp, err := conn.DescribeVPNConnections(&ec2.DescribeVPNConnectionsInput{ | ||
Filters: routeFilters, | ||
}) | ||
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 route: %s", err) | ||
return err | ||
} | ||
} | ||
|
||
vpnConnection := resp.VPNConnections[0] | ||
|
||
var found bool | ||
for _, r := range vpnConnection.Routes { | ||
if *r.DestinationCIDRBlock == cidrBlock { | ||
d.Set("destination_cidr_block", *r.DestinationCIDRBlock) | ||
d.Set("vpn_connection_id", *vpnConnection.VPNConnectionID) | ||
found = true | ||
} | ||
} | ||
if !found { | ||
// Something other than terraform eliminated the route. | ||
d.SetId("") | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func resourceAwsVpnConnectionRouteDelete(d *schema.ResourceData, meta interface{}) error { | ||
conn := meta.(*AWSClient).ec2conn | ||
|
||
_, err := conn.DeleteVPNConnectionRoute(&ec2.DeleteVPNConnectionRouteInput{ | ||
DestinationCIDRBlock: aws.String(d.Get("destination_cidr_block").(string)), | ||
VPNConnectionID: aws.String(d.Get("vpn_connection_id").(string)), | ||
}) | ||
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 route: %s", err) | ||
return err | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func resourceAwsVpnConnectionRouteParseId(id string) (string, string) { | ||
parts := strings.SplitN(id, ":", 2) | ||
return parts[0], parts[1] | ||
} |
150 changes: 150 additions & 0 deletions
150
builtin/providers/aws/resource_vpn_connection_route_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
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 TestAccAwsVpnConnectionRoute(t *testing.T) { | ||
resource.Test(t, resource.TestCase{ | ||
PreCheck: func() { testAccPreCheck(t) }, | ||
Providers: testAccProviders, | ||
CheckDestroy: testAccAwsVpnConnectionRouteDestroy, | ||
Steps: []resource.TestStep{ | ||
resource.TestStep{ | ||
Config: testAccAwsVpnConnectionRouteConfig, | ||
Check: resource.ComposeTestCheckFunc( | ||
testAccAwsVpnConnectionRoute( | ||
"aws_vpn_gateway.vpn_gateway", | ||
"aws_customer_gateway.customer_gateway", | ||
"aws_vpn_connection.vpn_connection", | ||
"aws_vpn_connection_route.foo", | ||
), | ||
), | ||
}, | ||
resource.TestStep{ | ||
Config: testAccAwsVpnConnectionRouteConfigUpdate, | ||
Check: resource.ComposeTestCheckFunc( | ||
testAccAwsVpnConnectionRoute( | ||
"aws_vpn_gateway.vpn_gateway", | ||
"aws_customer_gateway.customer_gateway", | ||
"aws_vpn_connection.vpn_connection", | ||
"aws_vpn_connection_route.foo", | ||
), | ||
), | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func testAccAwsVpnConnectionRouteDestroy(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 testAccAwsVpnConnectionRoute( | ||
vpnGatewayResource string, | ||
customerGatewayResource string, | ||
vpnConnectionResource string, | ||
vpnConnectionRouteResource string) resource.TestCheckFunc { | ||
return func(s *terraform.State) error { | ||
rs, ok := s.RootModule().Resources[vpnConnectionRouteResource] | ||
if !ok { | ||
return fmt.Errorf("Not found: %s", vpnConnectionRouteResource) | ||
} | ||
|
||
if rs.Primary.ID == "" { | ||
return fmt.Errorf("No ID is set") | ||
} | ||
route, ok := s.RootModule().Resources[vpnConnectionRouteResource] | ||
if !ok { | ||
return fmt.Errorf("Not found: %s", vpnConnectionRouteResource) | ||
} | ||
|
||
cidrBlock, vpnConnectionId := resourceAwsVpnConnectionRouteParseId(route.Primary.ID) | ||
|
||
routeFilters := []*ec2.Filter{ | ||
&ec2.Filter{ | ||
Name: aws.String("route.destination-cidr-block"), | ||
Values: []*string{aws.String(cidrBlock)}, | ||
}, | ||
&ec2.Filter{ | ||
Name: aws.String("vpn-connection-id"), | ||
Values: []*string{aws.String(vpnConnectionId)}, | ||
}, | ||
} | ||
|
||
ec2conn := testAccProvider.Meta().(*AWSClient).ec2conn | ||
|
||
_, err := ec2conn.DescribeVPNConnections(&ec2.DescribeVPNConnectionsInput{ | ||
Filters: routeFilters, | ||
}) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} | ||
} | ||
|
||
const testAccAwsVpnConnectionRouteConfig = ` | ||
resource "aws_vpn_gateway" "vpn_gateway" { | ||
tags { | ||
Name = "vpn_gateway" | ||
} | ||
} | ||
resource "aws_customer_gateway" "customer_gateway" { | ||
bgp_asn = 60000 | ||
ip_address = "182.0.0.1" | ||
type = "ipsec.1" | ||
} | ||
resource "aws_vpn_connection" "vpn_connection" { | ||
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_route" "foo" { | ||
destination_cidr_block = "172.168.10.0/24" | ||
vpn_connection_id = "${aws_vpn_connection.vpn_connection.id}" | ||
} | ||
` | ||
|
||
// Change destination_cidr_block | ||
const testAccAwsVpnConnectionRouteConfigUpdate = ` | ||
resource "aws_vpn_gateway" "vpn_gateway" { | ||
tags { | ||
Name = "vpn_gateway" | ||
} | ||
} | ||
resource "aws_customer_gateway" "customer_gateway" { | ||
bgp_asn = 60000 | ||
ip_address = "182.0.0.1" | ||
type = "ipsec.1" | ||
} | ||
resource "aws_vpn_connection" "vpn_connection" { | ||
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_route" "foo" { | ||
destination_cidr_block = "172.168.20.0/24" | ||
vpn_connection_id = "${aws_vpn_connection.vpn_connection.id}" | ||
} | ||
` |
55 changes: 55 additions & 0 deletions
55
website/source/docs/providers/aws/r/vpc_connection_route.html.markdown
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
--- | ||
layout: "aws" | ||
page_title: "AWS: aws_vpn_connection_route" | ||
sidebar_current: "docs-aws-resource-vpn-connection-route" | ||
description: |- | ||
Provides a static route between a VPN connection and a customer gateway. | ||
--- | ||
|
||
# aws\_vpn\_connection\_route | ||
|
||
Provides a static route between a VPN connection and a customer gateway. | ||
|
||
## 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 | ||
} | ||
resource "aws_vpn_connection_route" "office" { | ||
destination_cidr_block = "192.168.10.0/24" | ||
vpn_connection_id = "${aws_vpn_connection.main.id}" | ||
} | ||
``` | ||
|
||
## Argument Reference | ||
|
||
The following arguments are supported: | ||
|
||
* `destination_cidr_block` - (Required) The CIDR block associated with the local subnet of the customer network. | ||
* `vpn_connection_id` - (Required) The ID of the VPN connection. | ||
|
||
## Attribute Reference | ||
|
||
The following attributes are exported: | ||
|
||
* `destination_cidr_block` - The CIDR block associated with the local subnet of the customer network. | ||
* `vpn_connection_id` - The ID of the VPN connection. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters