Add aws_vpn_gateway_attachment resource. (#7870)
This commit adds VPN Gateway attachment resource, and also an initial tests and documentation stubs. Signed-off-by: Krzysztof Wilczynski <krzysztof.wilczynski@linux.com>
This commit is contained in:
parent
de822d909c
commit
9c54e9c955
|
@ -282,6 +282,7 @@ func Provider() terraform.ResourceProvider {
|
||||||
"aws_vpn_connection": resourceAwsVpnConnection(),
|
"aws_vpn_connection": resourceAwsVpnConnection(),
|
||||||
"aws_vpn_connection_route": resourceAwsVpnConnectionRoute(),
|
"aws_vpn_connection_route": resourceAwsVpnConnectionRoute(),
|
||||||
"aws_vpn_gateway": resourceAwsVpnGateway(),
|
"aws_vpn_gateway": resourceAwsVpnGateway(),
|
||||||
|
"aws_vpn_gateway_attachment": resourceAwsVpnGatewayAttachment(),
|
||||||
},
|
},
|
||||||
ConfigureFunc: providerConfigure,
|
ConfigureFunc: providerConfigure,
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@ func resourceAwsVpnGateway() *schema.Resource {
|
||||||
"vpc_id": &schema.Schema{
|
"vpc_id": &schema.Schema{
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
"tags": tagsSchema(),
|
"tags": tagsSchema(),
|
||||||
|
@ -80,17 +81,18 @@ func resourceAwsVpnGatewayRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
vpnGateway := resp.VpnGateways[0]
|
vpnGateway := resp.VpnGateways[0]
|
||||||
if vpnGateway == nil {
|
if vpnGateway == nil || *vpnGateway.State == "deleted" {
|
||||||
// Seems we have lost our VPN gateway
|
// Seems we have lost our VPN gateway
|
||||||
d.SetId("")
|
d.SetId("")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(vpnGateway.VpcAttachments) == 0 || *vpnGateway.VpcAttachments[0].State == "detached" || *vpnGateway.VpcAttachments[0].State == "deleted" {
|
vpnAttachment := vpnGatewayGetAttachment(vpnGateway)
|
||||||
|
if len(vpnGateway.VpcAttachments) == 0 || *vpnAttachment.State == "detached" {
|
||||||
// Gateway exists but not attached to the VPC
|
// Gateway exists but not attached to the VPC
|
||||||
d.Set("vpc_id", "")
|
d.Set("vpc_id", "")
|
||||||
} else {
|
} else {
|
||||||
d.Set("vpc_id", vpnGateway.VpcAttachments[0].VpcId)
|
d.Set("vpc_id", *vpnAttachment.VpcId)
|
||||||
}
|
}
|
||||||
d.Set("availability_zone", vpnGateway.AvailabilityZone)
|
d.Set("availability_zone", vpnGateway.AvailabilityZone)
|
||||||
d.Set("tags", tagsToMap(vpnGateway.Tags))
|
d.Set("tags", tagsToMap(vpnGateway.Tags))
|
||||||
|
@ -301,12 +303,21 @@ func vpnGatewayAttachStateRefreshFunc(conn *ec2.EC2, id string, expected string)
|
||||||
}
|
}
|
||||||
|
|
||||||
vpnGateway := resp.VpnGateways[0]
|
vpnGateway := resp.VpnGateways[0]
|
||||||
|
|
||||||
if len(vpnGateway.VpcAttachments) == 0 {
|
if len(vpnGateway.VpcAttachments) == 0 {
|
||||||
// No attachments, we're detached
|
// No attachments, we're detached
|
||||||
return vpnGateway, "detached", nil
|
return vpnGateway, "detached", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return vpnGateway, *vpnGateway.VpcAttachments[0].State, nil
|
vpnAttachment := vpnGatewayGetAttachment(vpnGateway)
|
||||||
|
return vpnGateway, *vpnAttachment.State, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func vpnGatewayGetAttachment(vgw *ec2.VpnGateway) *ec2.VpcAttachment {
|
||||||
|
for _, v := range vgw.VpcAttachments {
|
||||||
|
if *v.State == "attached" {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &ec2.VpcAttachment{State: aws.String("detached")}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,210 @@
|
||||||
|
package aws
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||||
|
"github.com/aws/aws-sdk-go/service/ec2"
|
||||||
|
"github.com/hashicorp/terraform/helper/hashcode"
|
||||||
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
)
|
||||||
|
|
||||||
|
func resourceAwsVpnGatewayAttachment() *schema.Resource {
|
||||||
|
return &schema.Resource{
|
||||||
|
Create: resourceAwsVpnGatewayAttachmentCreate,
|
||||||
|
Read: resourceAwsVpnGatewayAttachmentRead,
|
||||||
|
Delete: resourceAwsVpnGatewayAttachmentDelete,
|
||||||
|
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"vpc_id": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
"vpn_gateway_id": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceAwsVpnGatewayAttachmentCreate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
conn := meta.(*AWSClient).ec2conn
|
||||||
|
|
||||||
|
vpcId := d.Get("vpc_id").(string)
|
||||||
|
vgwId := d.Get("vpn_gateway_id").(string)
|
||||||
|
|
||||||
|
createOpts := &ec2.AttachVpnGatewayInput{
|
||||||
|
VpcId: aws.String(vpcId),
|
||||||
|
VpnGatewayId: aws.String(vgwId),
|
||||||
|
}
|
||||||
|
log.Printf("[DEBUG] VPN Gateway attachment options: %#v", *createOpts)
|
||||||
|
|
||||||
|
_, err := conn.AttachVpnGateway(createOpts)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error attaching VPN Gateway %q to VPC %q: %s",
|
||||||
|
vgwId, vpcId, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
d.SetId(vpnGatewayAttachmentId(vpcId, vgwId))
|
||||||
|
log.Printf("[INFO] VPN Gateway %q attachment ID: %s", vgwId, d.Id())
|
||||||
|
|
||||||
|
stateConf := &resource.StateChangeConf{
|
||||||
|
Pending: []string{"detached", "attaching"},
|
||||||
|
Target: []string{"attached"},
|
||||||
|
Refresh: vpnGatewayAttachmentStateRefresh(conn, vpcId, vgwId),
|
||||||
|
Timeout: 5 * time.Minute,
|
||||||
|
Delay: 10 * time.Second,
|
||||||
|
MinTimeout: 3 * time.Second,
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = stateConf.WaitForState()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error waiting for VPN Gateway %q to attach to VPC %q: %s",
|
||||||
|
vgwId, vpcId, err)
|
||||||
|
}
|
||||||
|
log.Printf("[DEBUG] VPN Gateway %q attached to VPC %q.", vgwId, vpcId)
|
||||||
|
|
||||||
|
return resourceAwsVpnGatewayAttachmentRead(d, meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceAwsVpnGatewayAttachmentRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
conn := meta.(*AWSClient).ec2conn
|
||||||
|
|
||||||
|
vgwId := d.Get("vpn_gateway_id").(string)
|
||||||
|
|
||||||
|
resp, err := conn.DescribeVpnGateways(&ec2.DescribeVpnGatewaysInput{
|
||||||
|
VpnGatewayIds: []*string{aws.String(vgwId)},
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
awsErr, ok := err.(awserr.Error)
|
||||||
|
if ok && awsErr.Code() == "InvalidVPNGatewayID.NotFound" {
|
||||||
|
log.Printf("[WARN] VPN Gateway %q not found.", vgwId)
|
||||||
|
d.SetId("")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
vgw := resp.VpnGateways[0]
|
||||||
|
if *vgw.State == "deleted" {
|
||||||
|
log.Printf("[INFO] VPN Gateway %q appears to have been deleted.", vgwId)
|
||||||
|
d.SetId("")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
vga := vpnGatewayGetAttachment(vgw)
|
||||||
|
if len(vgw.VpcAttachments) == 0 || *vga.State == "detached" {
|
||||||
|
d.Set("vpc_id", "")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
d.Set("vpc_id", *vga.VpcId)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceAwsVpnGatewayAttachmentDelete(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
conn := meta.(*AWSClient).ec2conn
|
||||||
|
|
||||||
|
vpcId := d.Get("vpc_id").(string)
|
||||||
|
vgwId := d.Get("vpn_gateway_id").(string)
|
||||||
|
|
||||||
|
if vpcId == "" {
|
||||||
|
log.Printf("[DEBUG] Not detaching VPN Gateway %q as no VPC ID is set.", vgwId)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := conn.DetachVpnGateway(&ec2.DetachVpnGatewayInput{
|
||||||
|
VpcId: aws.String(vpcId),
|
||||||
|
VpnGatewayId: aws.String(vgwId),
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
awsErr, ok := err.(awserr.Error)
|
||||||
|
if ok {
|
||||||
|
switch awsErr.Code() {
|
||||||
|
case "InvalidVPNGatewayID.NotFound":
|
||||||
|
log.Printf("[WARN] VPN Gateway %q not found.", vgwId)
|
||||||
|
d.SetId("")
|
||||||
|
return nil
|
||||||
|
case "InvalidVpnGatewayAttachment.NotFound":
|
||||||
|
log.Printf(
|
||||||
|
"[WARN] VPN Gateway %q attachment to VPC %q not found.",
|
||||||
|
vgwId, vpcId)
|
||||||
|
d.SetId("")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf("Error detaching VPN Gateway %q from VPC %q: %s",
|
||||||
|
vgwId, vpcId, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
stateConf := &resource.StateChangeConf{
|
||||||
|
Pending: []string{"attached", "detaching"},
|
||||||
|
Target: []string{"detached"},
|
||||||
|
Refresh: vpnGatewayAttachmentStateRefresh(conn, vpcId, vgwId),
|
||||||
|
Timeout: 5 * time.Minute,
|
||||||
|
Delay: 10 * time.Second,
|
||||||
|
MinTimeout: 3 * time.Second,
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = stateConf.WaitForState()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error waiting for VPN Gateway %q to detach from VPC %q: %s",
|
||||||
|
vgwId, vpcId, err)
|
||||||
|
}
|
||||||
|
log.Printf("[DEBUG] VPN Gateway %q detached from VPC %q.", vgwId, vpcId)
|
||||||
|
|
||||||
|
d.SetId("")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func vpnGatewayAttachmentStateRefresh(conn *ec2.EC2, vpcId, vgwId string) resource.StateRefreshFunc {
|
||||||
|
return func() (interface{}, string, error) {
|
||||||
|
resp, err := conn.DescribeVpnGateways(&ec2.DescribeVpnGatewaysInput{
|
||||||
|
Filters: []*ec2.Filter{
|
||||||
|
&ec2.Filter{
|
||||||
|
Name: aws.String("attachment.vpc-id"),
|
||||||
|
Values: []*string{aws.String(vpcId)},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
VpnGatewayIds: []*string{aws.String(vgwId)},
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
awsErr, ok := err.(awserr.Error)
|
||||||
|
if ok {
|
||||||
|
switch awsErr.Code() {
|
||||||
|
case "InvalidVPNGatewayID.NotFound":
|
||||||
|
fallthrough
|
||||||
|
case "InvalidVpnGatewayAttachment.NotFound":
|
||||||
|
return nil, "", nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
vgw := resp.VpnGateways[0]
|
||||||
|
if len(vgw.VpcAttachments) == 0 {
|
||||||
|
return vgw, "detached", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
vga := vpnGatewayGetAttachment(vgw)
|
||||||
|
|
||||||
|
log.Printf("[DEBUG] VPN Gateway %q attachment status: %s", vgwId, *vga.State)
|
||||||
|
return vgw, *vga.State, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func vpnGatewayAttachmentId(vpcId, vgwId string) string {
|
||||||
|
return fmt.Sprintf("vpn-attachment-%x", hashcode.String(fmt.Sprintf("%s-%s", vpcId, vgwId)))
|
||||||
|
}
|
|
@ -0,0 +1,163 @@
|
||||||
|
package aws
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
|
"github.com/aws/aws-sdk-go/service/ec2"
|
||||||
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAccAWSVpnGatewayAttachment_basic(t *testing.T) {
|
||||||
|
var vpc ec2.Vpc
|
||||||
|
var vgw ec2.VpnGateway
|
||||||
|
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
IDRefreshName: "aws_vpn_gateway_attachment.test",
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccCheckVpnGatewayAttachmentDestroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccVpnGatewayAttachmentConfig,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckVpcExists(
|
||||||
|
"aws_vpc.test",
|
||||||
|
&vpc),
|
||||||
|
testAccCheckVpnGatewayExists(
|
||||||
|
"aws_vpn_gateway.test",
|
||||||
|
&vgw),
|
||||||
|
testAccCheckVpnGatewayAttachmentExists(
|
||||||
|
"aws_vpn_gateway_attachment.test",
|
||||||
|
&vpc, &vgw),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAccAWSVpnGatewayAttachment_deleted(t *testing.T) {
|
||||||
|
var vpc ec2.Vpc
|
||||||
|
var vgw ec2.VpnGateway
|
||||||
|
|
||||||
|
testDeleted := func(n string) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
_, ok := s.RootModule().Resources[n]
|
||||||
|
if ok {
|
||||||
|
return fmt.Errorf("Expected VPN Gateway attachment resource %q to be deleted.", n)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
IDRefreshName: "aws_vpn_gateway_attachment.test",
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccCheckVpnGatewayAttachmentDestroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccVpnGatewayAttachmentConfig,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckVpcExists(
|
||||||
|
"aws_vpc.test",
|
||||||
|
&vpc),
|
||||||
|
testAccCheckVpnGatewayExists(
|
||||||
|
"aws_vpn_gateway.test",
|
||||||
|
&vgw),
|
||||||
|
testAccCheckVpnGatewayAttachmentExists(
|
||||||
|
"aws_vpn_gateway_attachment.test",
|
||||||
|
&vpc, &vgw),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccNoVpnGatewayAttachmentConfig,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testDeleted("aws_vpn_gateway_attachment.test"),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckVpnGatewayAttachmentExists(n string, vpc *ec2.Vpc, vgw *ec2.VpnGateway) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
rs, ok := s.RootModule().Resources[n]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("Not found: %s", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rs.Primary.ID == "" {
|
||||||
|
return fmt.Errorf("No ID is set")
|
||||||
|
}
|
||||||
|
|
||||||
|
vpcId := rs.Primary.Attributes["vpc_id"]
|
||||||
|
vgwId := rs.Primary.Attributes["vpn_gateway_id"]
|
||||||
|
|
||||||
|
if len(vgw.VpcAttachments) == 0 {
|
||||||
|
return fmt.Errorf("VPN Gateway %q has no attachments.", vgwId)
|
||||||
|
}
|
||||||
|
|
||||||
|
if *vgw.VpcAttachments[0].State != "attached" {
|
||||||
|
return fmt.Errorf("Expected VPN Gateway %q to be in attached state, but got: %q",
|
||||||
|
vgwId, *vgw.VpcAttachments[0].State)
|
||||||
|
}
|
||||||
|
|
||||||
|
if *vgw.VpcAttachments[0].VpcId != *vpc.VpcId {
|
||||||
|
return fmt.Errorf("Expected VPN Gateway %q to be attached to VPC %q, but got: %q",
|
||||||
|
vgwId, vpcId, *vgw.VpcAttachments[0].VpcId)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckVpnGatewayAttachmentDestroy(s *terraform.State) error {
|
||||||
|
conn := testAccProvider.Meta().(*AWSClient).ec2conn
|
||||||
|
|
||||||
|
for _, rs := range s.RootModule().Resources {
|
||||||
|
if rs.Type != "aws_vpn_gateway_attachment" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
vgwId := rs.Primary.Attributes["vpn_gateway_id"]
|
||||||
|
|
||||||
|
resp, err := conn.DescribeVpnGateways(&ec2.DescribeVpnGatewaysInput{
|
||||||
|
VpnGatewayIds: []*string{aws.String(vgwId)},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
vgw := resp.VpnGateways[0]
|
||||||
|
if *vgw.VpcAttachments[0].State != "detached" {
|
||||||
|
return fmt.Errorf("Expected VPN Gateway %q to be in detached state, but got: %q",
|
||||||
|
vgwId, *vgw.VpcAttachments[0].State)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
const testAccNoVpnGatewayAttachmentConfig = `
|
||||||
|
resource "aws_vpc" "test" {
|
||||||
|
cidr_block = "10.0.0.0/16"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_vpn_gateway" "test" { }
|
||||||
|
`
|
||||||
|
|
||||||
|
const testAccVpnGatewayAttachmentConfig = `
|
||||||
|
resource "aws_vpc" "test" {
|
||||||
|
cidr_block = "10.0.0.0/16"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_vpn_gateway" "test" { }
|
||||||
|
|
||||||
|
resource "aws_vpn_gateway_attachment" "test" {
|
||||||
|
vpc_id = "${aws_vpc.test.id}"
|
||||||
|
vpn_gateway_id = "${aws_vpn_gateway.test.id}"
|
||||||
|
}
|
||||||
|
`
|
|
@ -16,10 +16,10 @@ func TestAccAWSVpnGateway_basic(t *testing.T) {
|
||||||
|
|
||||||
testNotEqual := func(*terraform.State) error {
|
testNotEqual := func(*terraform.State) error {
|
||||||
if len(v.VpcAttachments) == 0 {
|
if len(v.VpcAttachments) == 0 {
|
||||||
return fmt.Errorf("VPN gateway A is not attached")
|
return fmt.Errorf("VPN Gateway A is not attached")
|
||||||
}
|
}
|
||||||
if len(v2.VpcAttachments) == 0 {
|
if len(v2.VpcAttachments) == 0 {
|
||||||
return fmt.Errorf("VPN gateway B is not attached")
|
return fmt.Errorf("VPN Gateway B is not attached")
|
||||||
}
|
}
|
||||||
|
|
||||||
id1 := v.VpcAttachments[0].VpcId
|
id1 := v.VpcAttachments[0].VpcId
|
||||||
|
@ -58,20 +58,38 @@ func TestAccAWSVpnGateway_basic(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAccAWSVpnGateway_reattach(t *testing.T) {
|
func TestAccAWSVpnGateway_reattach(t *testing.T) {
|
||||||
var v ec2.VpnGateway
|
var vpc1, vpc2 ec2.Vpc
|
||||||
|
var vgw1, vgw2 ec2.VpnGateway
|
||||||
|
|
||||||
genTestStateFunc := func(expectedState string) func(*terraform.State) error {
|
testAttachmentFunc := func(vgw *ec2.VpnGateway, vpc *ec2.Vpc) func(*terraform.State) error {
|
||||||
return func(*terraform.State) error {
|
return func(*terraform.State) error {
|
||||||
if len(v.VpcAttachments) == 0 {
|
if len(vgw.VpcAttachments) == 0 {
|
||||||
if expectedState != "detached" {
|
return fmt.Errorf("VPN Gateway %q has no VPC attachments.",
|
||||||
return fmt.Errorf("VPN gateway has no VPC attachments")
|
*vgw.VpnGatewayId)
|
||||||
}
|
}
|
||||||
} else if len(v.VpcAttachments) == 1 {
|
|
||||||
if *v.VpcAttachments[0].State != expectedState {
|
if len(vgw.VpcAttachments) > 1 {
|
||||||
return fmt.Errorf("Expected VPC gateway VPC attachment to be in '%s' state, but was not: %s", expectedState, v)
|
count := 0
|
||||||
|
for _, v := range vgw.VpcAttachments {
|
||||||
|
if *v.State == "attached" {
|
||||||
|
count += 1
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
return fmt.Errorf("VPN gateway has unexpected number of VPC attachments(more than 1): %s", v)
|
if count > 1 {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"VPN Gateway %q has an unexpected number of VPC attachments (more than 1): %#v",
|
||||||
|
*vgw.VpnGatewayId, vgw.VpcAttachments)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if *vgw.VpcAttachments[0].State != "attached" {
|
||||||
|
return fmt.Errorf("Expected VPN Gateway %q to be attached.",
|
||||||
|
*vgw.VpnGatewayId)
|
||||||
|
}
|
||||||
|
|
||||||
|
if *vgw.VpcAttachments[0].VpcId != *vpc.VpcId {
|
||||||
|
return fmt.Errorf("Expected VPN Gateway %q to be attached to VPC %q, but got: %q",
|
||||||
|
*vgw.VpnGatewayId, *vpc.VpcId, *vgw.VpcAttachments[0].VpcId)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -84,27 +102,38 @@ func TestAccAWSVpnGateway_reattach(t *testing.T) {
|
||||||
CheckDestroy: testAccCheckVpnGatewayDestroy,
|
CheckDestroy: testAccCheckVpnGatewayDestroy,
|
||||||
Steps: []resource.TestStep{
|
Steps: []resource.TestStep{
|
||||||
resource.TestStep{
|
resource.TestStep{
|
||||||
Config: testAccVpnGatewayConfig,
|
Config: testAccCheckVpnGatewayConfigReattach,
|
||||||
Check: resource.ComposeTestCheckFunc(
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckVpcExists("aws_vpc.foo", &vpc1),
|
||||||
|
testAccCheckVpcExists("aws_vpc.bar", &vpc2),
|
||||||
testAccCheckVpnGatewayExists(
|
testAccCheckVpnGatewayExists(
|
||||||
"aws_vpn_gateway.foo", &v),
|
"aws_vpn_gateway.foo", &vgw1),
|
||||||
genTestStateFunc("attached"),
|
testAccCheckVpnGatewayExists(
|
||||||
|
"aws_vpn_gateway.bar", &vgw2),
|
||||||
|
testAttachmentFunc(&vgw1, &vpc1),
|
||||||
|
testAttachmentFunc(&vgw2, &vpc2),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
resource.TestStep{
|
resource.TestStep{
|
||||||
Config: testAccVpnGatewayConfigDetach,
|
Config: testAccCheckVpnGatewayConfigReattachChange,
|
||||||
Check: resource.ComposeTestCheckFunc(
|
Check: resource.ComposeTestCheckFunc(
|
||||||
testAccCheckVpnGatewayExists(
|
testAccCheckVpnGatewayExists(
|
||||||
"aws_vpn_gateway.foo", &v),
|
"aws_vpn_gateway.foo", &vgw1),
|
||||||
genTestStateFunc("detached"),
|
testAccCheckVpnGatewayExists(
|
||||||
|
"aws_vpn_gateway.bar", &vgw2),
|
||||||
|
testAttachmentFunc(&vgw2, &vpc1),
|
||||||
|
testAttachmentFunc(&vgw1, &vpc2),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
resource.TestStep{
|
resource.TestStep{
|
||||||
Config: testAccVpnGatewayConfig,
|
Config: testAccCheckVpnGatewayConfigReattach,
|
||||||
Check: resource.ComposeTestCheckFunc(
|
Check: resource.ComposeTestCheckFunc(
|
||||||
testAccCheckVpnGatewayExists(
|
testAccCheckVpnGatewayExists(
|
||||||
"aws_vpn_gateway.foo", &v),
|
"aws_vpn_gateway.foo", &vgw1),
|
||||||
genTestStateFunc("attached"),
|
testAccCheckVpnGatewayExists(
|
||||||
|
"aws_vpn_gateway.bar", &vgw2),
|
||||||
|
testAttachmentFunc(&vgw1, &vpc1),
|
||||||
|
testAttachmentFunc(&vgw2, &vpc2),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -118,7 +147,7 @@ func TestAccAWSVpnGateway_delete(t *testing.T) {
|
||||||
return func(s *terraform.State) error {
|
return func(s *terraform.State) error {
|
||||||
_, ok := s.RootModule().Resources[r]
|
_, ok := s.RootModule().Resources[r]
|
||||||
if ok {
|
if ok {
|
||||||
return fmt.Errorf("VPN Gateway %q should have been deleted", r)
|
return fmt.Errorf("VPN Gateway %q should have been deleted.", r)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -159,7 +188,6 @@ func TestAccAWSVpnGateway_tags(t *testing.T) {
|
||||||
testAccCheckTags(&v.Tags, "foo", "bar"),
|
testAccCheckTags(&v.Tags, "foo", "bar"),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
|
||||||
resource.TestStep{
|
resource.TestStep{
|
||||||
Config: testAccCheckVpnGatewayConfigTagsUpdate,
|
Config: testAccCheckVpnGatewayConfigTagsUpdate,
|
||||||
Check: resource.ComposeTestCheckFunc(
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
@ -198,7 +226,7 @@ func testAccCheckVpnGatewayDestroy(s *terraform.State) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if *v.State != "deleted" {
|
if *v.State != "deleted" {
|
||||||
return fmt.Errorf("Expected VpnGateway to be in deleted state, but was not: %s", v)
|
return fmt.Errorf("Expected VPN Gateway to be in deleted state, but was not: %s", v)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -235,7 +263,7 @@ func testAccCheckVpnGatewayExists(n string, ig *ec2.VpnGateway) resource.TestChe
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(resp.VpnGateways) == 0 {
|
if len(resp.VpnGateways) == 0 {
|
||||||
return fmt.Errorf("VPNGateway not found")
|
return fmt.Errorf("VPN Gateway not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
*ig = *resp.VpnGateways[0]
|
*ig = *resp.VpnGateways[0]
|
||||||
|
@ -270,16 +298,6 @@ resource "aws_vpn_gateway" "foo" {
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
const testAccVpnGatewayConfigDetach = `
|
|
||||||
resource "aws_vpc" "foo" {
|
|
||||||
cidr_block = "10.1.0.0/16"
|
|
||||||
}
|
|
||||||
|
|
||||||
resource "aws_vpn_gateway" "foo" {
|
|
||||||
vpc_id = ""
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
const testAccCheckVpnGatewayConfigTags = `
|
const testAccCheckVpnGatewayConfigTags = `
|
||||||
resource "aws_vpc" "foo" {
|
resource "aws_vpc" "foo" {
|
||||||
cidr_block = "10.1.0.0/16"
|
cidr_block = "10.1.0.0/16"
|
||||||
|
@ -305,3 +323,39 @@ resource "aws_vpn_gateway" "foo" {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
const testAccCheckVpnGatewayConfigReattach = `
|
||||||
|
resource "aws_vpc" "foo" {
|
||||||
|
cidr_block = "10.1.0.0/16"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_vpc" "bar" {
|
||||||
|
cidr_block = "10.2.0.0/16"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_vpn_gateway" "foo" {
|
||||||
|
vpc_id = "${aws_vpc.foo.id}"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_vpn_gateway" "bar" {
|
||||||
|
vpc_id = "${aws_vpc.bar.id}"
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
const testAccCheckVpnGatewayConfigReattachChange = `
|
||||||
|
resource "aws_vpc" "foo" {
|
||||||
|
cidr_block = "10.1.0.0/16"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_vpc" "bar" {
|
||||||
|
cidr_block = "10.2.0.0/16"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_vpn_gateway" "foo" {
|
||||||
|
vpc_id = "${aws_vpc.bar.id}"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_vpn_gateway" "bar" {
|
||||||
|
vpc_id = "${aws_vpc.foo.id}"
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
---
|
||||||
|
layout: "aws"
|
||||||
|
page_title: "AWS: aws_vpn_gateway_attachment"
|
||||||
|
sidebar_current: "docs-aws-resource-vpn-gateway-attachment"
|
||||||
|
description: |-
|
||||||
|
Provides a Virtual Private Gateway attachment resource.
|
||||||
|
---
|
||||||
|
|
||||||
|
# aws\_vpn\_gateway\_attachment
|
||||||
|
|
||||||
|
Provides a Virtual Private Gateway attachment resource, allowing for an existing
|
||||||
|
hardware VPN gateway to be attached and/or detached from a VPC.
|
||||||
|
|
||||||
|
-> **Note:** The [`aws_vpn_gateway`](vpn_gateway.html)
|
||||||
|
resource can also automatically attach the Virtual Private Gateway it creates
|
||||||
|
to an existing VPC by setting the [`vpc_id`](vpn_gateway.html#vpc_id) attribute accordingly.
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
```
|
||||||
|
resource "aws_vpc" "network" {
|
||||||
|
cidr_block = "10.0.0.0/16"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_vpn_gateway" "vpn" {
|
||||||
|
tags {
|
||||||
|
Name = "example-vpn-gateway"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_vpn_gateway_attachment" "vpn_attachment" {
|
||||||
|
vpc_id = "${aws_vpc.network.id}"
|
||||||
|
vpn_gateway_id = "${aws_vpn_gateway.vpn.id}"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
See [Virtual Private Cloud](http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_Introduction.html)
|
||||||
|
and [Virtual Private Gateway](http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_VPN.html) user
|
||||||
|
guides for more information.
|
||||||
|
|
||||||
|
## Argument Reference
|
||||||
|
|
||||||
|
The following arguments are supported:
|
||||||
|
|
||||||
|
* `vpc_id` - (Required) The ID of the VPC.
|
||||||
|
* `vpn_gateway_id` - (Required) The ID of the Virtual Private Gateway.
|
||||||
|
|
||||||
|
## Attributes Reference
|
||||||
|
|
||||||
|
The following attributes are exported:
|
||||||
|
|
||||||
|
* `vpc_id` - The ID of the VPC that Virtual Private Gateway is attached to.
|
||||||
|
* `vpn_gateway_id` - The ID of the Virtual Private Gateway.
|
||||||
|
|
||||||
|
## Import
|
||||||
|
|
||||||
|
This resource does not support importing.
|
|
@ -885,6 +885,10 @@
|
||||||
<a href="/docs/providers/aws/r/vpn_gateway.html">aws_vpn_gateway</a>
|
<a href="/docs/providers/aws/r/vpn_gateway.html">aws_vpn_gateway</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
<li<%= sidebar_current("docs-aws-resource-vpn-gateway-attachment") %>>
|
||||||
|
<a href="/docs/providers/aws/r/vpn_gateway_attachment.html">aws_vpn_gateway_attachment</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue