mirror of
https://github.com/opentofu/opentofu.git
synced 2025-01-08 15:13:56 -06:00
feaabb6ca1
availability zone Fixes #4752 According to the AWS Documentation, when `describing-vpn-gateways` ``` AvailabilityZone -> (string) The Availability Zone where the virtual private gateway was created, if applicable. This field may be empty or not returned. ``` Therefore, if we pass an availability zone as part of vpn gateway, then it may come back as an empty string. If we set this empty string back to state, then the next plan will look as follows: ``` -/+ aws_vpn_gateway.vpn_gateway availability_zone: "" => "us-west-2a" (forces new resource) tags.%: "1" => "1" tags.Name: "vpn-us-west-2" => "vpn-us-west-2" vpc_id: "vpc-1e9da47a" => "vpc-1e9da47a" Plan: 1 to add, 0 to change, 1 to destroy. ``` If the availability_zone comes back from AWS as an empty string, then we should not set it to state to avoid forcing a new resource for the user ``` % make testacc TEST=./builtin/providers/aws TESTARGS='-run=TestAccAWSVpnGateway_withAvailabilityZoneSetToState' ==> Checking that code complies with gofmt requirements... go generate $(go list ./... | grep -v /terraform/vendor/) 2016/09/03 17:10:57 Generated command/internal_plugin_list.go TF_ACC=1 go test ./builtin/providers/aws -v -run=TestAccAWSVpnGateway_withAvailabilityZoneSetToState -timeout 120m === RUN TestAccAWSVpnGateway_withAvailabilityZoneSetToState --- FAIL: TestAccAWSVpnGateway_withAvailabilityZoneSetToState (36.11s) testing.go:265: Step 0 error: Check failed: Check 2/2 error: aws_vpn_gateway.foo: Attribute 'availability_zone' expected "us-west-2a", got "" FAIL exit status 1 FAIL github.com/hashicorp/terraform/builtin/providers/aws 36.130s make: *** [testacc] Error 1 [stacko@Pauls-MacBook-Pro:~/Code/go/src/github.com/hashicorp/terraform on master] % make testacc TEST=./builtin/providers/aws TESTARGS='-run=TestAccAWSVpnGateway_withAvailabilityZoneSetToState' 2 ↵ ✹ ==> Checking that code complies with gofmt requirements... go generate $(go list ./... | grep -v /terraform/vendor/) 2016/09/03 17:12:25 Generated command/internal_plugin_list.go TF_ACC=1 go test ./builtin/providers/aws -v -run=TestAccAWSVpnGateway_withAvailabilityZoneSetToState -timeout 120m === RUN TestAccAWSVpnGateway_withAvailabilityZoneSetToState --- PASS: TestAccAWSVpnGateway_withAvailabilityZoneSetToState (46.50s) PASS ok github.com/hashicorp/terraform/builtin/providers/aws 46.517s ```
469 lines
11 KiB
Go
469 lines
11 KiB
Go
package aws
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
"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/resource"
|
|
"github.com/hashicorp/terraform/terraform"
|
|
)
|
|
|
|
func TestAccAWSVpnGateway_basic(t *testing.T) {
|
|
var v, v2 ec2.VpnGateway
|
|
|
|
testNotEqual := func(*terraform.State) error {
|
|
if len(v.VpcAttachments) == 0 {
|
|
return fmt.Errorf("VPN Gateway A is not attached")
|
|
}
|
|
if len(v2.VpcAttachments) == 0 {
|
|
return fmt.Errorf("VPN Gateway B is not attached")
|
|
}
|
|
|
|
id1 := v.VpcAttachments[0].VpcId
|
|
id2 := v2.VpcAttachments[0].VpcId
|
|
if id1 == id2 {
|
|
return fmt.Errorf("Both attachment IDs are the same")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
resource.Test(t, resource.TestCase{
|
|
PreCheck: func() { testAccPreCheck(t) },
|
|
IDRefreshName: "aws_vpn_gateway.foo",
|
|
Providers: testAccProviders,
|
|
CheckDestroy: testAccCheckVpnGatewayDestroy,
|
|
Steps: []resource.TestStep{
|
|
resource.TestStep{
|
|
Config: testAccVpnGatewayConfig,
|
|
Check: resource.ComposeTestCheckFunc(
|
|
testAccCheckVpnGatewayExists(
|
|
"aws_vpn_gateway.foo", &v),
|
|
),
|
|
},
|
|
|
|
resource.TestStep{
|
|
Config: testAccVpnGatewayConfigChangeVPC,
|
|
Check: resource.ComposeTestCheckFunc(
|
|
testAccCheckVpnGatewayExists(
|
|
"aws_vpn_gateway.foo", &v2),
|
|
testNotEqual,
|
|
),
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
func TestAccAWSVpnGateway_withAvailabilityZoneSetToState(t *testing.T) {
|
|
var v ec2.VpnGateway
|
|
|
|
resource.Test(t, resource.TestCase{
|
|
PreCheck: func() { testAccPreCheck(t) },
|
|
Providers: testAccProviders,
|
|
CheckDestroy: testAccCheckVpnGatewayDestroy,
|
|
Steps: []resource.TestStep{
|
|
resource.TestStep{
|
|
Config: testAccVpnGatewayConfigWithAZ,
|
|
Check: resource.ComposeTestCheckFunc(
|
|
testAccCheckVpnGatewayExists("aws_vpn_gateway.foo", &v),
|
|
resource.TestCheckResourceAttr(
|
|
"aws_vpn_gateway.foo", "availability_zone", "us-west-2a"),
|
|
),
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
func TestAccAWSVpnGateway_disappears(t *testing.T) {
|
|
var v ec2.VpnGateway
|
|
|
|
resource.Test(t, resource.TestCase{
|
|
PreCheck: func() { testAccPreCheck(t) },
|
|
Providers: testAccProviders,
|
|
CheckDestroy: testAccCheckVpnGatewayDestroy,
|
|
Steps: []resource.TestStep{
|
|
resource.TestStep{
|
|
Config: testAccVpnGatewayConfig,
|
|
Check: resource.ComposeTestCheckFunc(
|
|
testAccCheckVpnGatewayExists("aws_vpn_gateway.foo", &v),
|
|
testAccAWSVpnGatewayDisappears(&v),
|
|
),
|
|
ExpectNonEmptyPlan: true,
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
func TestAccAWSVpnGateway_reattach(t *testing.T) {
|
|
var vpc1, vpc2 ec2.Vpc
|
|
var vgw1, vgw2 ec2.VpnGateway
|
|
|
|
testAttachmentFunc := func(vgw *ec2.VpnGateway, vpc *ec2.Vpc) func(*terraform.State) error {
|
|
return func(*terraform.State) error {
|
|
if len(vgw.VpcAttachments) == 0 {
|
|
return fmt.Errorf("VPN Gateway %q has no VPC attachments.",
|
|
*vgw.VpnGatewayId)
|
|
}
|
|
|
|
if len(vgw.VpcAttachments) > 1 {
|
|
count := 0
|
|
for _, v := range vgw.VpcAttachments {
|
|
if *v.State == "attached" {
|
|
count += 1
|
|
}
|
|
}
|
|
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
|
|
}
|
|
}
|
|
|
|
resource.Test(t, resource.TestCase{
|
|
PreCheck: func() { testAccPreCheck(t) },
|
|
IDRefreshName: "aws_vpn_gateway.foo",
|
|
Providers: testAccProviders,
|
|
CheckDestroy: testAccCheckVpnGatewayDestroy,
|
|
Steps: []resource.TestStep{
|
|
resource.TestStep{
|
|
Config: testAccCheckVpnGatewayConfigReattach,
|
|
Check: resource.ComposeTestCheckFunc(
|
|
testAccCheckVpcExists("aws_vpc.foo", &vpc1),
|
|
testAccCheckVpcExists("aws_vpc.bar", &vpc2),
|
|
testAccCheckVpnGatewayExists(
|
|
"aws_vpn_gateway.foo", &vgw1),
|
|
testAccCheckVpnGatewayExists(
|
|
"aws_vpn_gateway.bar", &vgw2),
|
|
testAttachmentFunc(&vgw1, &vpc1),
|
|
testAttachmentFunc(&vgw2, &vpc2),
|
|
),
|
|
},
|
|
resource.TestStep{
|
|
Config: testAccCheckVpnGatewayConfigReattachChange,
|
|
Check: resource.ComposeTestCheckFunc(
|
|
testAccCheckVpnGatewayExists(
|
|
"aws_vpn_gateway.foo", &vgw1),
|
|
testAccCheckVpnGatewayExists(
|
|
"aws_vpn_gateway.bar", &vgw2),
|
|
testAttachmentFunc(&vgw2, &vpc1),
|
|
testAttachmentFunc(&vgw1, &vpc2),
|
|
),
|
|
},
|
|
resource.TestStep{
|
|
Config: testAccCheckVpnGatewayConfigReattach,
|
|
Check: resource.ComposeTestCheckFunc(
|
|
testAccCheckVpnGatewayExists(
|
|
"aws_vpn_gateway.foo", &vgw1),
|
|
testAccCheckVpnGatewayExists(
|
|
"aws_vpn_gateway.bar", &vgw2),
|
|
testAttachmentFunc(&vgw1, &vpc1),
|
|
testAttachmentFunc(&vgw2, &vpc2),
|
|
),
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
func TestAccAWSVpnGateway_delete(t *testing.T) {
|
|
var vpnGateway ec2.VpnGateway
|
|
|
|
testDeleted := func(r string) resource.TestCheckFunc {
|
|
return func(s *terraform.State) error {
|
|
_, ok := s.RootModule().Resources[r]
|
|
if ok {
|
|
return fmt.Errorf("VPN Gateway %q should have been deleted.", r)
|
|
}
|
|
return nil
|
|
}
|
|
}
|
|
|
|
resource.Test(t, resource.TestCase{
|
|
PreCheck: func() { testAccPreCheck(t) },
|
|
IDRefreshName: "aws_vpn_gateway.foo",
|
|
Providers: testAccProviders,
|
|
CheckDestroy: testAccCheckVpnGatewayDestroy,
|
|
Steps: []resource.TestStep{
|
|
resource.TestStep{
|
|
Config: testAccVpnGatewayConfig,
|
|
Check: resource.ComposeTestCheckFunc(
|
|
testAccCheckVpnGatewayExists("aws_vpn_gateway.foo", &vpnGateway)),
|
|
},
|
|
resource.TestStep{
|
|
Config: testAccNoVpnGatewayConfig,
|
|
Check: resource.ComposeTestCheckFunc(testDeleted("aws_vpn_gateway.foo")),
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
func TestAccAWSVpnGateway_tags(t *testing.T) {
|
|
var v ec2.VpnGateway
|
|
|
|
resource.Test(t, resource.TestCase{
|
|
PreCheck: func() { testAccPreCheck(t) },
|
|
IDRefreshName: "aws_vpn_gateway.foo",
|
|
Providers: testAccProviders,
|
|
CheckDestroy: testAccCheckVpnGatewayDestroy,
|
|
Steps: []resource.TestStep{
|
|
resource.TestStep{
|
|
Config: testAccCheckVpnGatewayConfigTags,
|
|
Check: resource.ComposeTestCheckFunc(
|
|
testAccCheckVpnGatewayExists("aws_vpn_gateway.foo", &v),
|
|
testAccCheckTags(&v.Tags, "foo", "bar"),
|
|
),
|
|
},
|
|
resource.TestStep{
|
|
Config: testAccCheckVpnGatewayConfigTagsUpdate,
|
|
Check: resource.ComposeTestCheckFunc(
|
|
testAccCheckVpnGatewayExists("aws_vpn_gateway.foo", &v),
|
|
testAccCheckTags(&v.Tags, "foo", ""),
|
|
testAccCheckTags(&v.Tags, "bar", "baz"),
|
|
),
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
func testAccAWSVpnGatewayDisappears(gateway *ec2.VpnGateway) resource.TestCheckFunc {
|
|
return func(s *terraform.State) error {
|
|
conn := testAccProvider.Meta().(*AWSClient).ec2conn
|
|
|
|
_, err := conn.DetachVpnGateway(&ec2.DetachVpnGatewayInput{
|
|
VpnGatewayId: gateway.VpnGatewayId,
|
|
VpcId: gateway.VpcAttachments[0].VpcId,
|
|
})
|
|
if err != nil {
|
|
ec2err, ok := err.(awserr.Error)
|
|
if ok {
|
|
if ec2err.Code() == "InvalidVpnGatewayID.NotFound" {
|
|
return nil
|
|
} else if ec2err.Code() == "InvalidVpnGatewayAttachment.NotFound" {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
opts := &ec2.DeleteVpnGatewayInput{
|
|
VpnGatewayId: gateway.VpnGatewayId,
|
|
}
|
|
if _, err := conn.DeleteVpnGateway(opts); err != nil {
|
|
return err
|
|
}
|
|
return resource.Retry(40*time.Minute, func() *resource.RetryError {
|
|
opts := &ec2.DescribeVpnGatewaysInput{
|
|
VpnGatewayIds: []*string{gateway.VpnGatewayId},
|
|
}
|
|
resp, err := conn.DescribeVpnGateways(opts)
|
|
if err != nil {
|
|
cgw, ok := err.(awserr.Error)
|
|
if ok && cgw.Code() == "InvalidVpnGatewayID.NotFound" {
|
|
return nil
|
|
}
|
|
if ok && cgw.Code() == "IncorrectState" {
|
|
return resource.RetryableError(fmt.Errorf(
|
|
"Waiting for VPN Gateway to be in the correct state: %v", gateway.VpnGatewayId))
|
|
}
|
|
return resource.NonRetryableError(
|
|
fmt.Errorf("Error retrieving VPN Gateway: %s", err))
|
|
}
|
|
if *resp.VpnGateways[0].State == "deleted" {
|
|
return nil
|
|
}
|
|
return resource.RetryableError(fmt.Errorf(
|
|
"Waiting for VPN Gateway: %v", gateway.VpnGatewayId))
|
|
})
|
|
}
|
|
}
|
|
|
|
func testAccCheckVpnGatewayDestroy(s *terraform.State) error {
|
|
ec2conn := testAccProvider.Meta().(*AWSClient).ec2conn
|
|
|
|
for _, rs := range s.RootModule().Resources {
|
|
if rs.Type != "aws_vpn_gateway" {
|
|
continue
|
|
}
|
|
|
|
// Try to find the resource
|
|
resp, err := ec2conn.DescribeVpnGateways(&ec2.DescribeVpnGatewaysInput{
|
|
VpnGatewayIds: []*string{aws.String(rs.Primary.ID)},
|
|
})
|
|
if err == nil {
|
|
var v *ec2.VpnGateway
|
|
for _, g := range resp.VpnGateways {
|
|
if *g.VpnGatewayId == rs.Primary.ID {
|
|
v = g
|
|
}
|
|
}
|
|
|
|
if v == nil {
|
|
// wasn't found
|
|
return nil
|
|
}
|
|
|
|
if *v.State != "deleted" {
|
|
return fmt.Errorf("Expected VPN Gateway to be in deleted state, but was not: %s", v)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Verify the error is what we want
|
|
ec2err, ok := err.(awserr.Error)
|
|
if !ok {
|
|
return err
|
|
}
|
|
if ec2err.Code() != "InvalidVpnGatewayID.NotFound" {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func testAccCheckVpnGatewayExists(n string, ig *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")
|
|
}
|
|
|
|
ec2conn := testAccProvider.Meta().(*AWSClient).ec2conn
|
|
resp, err := ec2conn.DescribeVpnGateways(&ec2.DescribeVpnGatewaysInput{
|
|
VpnGatewayIds: []*string{aws.String(rs.Primary.ID)},
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if len(resp.VpnGateways) == 0 {
|
|
return fmt.Errorf("VPN Gateway not found")
|
|
}
|
|
|
|
*ig = *resp.VpnGateways[0]
|
|
|
|
return nil
|
|
}
|
|
}
|
|
|
|
const testAccNoVpnGatewayConfig = `
|
|
resource "aws_vpc" "foo" {
|
|
cidr_block = "10.1.0.0/16"
|
|
}
|
|
`
|
|
|
|
const testAccVpnGatewayConfig = `
|
|
resource "aws_vpc" "foo" {
|
|
cidr_block = "10.1.0.0/16"
|
|
}
|
|
|
|
resource "aws_vpn_gateway" "foo" {
|
|
vpc_id = "${aws_vpc.foo.id}"
|
|
}
|
|
`
|
|
|
|
const testAccVpnGatewayConfigChangeVPC = `
|
|
resource "aws_vpc" "bar" {
|
|
cidr_block = "10.2.0.0/16"
|
|
}
|
|
|
|
resource "aws_vpn_gateway" "foo" {
|
|
vpc_id = "${aws_vpc.bar.id}"
|
|
}
|
|
`
|
|
|
|
const testAccCheckVpnGatewayConfigTags = `
|
|
resource "aws_vpc" "foo" {
|
|
cidr_block = "10.1.0.0/16"
|
|
}
|
|
|
|
resource "aws_vpn_gateway" "foo" {
|
|
vpc_id = "${aws_vpc.foo.id}"
|
|
tags {
|
|
foo = "bar"
|
|
}
|
|
}
|
|
`
|
|
|
|
const testAccCheckVpnGatewayConfigTagsUpdate = `
|
|
resource "aws_vpc" "foo" {
|
|
cidr_block = "10.1.0.0/16"
|
|
}
|
|
|
|
resource "aws_vpn_gateway" "foo" {
|
|
vpc_id = "${aws_vpc.foo.id}"
|
|
tags {
|
|
bar = "baz"
|
|
}
|
|
}
|
|
`
|
|
|
|
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}"
|
|
}
|
|
`
|
|
|
|
const testAccVpnGatewayConfigWithAZ = `
|
|
resource "aws_vpc" "foo" {
|
|
cidr_block = "10.1.0.0/16"
|
|
}
|
|
|
|
resource "aws_vpn_gateway" "foo" {
|
|
vpc_id = "${aws_vpc.foo.id}"
|
|
availability_zone = "us-west-2a"
|
|
}
|
|
`
|