From 34c83269fc2c503df9472cb8380a796bdd9b4396 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Thu, 25 Jun 2020 16:07:29 -0400 Subject: [PATCH 01/40] r/aws_route: Tidy up 'testAccAWSRouteConfigBasic()'. Acceptance test output: $ make testacc TEST=./aws/ TESTARGS='-run=TestAccAWSRoute_basic' ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws/ -v -count 1 -parallel 20 -run=TestAccAWSRoute_basic -timeout 120m === RUN TestAccAWSRoute_basic === PAUSE TestAccAWSRoute_basic === CONT TestAccAWSRoute_basic --- PASS: TestAccAWSRoute_basic (53.08s) PASS ok github.com/terraform-providers/terraform-provider-aws/aws 53.129s $ make testacc TEST=./aws/ TESTARGS='-run=TestAccAWSRoute_disappears' ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws/ -v -count 1 -parallel 20 -run=TestAccAWSRoute_disappears -timeout 120m === RUN TestAccAWSRoute_disappears === PAUSE TestAccAWSRoute_disappears === CONT TestAccAWSRoute_disappears --- PASS: TestAccAWSRoute_disappears (49.64s) PASS ok github.com/terraform-providers/terraform-provider-aws/aws 49.690s $ make testacc TEST=./aws/ TESTARGS='-run=TestAccAWSRoute_changeCidr' ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws/ -v -count 1 -parallel 20 -run=TestAccAWSRoute_changeCidr -timeout 120m === RUN TestAccAWSRoute_changeCidr === PAUSE TestAccAWSRoute_changeCidr === CONT TestAccAWSRoute_changeCidr --- PASS: TestAccAWSRoute_changeCidr (77.60s) PASS ok github.com/terraform-providers/terraform-provider-aws/aws 77.646s --- aws/resource_aws_route_test.go | 343 ++++++++++----------------------- 1 file changed, 102 insertions(+), 241 deletions(-) diff --git a/aws/resource_aws_route_test.go b/aws/resource_aws_route_test.go index d6ce63c10899..2025542be7b4 100644 --- a/aws/resource_aws_route_test.go +++ b/aws/resource_aws_route_test.go @@ -4,6 +4,7 @@ import ( "fmt" "testing" + "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" "github.com/hashicorp/terraform-plugin-sdk/helper/acctest" "github.com/hashicorp/terraform-plugin-sdk/helper/resource" @@ -12,44 +13,27 @@ import ( func TestAccAWSRoute_basic(t *testing.T) { var route ec2.Route - - //aws creates a default route - testCheck := func(s *terraform.State) error { - if *route.DestinationCidrBlock != "10.3.0.0/16" { - return fmt.Errorf("Destination Cidr (Expected=%s, Actual=%s)\n", "10.3.0.0/16", *route.DestinationCidrBlock) - } - - name := "aws_internet_gateway.foo" - gwres, ok := s.RootModule().Resources[name] - if !ok { - return fmt.Errorf("Not found: %s\n", name) - } - - if *route.GatewayId != gwres.Primary.ID { - return fmt.Errorf("Internet Gateway Id (Expected=%s, Actual=%s)\n", gwres.Primary.ID, *route.GatewayId) - } - - return nil - } + resourceName := "aws_route.test" + igwResourceName := "aws_internet_gateway.test" + rName := acctest.RandomWithPrefix("tf-acc-test") + cidr := "10.3.0.0/16" resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { - testAccPreCheck(t) - }, + PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, CheckDestroy: testAccCheckAWSRouteDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSRouteBasicConfig(), + Config: testAccAWSRouteConfigBasic(rName, cidr), Check: resource.ComposeTestCheckFunc( - testAccCheckAWSRouteExists("aws_route.bar", &route), - testCheck, + testAccCheckAWSRouteExists(resourceName, &route), + testAccCheckAWSRouteInternetGatewayRoute(igwResourceName, &route, cidr), ), }, { - ResourceName: "aws_route.bar", + ResourceName: resourceName, ImportState: true, - ImportStateIdFunc: testAccAWSRouteImportStateIdFunc("aws_route.bar"), + ImportStateIdFunc: testAccAWSRouteImportStateIdFunc(resourceName), ImportStateVerify: true, }, }, @@ -58,19 +42,20 @@ func TestAccAWSRoute_basic(t *testing.T) { func TestAccAWSRoute_disappears(t *testing.T) { var route ec2.Route + resourceName := "aws_route.test" + rName := acctest.RandomWithPrefix("tf-acc-test") + cidr := "10.3.0.0/16" resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { - testAccPreCheck(t) - }, + PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, CheckDestroy: testAccCheckAWSRouteDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSRouteBasicConfig(), + Config: testAccAWSRouteConfigBasic(rName, cidr), Check: resource.ComposeTestCheckFunc( - testAccCheckAWSRouteExists("aws_route.bar", &route), - testAccCheckResourceDisappears(testAccProvider, resourceAwsRoute(), "aws_route.bar"), + testAccCheckAWSRouteExists(resourceName, &route), + testAccCheckResourceDisappears(testAccProvider, resourceAwsRoute(), resourceName), ), ExpectNonEmptyPlan: true, }, @@ -234,110 +219,41 @@ func TestAccAWSRoute_ipv6ToPeeringConnection(t *testing.T) { }) } -func TestAccAWSRoute_changeRouteTable(t *testing.T) { - var before ec2.Route - var after ec2.Route - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { - testAccPreCheck(t) - }, - Providers: testAccProviders, - CheckDestroy: testAccCheckAWSRouteDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAWSRouteBasicConfig(), - Check: resource.ComposeTestCheckFunc( - testAccCheckAWSRouteExists("aws_route.bar", &before), - ), - }, - { - Config: testAccAWSRouteNewRouteTable(), - Check: resource.ComposeTestCheckFunc( - testAccCheckAWSRouteExists("aws_route.bar", &after), - ), - }, - { - ResourceName: "aws_route.bar", - ImportState: true, - ImportStateIdFunc: testAccAWSRouteImportStateIdFunc("aws_route.bar"), - ImportStateVerify: true, - }, - }, - }) -} - func TestAccAWSRoute_changeCidr(t *testing.T) { var route ec2.Route var routeTable ec2.RouteTable - - //aws creates a default route - testCheck := func(s *terraform.State) error { - if *route.DestinationCidrBlock != "10.3.0.0/16" { - return fmt.Errorf("Destination Cidr (Expected=%s, Actual=%s)\n", "10.3.0.0/16", *route.DestinationCidrBlock) - } - - name := "aws_internet_gateway.foo" - gwres, ok := s.RootModule().Resources[name] - if !ok { - return fmt.Errorf("Not found: %s\n", name) - } - - if *route.GatewayId != gwres.Primary.ID { - return fmt.Errorf("Internet Gateway Id (Expected=%s, Actual=%s)\n", gwres.Primary.ID, *route.GatewayId) - } - - return nil - } - - testCheckChange := func(s *terraform.State) error { - if *route.DestinationCidrBlock != "10.2.0.0/16" { - return fmt.Errorf("Destination Cidr (Expected=%s, Actual=%s)\n", "10.2.0.0/16", *route.DestinationCidrBlock) - } - - name := "aws_internet_gateway.foo" - gwres, ok := s.RootModule().Resources[name] - if !ok { - return fmt.Errorf("Not found: %s\n", name) - } - - if *route.GatewayId != gwres.Primary.ID { - return fmt.Errorf("Internet Gateway Id (Expected=%s, Actual=%s)\n", gwres.Primary.ID, *route.GatewayId) - } - - if rtlen := len(routeTable.Routes); rtlen != 2 { - return fmt.Errorf("Route Table has too many routes (Expected=%d, Actual=%d)\n", rtlen, 2) - } - - return nil - } + resourceName := "aws_route.test" + igwResourceName := "aws_internet_gateway.test" + rtResourceName := "aws_route_table.test" + rName := acctest.RandomWithPrefix("tf-acc-test") + cidr := "10.3.0.0/16" + changedCidr := "10.2.0.0/16" resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { - testAccPreCheck(t) - }, + PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, CheckDestroy: testAccCheckAWSRouteDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSRouteBasicConfig(), + Config: testAccAWSRouteConfigBasic(rName, cidr), Check: resource.ComposeTestCheckFunc( - testAccCheckAWSRouteExists("aws_route.bar", &route), - testCheck, + testAccCheckAWSRouteExists(resourceName, &route), + testAccCheckAWSRouteInternetGatewayRoute(igwResourceName, &route, cidr), ), }, { - Config: testAccAWSRouteBasicConfigChangeCidr(), + Config: testAccAWSRouteConfigBasic(rName, changedCidr), Check: resource.ComposeTestCheckFunc( - testAccCheckAWSRouteExists("aws_route.bar", &route), - testAccCheckRouteTableExists("aws_route_table.foo", &routeTable), - testCheckChange, + testAccCheckAWSRouteExists(resourceName, &route), + testAccCheckAWSRouteInternetGatewayRoute(igwResourceName, &route, changedCidr), + testAccCheckRouteTableExists(rtResourceName, &routeTable), + testAccCheckAWSRouteNumberOfRoutes(&routeTable, 2), ), }, { - ResourceName: "aws_route.bar", + ResourceName: resourceName, ImportState: true, - ImportStateIdFunc: testAccAWSRouteImportStateIdFunc("aws_route.bar"), + ImportStateIdFunc: testAccAWSRouteImportStateIdFunc(resourceName), ImportStateVerify: true, }, }, @@ -364,14 +280,14 @@ func TestAccAWSRoute_noopdiff(t *testing.T) { CheckDestroy: testAccCheckAWSRouteDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSRouteNoopChange(), + Config: testAccAWSRouteNoopChange, Check: resource.ComposeTestCheckFunc( testAccCheckAWSRouteExists("aws_route.test", &route), testCheck, ), }, { - Config: testAccAWSRouteNoopChange(), + Config: testAccAWSRouteNoopChange, Check: resource.ComposeTestCheckFunc( testAccCheckAWSRouteExists("aws_route.test", &route), testAccCheckRouteTableExists("aws_route_table.test", &routeTable), @@ -546,34 +462,71 @@ func testAccAWSRouteImportStateIdFunc(resourceName string) resource.ImportStateI } } -func testAccAWSRouteBasicConfig() string { +func testAccCheckAWSRouteInternetGatewayRoute(n string, route *ec2.Route, cidr string) resource.TestCheckFunc { + return func(s *terraform.State) error { + if aws.StringValue(route.DestinationCidrBlock) != cidr { + return fmt.Errorf("Destination CIDR (Expected=%s, Actual=%s)\n", cidr, aws.StringValue(route.DestinationCidrBlock)) + } + + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s\n", n) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("No ID is set") + } + + if aws.StringValue(route.GatewayId) != rs.Primary.ID { + return fmt.Errorf("Internet Gateway ID (Expected=%s, Actual=%s)\n", rs.Primary.ID, aws.StringValue(route.GatewayId)) + } + + return nil + } +} + +func testAccCheckAWSRouteNumberOfRoutes(routeTable *ec2.RouteTable, n int) resource.TestCheckFunc { + return func(s *terraform.State) error { + if len := len(routeTable.Routes); len != n { + return fmt.Errorf("Route Table has incorrect number of routes (Expected=%d, Actual=%d)\n", n, len) + } + + return nil + } +} + +func testAccAWSRouteConfigBasic(rName, cidr string) string { return fmt.Sprintf(` -resource "aws_vpc" "foo" { +resource "aws_vpc" "test" { cidr_block = "10.1.0.0/16" - + tags = { - Name = "terraform-testacc-route-basic" + Name = %[1]q } } -resource "aws_internet_gateway" "foo" { - vpc_id = aws_vpc.foo.id +resource "aws_internet_gateway" "test" { + vpc_id = aws_vpc.test.id tags = { - Name = "terraform-testacc-route-basic" + Name = %[1]q } } -resource "aws_route_table" "foo" { - vpc_id = aws_vpc.foo.id +resource "aws_route_table" "test" { + vpc_id = aws_vpc.test.id + + tags = { + Name = %[1]q + } } -resource "aws_route" "bar" { - route_table_id = aws_route_table.foo.id - destination_cidr_block = "10.3.0.0/16" - gateway_id = aws_internet_gateway.foo.id +resource "aws_route" "test" { + route_table_id = aws_route_table.test.id + destination_cidr_block = %[2]q + gateway_id = aws_internet_gateway.test.id } -`) +`, rName, cidr) } func testAccAWSRouteConfigIpv6InternetGateway() string { @@ -619,7 +572,7 @@ resource "aws_vpc" "examplevpc" { cidr_block = "10.100.0.0/16" enable_dns_hostnames = true assign_generated_ipv6_cidr_block = true - + tags = { Name = "terraform-testacc-route-ipv6-network-interface" } @@ -661,7 +614,7 @@ resource "aws_subnet" "router-network" { assign_ipv6_address_on_creation = true map_public_ip_on_launch = true availability_zone = data.aws_availability_zones.available.names[0] - + tags = { Name = "tf-acc-route-ipv6-network-interface-router" } @@ -674,7 +627,7 @@ resource "aws_subnet" "client-network" { assign_ipv6_address_on_creation = true map_public_ip_on_launch = false availability_zone = data.aws_availability_zones.available.names[0] - + tags = { Name = "tf-acc-route-ipv6-network-interface-client" } @@ -770,7 +723,7 @@ resource "aws_subnet" "router-network" { assign_ipv6_address_on_creation = true map_public_ip_on_launch = true availability_zone = data.aws_availability_zones.available.names[0] - + tags = { Name = "tf-acc-route-ipv6-instance-router" } @@ -783,7 +736,7 @@ resource "aws_subnet" "client-network" { assign_ipv6_address_on_creation = true map_public_ip_on_launch = false availability_zone = data.aws_availability_zones.available.names[0] - + tags = { Name = "tf-acc-route-ipv6-instance-client" } @@ -826,7 +779,7 @@ resource "aws_vpc" "examplevpc" { cidr_block = "10.100.0.0/16" enable_dns_hostnames = true assign_generated_ipv6_cidr_block = true - + tags = { Name = "terraform-testacc-route-ipv6-instance" } @@ -868,7 +821,7 @@ resource "aws_subnet" "router-network" { assign_ipv6_address_on_creation = true map_public_ip_on_launch = true availability_zone = data.aws_availability_zones.available.names[0] - + tags = { Name = "tf-acc-route-ipv6-instance-router" } @@ -881,7 +834,7 @@ resource "aws_subnet" "client-network" { assign_ipv6_address_on_creation = true map_public_ip_on_launch = false availability_zone = data.aws_availability_zones.available.names[0] - + tags = { Name = "tf-acc-route-ipv6-instance-client" } @@ -921,7 +874,7 @@ func testAccAWSRouteConfigIpv6PeeringConnection() string { resource "aws_vpc" "foo" { cidr_block = "10.0.0.0/16" assign_generated_ipv6_cidr_block = true - + tags = { Name = "terraform-testacc-route-ipv6-peering-connection" } @@ -1004,40 +957,7 @@ resource "aws_route" "bar" { `) } -func testAccAWSRouteBasicConfigChangeCidr() string { - return fmt.Sprintf(` -resource "aws_vpc" "foo" { - cidr_block = "10.1.0.0/16" - - tags = { - Name = "terraform-testacc-route-change-cidr" - } -} - -resource "aws_internet_gateway" "foo" { - vpc_id = aws_vpc.foo.id - - tags = { - Name = "terraform-testacc-route-change-cidr" - } -} - -resource "aws_route_table" "foo" { - vpc_id = aws_vpc.foo.id -} - -resource "aws_route" "bar" { - route_table_id = aws_route_table.foo.id - destination_cidr_block = "10.2.0.0/16" - gateway_id = aws_internet_gateway.foo.id -} -`) -} - -func testAccAWSRouteNoopChange() string { - return testAccAvailableEc2InstanceTypeForAvailabilityZone("aws_subnet.test.availability_zone", "t2.nano", "t3.nano") + - testAccLatestAmazonLinuxHvmEbsAmiConfig() + - fmt.Sprint(` +var testAccAWSRouteNoopChange = fmt.Sprint(` data "aws_availability_zones" "available" { state = "available" @@ -1049,7 +969,7 @@ data "aws_availability_zones" "available" { resource "aws_vpc" "test" { cidr_block = "10.10.0.0/16" - + tags = { Name = "terraform-testacc-route-noop-change" } @@ -1063,7 +983,7 @@ resource "aws_subnet" "test" { availability_zone = data.aws_availability_zones.available.names[0] vpc_id = aws_vpc.test.id cidr_block = "10.10.10.0/24" - + tags = { Name = "tf-acc-route-noop-change" } @@ -1081,7 +1001,6 @@ resource "aws_instance" "nat" { subnet_id = aws_subnet.test.id } `) -} func testAccAWSRouteWithVPCEndpoint() string { return fmt.Sprintf(` @@ -1089,7 +1008,7 @@ data "aws_region" "current" {} resource "aws_vpc" "foo" { cidr_block = "10.1.0.0/16" - + tags = { Name = "terraform-testacc-route-with-vpc-endpoint" } @@ -1124,68 +1043,10 @@ resource "aws_vpc_endpoint" "baz" { `) } -func testAccAWSRouteNewRouteTable() string { - return fmt.Sprintf(` -resource "aws_vpc" "foo" { - cidr_block = "10.1.0.0/16" - - tags = { - Name = "terraform-testacc-route-basic" - } -} - -resource "aws_vpc" "bar" { - cidr_block = "10.2.0.0/16" - - tags = { - Name = "terraform-testacc-route-new-route-table" - } -} - -resource "aws_internet_gateway" "foo" { - vpc_id = aws_vpc.foo.id - - tags = { - Name = "terraform-testacc-route-basic" - } -} - -resource "aws_internet_gateway" "bar" { - vpc_id = aws_vpc.bar.id - - tags = { - Name = "terraform-testacc-route-new-route-table" - } -} - -resource "aws_route_table" "foo" { - vpc_id = aws_vpc.foo.id - - tags = { - Name = "terraform-testacc-route-basic" - } -} - -resource "aws_route_table" "bar" { - vpc_id = aws_vpc.bar.id - - tags = { - Name = "terraform-testacc-route-new-route-table" - } -} - -resource "aws_route" "bar" { - route_table_id = aws_route_table.bar.id - destination_cidr_block = "10.4.0.0/16" - gateway_id = aws_internet_gateway.bar.id -} -`) -} - func testAccAWSRouteConfigTransitGatewayIDDestinatationCidrBlock() string { return testAccAvailableAZsNoOptInDefaultExcludeConfig() + fmt.Sprintf(` -# IncorrectState: Transit Gateway is not available in availability zone usw2-az4 +# IncorrectState: Transit Gateway is not available in availability zone usw2-az4 resource "aws_vpc" "test" { cidr_block = "10.0.0.0/16" From ae3877db7123d2b8865dd9be4807abe24977ab5a Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Thu, 25 Jun 2020 17:08:31 -0400 Subject: [PATCH 02/40] r/aws_route: Rename 'TestAccAWSRoute_ipv6Support' to 'TestAccAWSRoute_ipv6ToEgressOnlyInternetGateway'. Acceptance test output: $ make testacc TEST=./aws/ TESTARGS='-run=TestAccAWSRoute_ipv6ToEgressOnlyInternetGateway' ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws/ -v -count 1 -parallel 20 -run=TestAccAWSRoute_ipv6ToEgressOnlyInternetGateway -timeout 120m === RUN TestAccAWSRoute_ipv6ToEgressOnlyInternetGateway === PAUSE TestAccAWSRoute_ipv6ToEgressOnlyInternetGateway === CONT TestAccAWSRoute_ipv6ToEgressOnlyInternetGateway --- PASS: TestAccAWSRoute_ipv6ToEgressOnlyInternetGateway (61.15s) PASS ok github.com/terraform-providers/terraform-provider-aws/aws 61.206s $ make testacc TEST=./aws/ TESTARGS='-run=TestAccAWSRoute_basic' ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws/ -v -count 1 -parallel 20 -run=TestAccAWSRoute_basic -timeout 120m === RUN TestAccAWSRoute_basic === PAUSE TestAccAWSRoute_basic === CONT TestAccAWSRoute_basic --- PASS: TestAccAWSRoute_basic (52.29s) PASS ok github.com/terraform-providers/terraform-provider-aws/aws 52.339s $ make testacc TEST=./aws/ TESTARGS='-run=TestAccAWSRoute_changeCidr' ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws/ -v -count 1 -parallel 20 -run=TestAccAWSRoute_changeCidr -timeout 120m === RUN TestAccAWSRoute_changeCidr === PAUSE TestAccAWSRoute_changeCidr === CONT TestAccAWSRoute_changeCidr --- PASS: TestAccAWSRoute_changeCidr (78.93s) PASS ok github.com/terraform-providers/terraform-provider-aws/aws 79.529s --- aws/resource_aws_route_test.go | 112 +++++++++++++++++++-------------- 1 file changed, 65 insertions(+), 47 deletions(-) diff --git a/aws/resource_aws_route_test.go b/aws/resource_aws_route_test.go index 2025542be7b4..0d4ad3c50dd5 100644 --- a/aws/resource_aws_route_test.go +++ b/aws/resource_aws_route_test.go @@ -27,7 +27,9 @@ func TestAccAWSRoute_basic(t *testing.T) { Config: testAccAWSRouteConfigBasic(rName, cidr), Check: resource.ComposeTestCheckFunc( testAccCheckAWSRouteExists(resourceName, &route), - testAccCheckAWSRouteInternetGatewayRoute(igwResourceName, &route, cidr), + testAccCheckAWSRouteInternetGatewayRoute(igwResourceName, &route), + resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", cidr), + resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), ), }, { @@ -63,48 +65,35 @@ func TestAccAWSRoute_disappears(t *testing.T) { }) } -func TestAccAWSRoute_ipv6Support(t *testing.T) { +func TestAccAWSRoute_ipv6ToEgressOnlyInternetGateway(t *testing.T) { var route ec2.Route - - //aws creates a default route - testCheck := func(s *terraform.State) error { - - name := "aws_egress_only_internet_gateway.foo" - gwres, ok := s.RootModule().Resources[name] - if !ok { - return fmt.Errorf("Not found: %s\n", name) - } - - if *route.EgressOnlyInternetGatewayId != gwres.Primary.ID { - return fmt.Errorf("Egress Only Internet Gateway Id (Expected=%s, Actual=%s)\n", gwres.Primary.ID, *route.EgressOnlyInternetGatewayId) - } - - return nil - } + resourceName := "aws_route.test" + eoigwResourceName := "aws_egress_only_internet_gateway.test" + rName := acctest.RandomWithPrefix("tf-acc-test") + cidr := "::/0" resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { - testAccPreCheck(t) - }, + PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, CheckDestroy: testAccCheckAWSRouteDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSRouteConfigIpv6(), + Config: testAccAWSRouteConfigIpv6EgressOnlyInternetGateway(rName, cidr), Check: resource.ComposeTestCheckFunc( - testAccCheckAWSRouteExists("aws_route.bar", &route), - testCheck, - resource.TestCheckResourceAttr("aws_route.bar", "destination_ipv6_cidr_block", "::/0"), + testAccCheckAWSRouteExists(resourceName, &route), + testAccCheckAWSRouteEgressOnlyInternetGatewayRoute(eoigwResourceName, &route), + resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", ""), + resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", cidr), ), }, { - ResourceName: "aws_route.bar", + ResourceName: resourceName, ImportState: true, - ImportStateIdFunc: testAccAWSRouteImportStateIdFunc("aws_route.bar"), + ImportStateIdFunc: testAccAWSRouteImportStateIdFunc(resourceName), ImportStateVerify: true, }, { - Config: testAccAWSRouteConfigIpv6Expanded(), + Config: testAccAWSRouteConfigIpv6EgressOnlyInternetGateway(rName, "::0/0"), PlanOnly: true, }, }, @@ -238,16 +227,22 @@ func TestAccAWSRoute_changeCidr(t *testing.T) { Config: testAccAWSRouteConfigBasic(rName, cidr), Check: resource.ComposeTestCheckFunc( testAccCheckAWSRouteExists(resourceName, &route), - testAccCheckAWSRouteInternetGatewayRoute(igwResourceName, &route, cidr), + testAccCheckAWSRouteInternetGatewayRoute(igwResourceName, &route), + testAccCheckRouteTableExists(rtResourceName, &routeTable), + testAccCheckAWSRouteNumberOfRoutes(&routeTable, 2), + resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", cidr), + resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), ), }, { Config: testAccAWSRouteConfigBasic(rName, changedCidr), Check: resource.ComposeTestCheckFunc( testAccCheckAWSRouteExists(resourceName, &route), - testAccCheckAWSRouteInternetGatewayRoute(igwResourceName, &route, changedCidr), + testAccCheckAWSRouteInternetGatewayRoute(igwResourceName, &route), testAccCheckRouteTableExists(rtResourceName, &routeTable), testAccCheckAWSRouteNumberOfRoutes(&routeTable, 2), + resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", changedCidr), + resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), ), }, { @@ -462,12 +457,27 @@ func testAccAWSRouteImportStateIdFunc(resourceName string) resource.ImportStateI } } -func testAccCheckAWSRouteInternetGatewayRoute(n string, route *ec2.Route, cidr string) resource.TestCheckFunc { +func testAccCheckAWSRouteInternetGatewayRoute(n string, route *ec2.Route) resource.TestCheckFunc { return func(s *terraform.State) error { - if aws.StringValue(route.DestinationCidrBlock) != cidr { - return fmt.Errorf("Destination CIDR (Expected=%s, Actual=%s)\n", cidr, aws.StringValue(route.DestinationCidrBlock)) + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s\n", n) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("No ID is set") + } + + if gwId := aws.StringValue(route.GatewayId); gwId != rs.Primary.ID { + return fmt.Errorf("Internet Gateway ID (Expected=%s, Actual=%s)\n", rs.Primary.ID, gwId) } + return nil + } +} + +func testAccCheckAWSRouteEgressOnlyInternetGatewayRoute(n string, route *ec2.Route) resource.TestCheckFunc { + return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] if !ok { return fmt.Errorf("Not found: %s\n", n) @@ -477,8 +487,8 @@ func testAccCheckAWSRouteInternetGatewayRoute(n string, route *ec2.Route, cidr s return fmt.Errorf("No ID is set") } - if aws.StringValue(route.GatewayId) != rs.Primary.ID { - return fmt.Errorf("Internet Gateway ID (Expected=%s, Actual=%s)\n", rs.Primary.ID, aws.StringValue(route.GatewayId)) + if gwId := aws.StringValue(route.EgressOnlyInternetGatewayId); gwId != rs.Primary.ID { + return fmt.Errorf("Egress Only Internet Gateway ID (Expected=%s, Actual=%s)\n", rs.Primary.ID, gwId) } return nil @@ -903,31 +913,39 @@ resource "aws_route" "pc" { `) } -func testAccAWSRouteConfigIpv6() string { +func testAccAWSRouteConfigIpv6EgressOnlyInternetGateway(rName, cidr string) string { return fmt.Sprintf(` -resource "aws_vpc" "foo" { +resource "aws_vpc" "test" { cidr_block = "10.1.0.0/16" assign_generated_ipv6_cidr_block = true tags = { - Name = "terraform-testacc-route-ipv6" + Name = %[1]q } } -resource "aws_egress_only_internet_gateway" "foo" { - vpc_id = aws_vpc.foo.id +resource "aws_egress_only_internet_gateway" "test" { + vpc_id = aws_vpc.test.id + + tags = { + Name = %[1]q + } } -resource "aws_route_table" "foo" { - vpc_id = aws_vpc.foo.id +resource "aws_route_table" "test" { + vpc_id = aws_vpc.test.id + + tags = { + Name = %[1]q + } } -resource "aws_route" "bar" { - route_table_id = aws_route_table.foo.id - destination_ipv6_cidr_block = "::/0" - egress_only_gateway_id = aws_egress_only_internet_gateway.foo.id +resource "aws_route" "test" { + route_table_id = aws_route_table.test.id + destination_ipv6_cidr_block = %[2]q + egress_only_gateway_id = aws_egress_only_internet_gateway.test.id } -`) +`, rName, cidr) } func testAccAWSRouteConfigIpv6Expanded() string { From 898d88f4d597c4d8e5b79ea28f80b6486e57c97b Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Thu, 25 Jun 2020 17:15:00 -0400 Subject: [PATCH 03/40] Remove 'TestAccAWSRoute_noopdiff'. Test steps implicitly test this functionality. --- aws/resource_aws_route_test.go | 97 +--------------------------------- 1 file changed, 2 insertions(+), 95 deletions(-) diff --git a/aws/resource_aws_route_test.go b/aws/resource_aws_route_test.go index 0d4ad3c50dd5..2401bcf36827 100644 --- a/aws/resource_aws_route_test.go +++ b/aws/resource_aws_route_test.go @@ -255,50 +255,6 @@ func TestAccAWSRoute_changeCidr(t *testing.T) { }) } -func TestAccAWSRoute_noopdiff(t *testing.T) { - var route ec2.Route - var routeTable ec2.RouteTable - - testCheck := func(s *terraform.State) error { - return nil - } - - testCheckChange := func(s *terraform.State) error { - return nil - } - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { - testAccPreCheck(t) - }, - Providers: testAccProviders, - CheckDestroy: testAccCheckAWSRouteDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAWSRouteNoopChange, - Check: resource.ComposeTestCheckFunc( - testAccCheckAWSRouteExists("aws_route.test", &route), - testCheck, - ), - }, - { - Config: testAccAWSRouteNoopChange, - Check: resource.ComposeTestCheckFunc( - testAccCheckAWSRouteExists("aws_route.test", &route), - testAccCheckRouteTableExists("aws_route_table.test", &routeTable), - testCheckChange, - ), - }, - { - ResourceName: "aws_route.test", - ImportState: true, - ImportStateIdFunc: testAccAWSRouteImportStateIdFunc("aws_route.test"), - ImportStateVerify: true, - }, - }, - }) -} - func TestAccAWSRoute_doesNotCrashWithVPCEndpoint(t *testing.T) { var route ec2.Route @@ -308,7 +264,7 @@ func TestAccAWSRoute_doesNotCrashWithVPCEndpoint(t *testing.T) { CheckDestroy: testAccCheckAWSRouteDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSRouteWithVPCEndpoint(), + Config: testAccAWSRouteWithVPCEndpoint, Check: resource.ComposeTestCheckFunc( testAccCheckAWSRouteExists("aws_route.bar", &route), ), @@ -975,55 +931,7 @@ resource "aws_route" "bar" { `) } -var testAccAWSRouteNoopChange = fmt.Sprint(` -data "aws_availability_zones" "available" { - state = "available" - - filter { - name = "opt-in-status" - values = ["opt-in-not-required"] - } -} - -resource "aws_vpc" "test" { - cidr_block = "10.10.0.0/16" - - tags = { - Name = "terraform-testacc-route-noop-change" - } -} - -resource "aws_route_table" "test" { - vpc_id = aws_vpc.test.id -} - -resource "aws_subnet" "test" { - availability_zone = data.aws_availability_zones.available.names[0] - vpc_id = aws_vpc.test.id - cidr_block = "10.10.10.0/24" - - tags = { - Name = "tf-acc-route-noop-change" - } -} - -resource "aws_route" "test" { - route_table_id = aws_route_table.test.id - destination_cidr_block = "0.0.0.0/0" - instance_id = aws_instance.nat.id -} - -resource "aws_instance" "nat" { - ami = data.aws_ami.amzn-ami-minimal-hvm-ebs.id - instance_type = data.aws_ec2_instance_type_offering.available.instance_type - subnet_id = aws_subnet.test.id -} -`) - -func testAccAWSRouteWithVPCEndpoint() string { - return fmt.Sprintf(` -data "aws_region" "current" {} - +var testAccAWSRouteWithVPCEndpoint = fmt.Sprint(` resource "aws_vpc" "foo" { cidr_block = "10.1.0.0/16" @@ -1059,7 +967,6 @@ resource "aws_vpc_endpoint" "baz" { route_table_ids = [aws_route_table.foo.id] } `) -} func testAccAWSRouteConfigTransitGatewayIDDestinatationCidrBlock() string { return testAccAvailableAZsNoOptInDefaultExcludeConfig() + From 21a7be4bab6e14acfc833fe66cf2595aa2b7db4b Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Thu, 25 Jun 2020 17:47:52 -0400 Subject: [PATCH 04/40] r/aws_route: Tidy up 'TestAccAWSRoute_doesNotCrashWithVPCEndpoint'. Acceptance test output: $ make testacc TEST=./aws/ TESTARGS='-run=TestAccAWSRoute_doesNotCrashWithVPCEndpoint' ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws/ -v -count 1 -parallel 20 -run=TestAccAWSRoute_doesNotCrashWithVPCEndpoint -timeout 120m === RUN TestAccAWSRoute_doesNotCrashWithVPCEndpoint === PAUSE TestAccAWSRoute_doesNotCrashWithVPCEndpoint === CONT TestAccAWSRoute_doesNotCrashWithVPCEndpoint --- PASS: TestAccAWSRoute_doesNotCrashWithVPCEndpoint (62.84s) PASS ok github.com/terraform-providers/terraform-provider-aws/aws 62.882s --- aws/resource_aws_route_test.go | 50 ++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/aws/resource_aws_route_test.go b/aws/resource_aws_route_test.go index 2401bcf36827..717d15edb07b 100644 --- a/aws/resource_aws_route_test.go +++ b/aws/resource_aws_route_test.go @@ -257,6 +257,8 @@ func TestAccAWSRoute_changeCidr(t *testing.T) { func TestAccAWSRoute_doesNotCrashWithVPCEndpoint(t *testing.T) { var route ec2.Route + resourceName := "aws_route.test" + rName := acctest.RandomWithPrefix("tf-acc-test") resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -264,15 +266,15 @@ func TestAccAWSRoute_doesNotCrashWithVPCEndpoint(t *testing.T) { CheckDestroy: testAccCheckAWSRouteDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSRouteWithVPCEndpoint, + Config: testAccAWSRouteWithVPCEndpoint(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckAWSRouteExists("aws_route.bar", &route), + testAccCheckAWSRouteExists(resourceName, &route), ), }, { - ResourceName: "aws_route.bar", + ResourceName: resourceName, ImportState: true, - ImportStateIdFunc: testAccAWSRouteImportStateIdFunc("aws_route.bar"), + ImportStateIdFunc: testAccAWSRouteImportStateIdFunc(resourceName), ImportStateVerify: true, }, }, @@ -931,42 +933,50 @@ resource "aws_route" "bar" { `) } -var testAccAWSRouteWithVPCEndpoint = fmt.Sprint(` -resource "aws_vpc" "foo" { +func testAccAWSRouteWithVPCEndpoint(rName string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { cidr_block = "10.1.0.0/16" tags = { - Name = "terraform-testacc-route-with-vpc-endpoint" + Name = %[1]q } } -resource "aws_internet_gateway" "foo" { - vpc_id = aws_vpc.foo.id +resource "aws_internet_gateway" "test" { + vpc_id = aws_vpc.test.id tags = { - Name = "terraform-testacc-route-with-vpc-endpoint" + Name = %[1]q } } -resource "aws_route_table" "foo" { - vpc_id = aws_vpc.foo.id +resource "aws_route_table" "test" { + vpc_id = aws_vpc.test.id + + tags = { + Name = %[1]q + } } -resource "aws_route" "bar" { - route_table_id = aws_route_table.foo.id +resource "aws_route" "test" { + route_table_id = aws_route_table.test.id destination_cidr_block = "10.3.0.0/16" - gateway_id = aws_internet_gateway.foo.id + gateway_id = aws_internet_gateway.test.id # Forcing endpoint to create before route - without this the crash is a race. - depends_on = ["aws_vpc_endpoint.baz"] + depends_on = [aws_vpc_endpoint.test] } -resource "aws_vpc_endpoint" "baz" { - vpc_id = aws_vpc.foo.id +data "aws_region" "current" {} + +resource "aws_vpc_endpoint" "test" { + vpc_id = aws_vpc.test.id service_name = "com.amazonaws.${data.aws_region.current.name}.s3" - route_table_ids = [aws_route_table.foo.id] + route_table_ids = [aws_route_table.test.id] +} +`, rName) } -`) func testAccAWSRouteConfigTransitGatewayIDDestinatationCidrBlock() string { return testAccAvailableAZsNoOptInDefaultExcludeConfig() + From 14619ce453b08992567bb8d62b7b3852d49bee64 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 26 Jun 2020 10:26:42 -0400 Subject: [PATCH 05/40] r/aws_route: Tidy up 'TestAccAWSRoute_ipv6ToInternetGateway'. Acceptance test output: $ make testacc TEST=./aws/ TESTARGS='-run=TestAccAWSRoute_ipv6ToInternetGateway' ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws/ -v -count 1 -parallel 20 -run=TestAccAWSRoute_ipv6ToInternetGateway -timeout 120m === RUN TestAccAWSRoute_ipv6ToInternetGateway === PAUSE TestAccAWSRoute_ipv6ToInternetGateway === CONT TestAccAWSRoute_ipv6ToInternetGateway --- PASS: TestAccAWSRoute_ipv6ToInternetGateway (51.99s) PASS ok github.com/terraform-providers/terraform-provider-aws/aws 52.050s --- aws/resource_aws_route_test.go | 145 ++++++++++++++++----------------- 1 file changed, 70 insertions(+), 75 deletions(-) diff --git a/aws/resource_aws_route_test.go b/aws/resource_aws_route_test.go index 717d15edb07b..5342bf280254 100644 --- a/aws/resource_aws_route_test.go +++ b/aws/resource_aws_route_test.go @@ -13,10 +13,12 @@ import ( func TestAccAWSRoute_basic(t *testing.T) { var route ec2.Route + var routeTable ec2.RouteTable resourceName := "aws_route.test" igwResourceName := "aws_internet_gateway.test" + rtResourceName := "aws_route_table.test" rName := acctest.RandomWithPrefix("tf-acc-test") - cidr := "10.3.0.0/16" + destinationCidr := "10.3.0.0/16" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -24,11 +26,13 @@ func TestAccAWSRoute_basic(t *testing.T) { CheckDestroy: testAccCheckAWSRouteDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSRouteConfigBasic(rName, cidr), + Config: testAccAWSRouteConfigIpv4InternetGateway(rName, destinationCidr), Check: resource.ComposeTestCheckFunc( testAccCheckAWSRouteExists(resourceName, &route), - testAccCheckAWSRouteInternetGatewayRoute(igwResourceName, &route), - resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", cidr), + testAccCheckAWSRouteGatewayRoute(igwResourceName, &route), + testAccCheckRouteTableExists(rtResourceName, &routeTable), + testAccCheckAWSRouteNumberOfRoutes(&routeTable, 2), + resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", destinationCidr), resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), ), }, @@ -46,7 +50,7 @@ func TestAccAWSRoute_disappears(t *testing.T) { var route ec2.Route resourceName := "aws_route.test" rName := acctest.RandomWithPrefix("tf-acc-test") - cidr := "10.3.0.0/16" + destinationCidr := "10.3.0.0/16" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -54,7 +58,7 @@ func TestAccAWSRoute_disappears(t *testing.T) { CheckDestroy: testAccCheckAWSRouteDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSRouteConfigBasic(rName, cidr), + Config: testAccAWSRouteConfigIpv4InternetGateway(rName, destinationCidr), Check: resource.ComposeTestCheckFunc( testAccCheckAWSRouteExists(resourceName, &route), testAccCheckResourceDisappears(testAccProvider, resourceAwsRoute(), resourceName), @@ -70,7 +74,7 @@ func TestAccAWSRoute_ipv6ToEgressOnlyInternetGateway(t *testing.T) { resourceName := "aws_route.test" eoigwResourceName := "aws_egress_only_internet_gateway.test" rName := acctest.RandomWithPrefix("tf-acc-test") - cidr := "::/0" + destinationCidr := "::/0" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -78,12 +82,12 @@ func TestAccAWSRoute_ipv6ToEgressOnlyInternetGateway(t *testing.T) { CheckDestroy: testAccCheckAWSRouteDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSRouteConfigIpv6EgressOnlyInternetGateway(rName, cidr), + Config: testAccAWSRouteConfigIpv6EgressOnlyInternetGateway(rName, destinationCidr), Check: resource.ComposeTestCheckFunc( testAccCheckAWSRouteExists(resourceName, &route), testAccCheckAWSRouteEgressOnlyInternetGatewayRoute(eoigwResourceName, &route), resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", ""), - resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", cidr), + resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", destinationCidr), ), }, { @@ -93,6 +97,7 @@ func TestAccAWSRoute_ipv6ToEgressOnlyInternetGateway(t *testing.T) { ImportStateVerify: true, }, { + // Verify that expanded form of the destination CIDR causes no diff. Config: testAccAWSRouteConfigIpv6EgressOnlyInternetGateway(rName, "::0/0"), PlanOnly: true, }, @@ -102,24 +107,29 @@ func TestAccAWSRoute_ipv6ToEgressOnlyInternetGateway(t *testing.T) { func TestAccAWSRoute_ipv6ToInternetGateway(t *testing.T) { var route ec2.Route + resourceName := "aws_route.test" + igwResourceName := "aws_internet_gateway.test" + rName := acctest.RandomWithPrefix("tf-acc-test") + destinationCidr := "::/0" resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { - testAccPreCheck(t) - }, + PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, CheckDestroy: testAccCheckAWSRouteDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSRouteConfigIpv6InternetGateway(), + Config: testAccAWSRouteConfigIpv6InternetGateway(rName, destinationCidr), Check: resource.ComposeTestCheckFunc( - testAccCheckAWSRouteExists("aws_route.igw", &route), + testAccCheckAWSRouteExists(resourceName, &route), + testAccCheckAWSRouteGatewayRoute(igwResourceName, &route), + resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", ""), + resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", destinationCidr), ), }, { - ResourceName: "aws_route.igw", + ResourceName: resourceName, ImportState: true, - ImportStateIdFunc: testAccAWSRouteImportStateIdFunc("aws_route.igw"), + ImportStateIdFunc: testAccAWSRouteImportStateIdFunc(resourceName), ImportStateVerify: true, }, }, @@ -208,15 +218,15 @@ func TestAccAWSRoute_ipv6ToPeeringConnection(t *testing.T) { }) } -func TestAccAWSRoute_changeCidr(t *testing.T) { +func TestAccAWSRoute_ipv4ToInternetGateway(t *testing.T) { var route ec2.Route var routeTable ec2.RouteTable resourceName := "aws_route.test" igwResourceName := "aws_internet_gateway.test" rtResourceName := "aws_route_table.test" rName := acctest.RandomWithPrefix("tf-acc-test") - cidr := "10.3.0.0/16" - changedCidr := "10.2.0.0/16" + destinationCidr := "10.3.0.0/16" + changedDestinationCidr := "10.2.0.0/16" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -224,24 +234,24 @@ func TestAccAWSRoute_changeCidr(t *testing.T) { CheckDestroy: testAccCheckAWSRouteDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSRouteConfigBasic(rName, cidr), + Config: testAccAWSRouteConfigIpv4InternetGateway(rName, destinationCidr), Check: resource.ComposeTestCheckFunc( testAccCheckAWSRouteExists(resourceName, &route), - testAccCheckAWSRouteInternetGatewayRoute(igwResourceName, &route), + testAccCheckAWSRouteGatewayRoute(igwResourceName, &route), testAccCheckRouteTableExists(rtResourceName, &routeTable), testAccCheckAWSRouteNumberOfRoutes(&routeTable, 2), - resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", cidr), + resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", destinationCidr), resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), ), }, { - Config: testAccAWSRouteConfigBasic(rName, changedCidr), + Config: testAccAWSRouteConfigIpv4InternetGateway(rName, changedDestinationCidr), Check: resource.ComposeTestCheckFunc( testAccCheckAWSRouteExists(resourceName, &route), - testAccCheckAWSRouteInternetGatewayRoute(igwResourceName, &route), + testAccCheckAWSRouteGatewayRoute(igwResourceName, &route), testAccCheckRouteTableExists(rtResourceName, &routeTable), testAccCheckAWSRouteNumberOfRoutes(&routeTable, 2), - resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", changedCidr), + resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", changedDestinationCidr), resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), ), }, @@ -255,9 +265,11 @@ func TestAccAWSRoute_changeCidr(t *testing.T) { }) } -func TestAccAWSRoute_doesNotCrashWithVPCEndpoint(t *testing.T) { +func TestAccAWSRoute_doesNotCrashWithVpcEndpoint(t *testing.T) { var route ec2.Route + var routeTable ec2.RouteTable resourceName := "aws_route.test" + rtResourceName := "aws_route_table.test" rName := acctest.RandomWithPrefix("tf-acc-test") resource.ParallelTest(t, resource.TestCase{ @@ -266,9 +278,11 @@ func TestAccAWSRoute_doesNotCrashWithVPCEndpoint(t *testing.T) { CheckDestroy: testAccCheckAWSRouteDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSRouteWithVPCEndpoint(rName), + Config: testAccAWSRouteConfigWithVpcEndpoint(rName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSRouteExists(resourceName, &route), + testAccCheckRouteTableExists(rtResourceName, &routeTable), + testAccCheckAWSRouteNumberOfRoutes(&routeTable, 3), ), }, { @@ -415,7 +429,7 @@ func testAccAWSRouteImportStateIdFunc(resourceName string) resource.ImportStateI } } -func testAccCheckAWSRouteInternetGatewayRoute(n string, route *ec2.Route) resource.TestCheckFunc { +func testAccCheckAWSRouteGatewayRoute(n string, route *ec2.Route) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] if !ok { @@ -463,7 +477,7 @@ func testAccCheckAWSRouteNumberOfRoutes(routeTable *ec2.RouteTable, n int) resou } } -func testAccAWSRouteConfigBasic(rName, cidr string) string { +func testAccAWSRouteConfigIpv4InternetGateway(rName, destinationCidr string) string { return fmt.Sprintf(` resource "aws_vpc" "test" { cidr_block = "10.1.0.0/16" @@ -494,42 +508,50 @@ resource "aws_route" "test" { destination_cidr_block = %[2]q gateway_id = aws_internet_gateway.test.id } -`, rName, cidr) +`, rName, destinationCidr) } -func testAccAWSRouteConfigIpv6InternetGateway() string { +func testAccAWSRouteConfigIpv6InternetGateway(rName, destinationCidr string) string { return fmt.Sprintf(` -resource "aws_vpc" "foo" { +resource "aws_vpc" "test" { cidr_block = "10.1.0.0/16" assign_generated_ipv6_cidr_block = true tags = { - Name = "terraform-testacc-route-ipv6-igw" + Name = %[1]q } } -resource "aws_egress_only_internet_gateway" "foo" { - vpc_id = aws_vpc.foo.id +resource "aws_egress_only_internet_gateway" "test" { + vpc_id = aws_vpc.test.id + + tags = { + Name = %[1]q + } } -resource "aws_internet_gateway" "foo" { - vpc_id = aws_vpc.foo.id +resource "aws_internet_gateway" "test" { + vpc_id = aws_vpc.test.id tags = { - Name = "terraform-testacc-route-ipv6-igw" + Name = %[1]q } } -resource "aws_route_table" "external" { - vpc_id = aws_vpc.foo.id +resource "aws_route_table" "test" { + vpc_id = aws_vpc.test.id + + tags = { + Name = %[1]q + } } -resource "aws_route" "igw" { - route_table_id = aws_route_table.external.id - destination_ipv6_cidr_block = "::/0" - gateway_id = aws_internet_gateway.foo.id +resource "aws_route" "test" { + route_table_id = aws_route_table.test.id + destination_ipv6_cidr_block = %[2]q + gateway_id = aws_internet_gateway.test.id } -`) +`, rName, destinationCidr) } func testAccAWSRouteConfigIpv6NetworkInterface() string { @@ -871,7 +893,7 @@ resource "aws_route" "pc" { `) } -func testAccAWSRouteConfigIpv6EgressOnlyInternetGateway(rName, cidr string) string { +func testAccAWSRouteConfigIpv6EgressOnlyInternetGateway(rName, destinationCidr string) string { return fmt.Sprintf(` resource "aws_vpc" "test" { cidr_block = "10.1.0.0/16" @@ -903,37 +925,10 @@ resource "aws_route" "test" { destination_ipv6_cidr_block = %[2]q egress_only_gateway_id = aws_egress_only_internet_gateway.test.id } -`, rName, cidr) -} - -func testAccAWSRouteConfigIpv6Expanded() string { - return fmt.Sprintf(` -resource "aws_vpc" "foo" { - cidr_block = "10.1.0.0/16" - assign_generated_ipv6_cidr_block = true - - tags = { - Name = "terraform-testacc-route-ipv6" - } -} - -resource "aws_egress_only_internet_gateway" "foo" { - vpc_id = aws_vpc.foo.id -} - -resource "aws_route_table" "foo" { - vpc_id = aws_vpc.foo.id -} - -resource "aws_route" "bar" { - route_table_id = aws_route_table.foo.id - destination_ipv6_cidr_block = "::0/0" - egress_only_gateway_id = aws_egress_only_internet_gateway.foo.id -} -`) +`, rName, destinationCidr) } -func testAccAWSRouteWithVPCEndpoint(rName string) string { +func testAccAWSRouteConfigWithVpcEndpoint(rName string) string { return fmt.Sprintf(` resource "aws_vpc" "test" { cidr_block = "10.1.0.0/16" From e614a3f8c08c26ab9f392d55b5759da992940d49 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 26 Jun 2020 11:00:45 -0400 Subject: [PATCH 06/40] r/aws_route: Tidy up 'TestAccAWSRoute_ipv6ToInstance'. Acceptance test output: $ make testacc TEST=./aws/ TESTARGS='-run=TestAccAWSRoute_ipv6ToInstance' ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws/ -v -count 1 -parallel 20 -run=TestAccAWSRoute_ipv6ToInstance -timeout 120m === RUN TestAccAWSRoute_ipv6ToInstance === PAUSE TestAccAWSRoute_ipv6ToInstance === CONT TestAccAWSRoute_ipv6ToInstance --- PASS: TestAccAWSRoute_ipv6ToInstance (111.03s) PASS ok github.com/terraform-providers/terraform-provider-aws/aws 111.103s --- aws/resource_aws_route_test.go | 240 +++++++++------------------------ 1 file changed, 64 insertions(+), 176 deletions(-) diff --git a/aws/resource_aws_route_test.go b/aws/resource_aws_route_test.go index 5342bf280254..0133721cf885 100644 --- a/aws/resource_aws_route_test.go +++ b/aws/resource_aws_route_test.go @@ -138,30 +138,31 @@ func TestAccAWSRoute_ipv6ToInternetGateway(t *testing.T) { func TestAccAWSRoute_ipv6ToInstance(t *testing.T) { var route ec2.Route + resourceName := "aws_route.test" + instanceResourceName := "aws_instance.test" + rName := acctest.RandomWithPrefix("tf-acc-test") + destinationCidr := "::/0" resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { - testAccPreCheck(t) - }, + PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, CheckDestroy: testAccCheckAWSRouteDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSRouteConfigIpv6Instance(), + Config: testAccAWSRouteConfigIpv6Instance(rName, destinationCidr), Check: resource.ComposeTestCheckFunc( - testAccCheckAWSRouteExists("aws_route.internal-default-route-ipv6", &route), + testAccCheckAWSRouteExists(resourceName, &route), + testAccCheckAWSRouteInstanceRoute(instanceResourceName, &route), + resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", ""), + resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", destinationCidr), ), }, { - ResourceName: "aws_route.internal-default-route-ipv6", + ResourceName: resourceName, ImportState: true, - ImportStateIdFunc: testAccAWSRouteImportStateIdFunc("aws_route.internal-default-route-ipv6"), + ImportStateIdFunc: testAccAWSRouteImportStateIdFunc(resourceName), ImportStateVerify: true, }, - { - Config: testAccAWSRouteConfigIpv6InstanceExpanded(), - PlanOnly: true, - }, }, }) } @@ -429,6 +430,25 @@ func testAccAWSRouteImportStateIdFunc(resourceName string) resource.ImportStateI } } +func testAccCheckAWSRouteEgressOnlyInternetGatewayRoute(n string, route *ec2.Route) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s\n", n) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("No ID is set") + } + + if gwId := aws.StringValue(route.EgressOnlyInternetGatewayId); gwId != rs.Primary.ID { + return fmt.Errorf("Egress Only Internet Gateway ID (Expected=%s, Actual=%s)\n", rs.Primary.ID, gwId) + } + + return nil + } +} + func testAccCheckAWSRouteGatewayRoute(n string, route *ec2.Route) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] @@ -448,7 +468,7 @@ func testAccCheckAWSRouteGatewayRoute(n string, route *ec2.Route) resource.TestC } } -func testAccCheckAWSRouteEgressOnlyInternetGatewayRoute(n string, route *ec2.Route) resource.TestCheckFunc { +func testAccCheckAWSRouteInstanceRoute(n string, route *ec2.Route) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] if !ok { @@ -459,8 +479,8 @@ func testAccCheckAWSRouteEgressOnlyInternetGatewayRoute(n string, route *ec2.Rou return fmt.Errorf("No ID is set") } - if gwId := aws.StringValue(route.EgressOnlyInternetGatewayId); gwId != rs.Primary.ID { - return fmt.Errorf("Egress Only Internet Gateway ID (Expected=%s, Actual=%s)\n", rs.Primary.ID, gwId) + if gwId := aws.StringValue(route.InstanceId); gwId != rs.Primary.ID { + return fmt.Errorf("Instance ID (Expected=%s, Actual=%s)\n", rs.Primary.ID, gwId) } return nil @@ -663,22 +683,15 @@ resource "aws_route" "internal-default-route-ipv6" { `) } -func testAccAWSRouteConfigIpv6Instance() string { - return testAccAvailableEc2InstanceTypeForAvailabilityZone("aws_subnet.router-network.availability_zone", "t2.small", "t3.small") + - testAccLatestAmazonLinuxHvmEbsAmiConfig() + +func testAccAWSRouteConfigIpv6Instance(rName, destinationCidr string) string { + return composeConfig( + testAccLatestAmazonLinuxHvmEbsAmiConfig(), + testAccAvailableEc2InstanceTypeForRegion("t3.micro", "t2.micro"), fmt.Sprintf(` -resource "aws_vpc" "examplevpc" { - cidr_block = "10.100.0.0/16" - enable_dns_hostnames = true - assign_generated_ipv6_cidr_block = true - - tags = { - Name = "terraform-testacc-route-ipv6-instance" - } -} - -data "aws_availability_zones" "available" { - state = "available" +data "aws_availability_zones" "current" { + # Exclude usw2-az4 (us-west-2d) as it has limited instance types. + blacklisted_zone_ids = ["usw2-az4"] + state = "available" filter { name = "opt-in-status" @@ -686,177 +699,52 @@ data "aws_availability_zones" "available" { } } -resource "aws_internet_gateway" "internet" { - vpc_id = aws_vpc.examplevpc.id - - tags = { - Name = "terraform-testacc-route-ipv6-instance" - } -} - -resource "aws_route" "igw" { - route_table_id = aws_vpc.examplevpc.main_route_table_id - destination_cidr_block = "0.0.0.0/0" - gateway_id = aws_internet_gateway.internet.id -} - -resource "aws_route" "igw-ipv6" { - route_table_id = aws_vpc.examplevpc.main_route_table_id - destination_ipv6_cidr_block = "::/0" - gateway_id = aws_internet_gateway.internet.id -} - -resource "aws_subnet" "router-network" { - cidr_block = "10.100.1.0/24" - vpc_id = aws_vpc.examplevpc.id - ipv6_cidr_block = cidrsubnet(aws_vpc.examplevpc.ipv6_cidr_block, 8, 1) - assign_ipv6_address_on_creation = true - map_public_ip_on_launch = true - availability_zone = data.aws_availability_zones.available.names[0] +resource "aws_vpc" "test" { + cidr_block = "10.1.0.0/16" + assign_generated_ipv6_cidr_block = true tags = { - Name = "tf-acc-route-ipv6-instance-router" + Name = %[1]q } } -resource "aws_subnet" "client-network" { - cidr_block = "10.100.10.0/24" - vpc_id = aws_vpc.examplevpc.id - ipv6_cidr_block = cidrsubnet(aws_vpc.examplevpc.ipv6_cidr_block, 8, 2) - assign_ipv6_address_on_creation = true - map_public_ip_on_launch = false - availability_zone = data.aws_availability_zones.available.names[0] +resource "aws_subnet" "test" { + cidr_block = "10.1.1.0/24" + vpc_id = aws_vpc.test.id + availability_zone = data.aws_availability_zones.current.names[0] + ipv6_cidr_block = cidrsubnet(aws_vpc.test.ipv6_cidr_block, 8, 1) tags = { - Name = "tf-acc-route-ipv6-instance-client" + Name = %[1]q } } -resource "aws_route_table" "client-routes" { - vpc_id = aws_vpc.examplevpc.id -} - -resource "aws_route_table_association" "client-routes" { - route_table_id = aws_route_table.client-routes.id - subnet_id = aws_subnet.client-network.id -} - -resource "aws_instance" "test-router" { +resource "aws_instance" "test" { ami = data.aws_ami.amzn-ami-minimal-hvm-ebs.id instance_type = data.aws_ec2_instance_type_offering.available.instance_type - subnet_id = aws_subnet.router-network.id -} - -resource "aws_route" "internal-default-route" { - route_table_id = aws_route_table.client-routes.id - destination_cidr_block = "0.0.0.0/0" - instance_id = aws_instance.test-router.id -} - -resource "aws_route" "internal-default-route-ipv6" { - route_table_id = aws_route_table.client-routes.id - destination_ipv6_cidr_block = "::/0" - instance_id = aws_instance.test-router.id -} -`) -} - -func testAccAWSRouteConfigIpv6InstanceExpanded() string { - return testAccAvailableEc2InstanceTypeForAvailabilityZone("aws_subnet.router-network.availability_zone", "t2.small", "t3.small") + - testAccLatestAmazonLinuxHvmEbsAmiConfig() + - fmt.Sprintf(` -resource "aws_vpc" "examplevpc" { - cidr_block = "10.100.0.0/16" - enable_dns_hostnames = true - assign_generated_ipv6_cidr_block = true - - tags = { - Name = "terraform-testacc-route-ipv6-instance" - } -} - -data "aws_availability_zones" "available" { - state = "available" - - filter { - name = "opt-in-status" - values = ["opt-in-not-required"] - } -} - -resource "aws_internet_gateway" "internet" { - vpc_id = aws_vpc.examplevpc.id - - tags = { - Name = "terraform-testacc-route-ipv6-instance" - } -} - -resource "aws_route" "igw" { - route_table_id = aws_vpc.examplevpc.main_route_table_id - destination_cidr_block = "0.0.0.0/0" - gateway_id = aws_internet_gateway.internet.id -} + subnet_id = aws_subnet.test.id -resource "aws_route" "igw-ipv6" { - route_table_id = aws_vpc.examplevpc.main_route_table_id - destination_ipv6_cidr_block = "::0/0" - gateway_id = aws_internet_gateway.internet.id -} - -resource "aws_subnet" "router-network" { - cidr_block = "10.100.1.0/24" - vpc_id = aws_vpc.examplevpc.id - ipv6_cidr_block = cidrsubnet(aws_vpc.examplevpc.ipv6_cidr_block, 8, 1) - assign_ipv6_address_on_creation = true - map_public_ip_on_launch = true - availability_zone = data.aws_availability_zones.available.names[0] + ipv6_address_count = 1 tags = { - Name = "tf-acc-route-ipv6-instance-router" + Name = %[1]q } } -resource "aws_subnet" "client-network" { - cidr_block = "10.100.10.0/24" - vpc_id = aws_vpc.examplevpc.id - ipv6_cidr_block = cidrsubnet(aws_vpc.examplevpc.ipv6_cidr_block, 8, 2) - assign_ipv6_address_on_creation = true - map_public_ip_on_launch = false - availability_zone = data.aws_availability_zones.available.names[0] +resource "aws_route_table" "test" { + vpc_id = aws_vpc.test.id tags = { - Name = "tf-acc-route-ipv6-instance-client" + Name = %[1]q } } -resource "aws_route_table" "client-routes" { - vpc_id = aws_vpc.examplevpc.id -} - -resource "aws_route_table_association" "client-routes" { - route_table_id = aws_route_table.client-routes.id - subnet_id = aws_subnet.client-network.id -} - -resource "aws_instance" "test-router" { - ami = data.aws_ami.amzn-ami-minimal-hvm-ebs.id - instance_type = data.aws_ec2_instance_type_offering.available.instance_type - subnet_id = aws_subnet.router-network.id -} - -resource "aws_route" "internal-default-route" { - route_table_id = aws_route_table.client-routes.id - destination_cidr_block = "0.0.0.0/0" - instance_id = aws_instance.test-router.id -} - -resource "aws_route" "internal-default-route-ipv6" { - route_table_id = aws_route_table.client-routes.id - destination_ipv6_cidr_block = "::0/0" - instance_id = aws_instance.test-router.id +resource "aws_route" "test" { + route_table_id = aws_route_table.test.id + destination_ipv6_cidr_block = %[2]q + instance_id = aws_instance.test.id } -`) +`, rName, destinationCidr)) } func testAccAWSRouteConfigIpv6PeeringConnection() string { From d169975c98ec11f4f0e0eea78847def30d81dcef Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 26 Jun 2020 11:17:59 -0400 Subject: [PATCH 07/40] r/aws_route: Tidy up 'TestAccAWSRoute_ipv6ToNetworkInterface'. Acceptance test output: $ make testacc TEST=./aws/ TESTARGS='-run=TestAccAWSRoute_ipv6ToNetworkInterface' ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws/ -v -count 1 -parallel 20 -run=TestAccAWSRoute_ipv6ToNetworkInterface -timeout 120m === RUN TestAccAWSRoute_ipv6ToNetworkInterface === PAUSE TestAccAWSRoute_ipv6ToNetworkInterface === CONT TestAccAWSRoute_ipv6ToNetworkInterface --- PASS: TestAccAWSRoute_ipv6ToNetworkInterface (47.92s) PASS ok github.com/terraform-providers/terraform-provider-aws/aws 47.969s --- aws/resource_aws_route_test.go | 143 ++++++++++++++------------------- 1 file changed, 59 insertions(+), 84 deletions(-) diff --git a/aws/resource_aws_route_test.go b/aws/resource_aws_route_test.go index 0133721cf885..0323913d4621 100644 --- a/aws/resource_aws_route_test.go +++ b/aws/resource_aws_route_test.go @@ -169,6 +169,10 @@ func TestAccAWSRoute_ipv6ToInstance(t *testing.T) { func TestAccAWSRoute_ipv6ToNetworkInterface(t *testing.T) { var route ec2.Route + resourceName := "aws_route.test" + eniResourceName := "aws_network_interface.test" + rName := acctest.RandomWithPrefix("tf-acc-test") + destinationCidr := "::/0" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { @@ -178,15 +182,18 @@ func TestAccAWSRoute_ipv6ToNetworkInterface(t *testing.T) { CheckDestroy: testAccCheckAWSRouteDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSRouteConfigIpv6NetworkInterface(), + Config: testAccAWSRouteConfigIpv6NetworkInterface(rName, destinationCidr), Check: resource.ComposeTestCheckFunc( - testAccCheckAWSRouteExists("aws_route.internal-default-route-ipv6", &route), + testAccCheckAWSRouteExists(resourceName, &route), + testAccCheckAWSRouteNetworkInterfaceRoute(eniResourceName, &route), + resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", ""), + resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", destinationCidr), ), }, { - ResourceName: "aws_route.internal-default-route-ipv6", + ResourceName: resourceName, ImportState: true, - ImportStateIdFunc: testAccAWSRouteImportStateIdFunc("aws_route.internal-default-route-ipv6"), + ImportStateIdFunc: testAccAWSRouteImportStateIdFunc(resourceName), ImportStateVerify: true, }, }, @@ -487,6 +494,25 @@ func testAccCheckAWSRouteInstanceRoute(n string, route *ec2.Route) resource.Test } } +func testAccCheckAWSRouteNetworkInterfaceRoute(n string, route *ec2.Route) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s\n", n) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("No ID is set") + } + + if gwId := aws.StringValue(route.NetworkInterfaceId); gwId != rs.Primary.ID { + return fmt.Errorf("Network Interface ID (Expected=%s, Actual=%s)\n", rs.Primary.ID, gwId) + } + + return nil + } +} + func testAccCheckAWSRouteNumberOfRoutes(routeTable *ec2.RouteTable, n int) resource.TestCheckFunc { return func(s *terraform.State) error { if len := len(routeTable.Routes); len != n { @@ -574,22 +600,12 @@ resource "aws_route" "test" { `, rName, destinationCidr) } -func testAccAWSRouteConfigIpv6NetworkInterface() string { - return testAccAvailableEc2InstanceTypeForAvailabilityZone("aws_subnet.router-network.availability_zone", "t2.small", "t3.small") + - testAccLatestAmazonLinuxHvmEbsAmiConfig() + - fmt.Sprintf(` -resource "aws_vpc" "examplevpc" { - cidr_block = "10.100.0.0/16" - enable_dns_hostnames = true - assign_generated_ipv6_cidr_block = true - - tags = { - Name = "terraform-testacc-route-ipv6-network-interface" - } -} - -data "aws_availability_zones" "available" { - state = "available" +func testAccAWSRouteConfigIpv6NetworkInterface(rName, destinationCidr string) string { + return fmt.Sprintf(` +data "aws_availability_zones" "current" { + # Exclude usw2-az4 (us-west-2d) as it has limited instance types. + blacklisted_zone_ids = ["usw2-az4"] + state = "available" filter { name = "opt-in-status" @@ -597,90 +613,49 @@ data "aws_availability_zones" "available" { } } -resource "aws_internet_gateway" "internet" { - vpc_id = aws_vpc.examplevpc.id +resource "aws_vpc" "test" { + cidr_block = "10.1.0.0/16" + assign_generated_ipv6_cidr_block = true tags = { - Name = "terraform-testacc-route-ipv6-network-interface" + Name = %[1]q } } -resource "aws_route" "igw" { - route_table_id = aws_vpc.examplevpc.main_route_table_id - destination_cidr_block = "0.0.0.0/0" - gateway_id = aws_internet_gateway.internet.id -} - -resource "aws_route" "igw-ipv6" { - route_table_id = aws_vpc.examplevpc.main_route_table_id - destination_ipv6_cidr_block = "::/0" - gateway_id = aws_internet_gateway.internet.id -} - -resource "aws_subnet" "router-network" { - cidr_block = "10.100.1.0/24" - vpc_id = aws_vpc.examplevpc.id - ipv6_cidr_block = cidrsubnet(aws_vpc.examplevpc.ipv6_cidr_block, 8, 1) - assign_ipv6_address_on_creation = true - map_public_ip_on_launch = true - availability_zone = data.aws_availability_zones.available.names[0] +resource "aws_subnet" "test" { + cidr_block = "10.1.1.0/24" + vpc_id = aws_vpc.test.id + availability_zone = data.aws_availability_zones.current.names[0] + ipv6_cidr_block = cidrsubnet(aws_vpc.test.ipv6_cidr_block, 8, 1) tags = { - Name = "tf-acc-route-ipv6-network-interface-router" + Name = %[1]q } } -resource "aws_subnet" "client-network" { - cidr_block = "10.100.10.0/24" - vpc_id = aws_vpc.examplevpc.id - ipv6_cidr_block = cidrsubnet(aws_vpc.examplevpc.ipv6_cidr_block, 8, 2) - assign_ipv6_address_on_creation = true - map_public_ip_on_launch = false - availability_zone = data.aws_availability_zones.available.names[0] +resource "aws_network_interface" "test" { + subnet_id = aws_subnet.test.id tags = { - Name = "tf-acc-route-ipv6-network-interface-client" + Name = %[1]q } } -resource "aws_route_table" "client-routes" { - vpc_id = aws_vpc.examplevpc.id -} - -resource "aws_route_table_association" "client-routes" { - route_table_id = aws_route_table.client-routes.id - subnet_id = aws_subnet.client-network.id -} - -resource "aws_instance" "test-router" { - ami = data.aws_ami.amzn-ami-minimal-hvm-ebs.id - instance_type = data.aws_ec2_instance_type_offering.available.instance_type - subnet_id = aws_subnet.router-network.id -} -resource "aws_network_interface" "router-internal" { - subnet_id = aws_subnet.client-network.id - source_dest_check = false -} - -resource "aws_network_interface_attachment" "router-internal" { - device_index = 1 - instance_id = aws_instance.test-router.id - network_interface_id = aws_network_interface.router-internal.id -} +resource "aws_route_table" "test" { + vpc_id = aws_vpc.test.id -resource "aws_route" "internal-default-route" { - route_table_id = aws_route_table.client-routes.id - destination_cidr_block = "0.0.0.0/0" - network_interface_id = aws_network_interface.router-internal.id + tags = { + Name = %[1]q + } } -resource "aws_route" "internal-default-route-ipv6" { - route_table_id = aws_route_table.client-routes.id - destination_ipv6_cidr_block = "::/0" - network_interface_id = aws_network_interface.router-internal.id +resource "aws_route" "test" { + route_table_id = aws_route_table.test.id + destination_ipv6_cidr_block = %[2]q + network_interface_id = aws_network_interface.test.id } -`) +`, rName, destinationCidr) } func testAccAWSRouteConfigIpv6Instance(rName, destinationCidr string) string { From 23d79156a1c41cd5607220970153c8bd63b43a39 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 26 Jun 2020 14:56:30 -0400 Subject: [PATCH 08/40] r/aws_route: Tidy up 'TestAccAWSRoute_ipv6ToVpcPeeringConnection'. Acceptance test output: $ make testacc TEST=./aws/ TESTARGS='-run=TestAccAWSRoute_ipv6ToVpcPeeringConnection' ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws/ -v -count 1 -parallel 20 -run=TestAccAWSRoute_ipv6ToVpcPeeringConnection -timeout 120m === RUN TestAccAWSRoute_ipv6ToVpcPeeringConnection === PAUSE TestAccAWSRoute_ipv6ToVpcPeeringConnection === CONT TestAccAWSRoute_ipv6ToVpcPeeringConnection --- PASS: TestAccAWSRoute_ipv6ToVpcPeeringConnection (44.00s) PASS ok github.com/terraform-providers/terraform-provider-aws/aws 44.054s --- aws/resource_aws_route_test.go | 80 ++++++++++++++++++++++++---------- 1 file changed, 58 insertions(+), 22 deletions(-) diff --git a/aws/resource_aws_route_test.go b/aws/resource_aws_route_test.go index 0323913d4621..80ec5a447644 100644 --- a/aws/resource_aws_route_test.go +++ b/aws/resource_aws_route_test.go @@ -200,26 +200,31 @@ func TestAccAWSRoute_ipv6ToNetworkInterface(t *testing.T) { }) } -func TestAccAWSRoute_ipv6ToPeeringConnection(t *testing.T) { +func TestAccAWSRoute_ipv6ToVpcPeeringConnection(t *testing.T) { var route ec2.Route + resourceName := "aws_route.test" + pcxResourceName := "aws_vpc_peering_connection.test" + rName := acctest.RandomWithPrefix("tf-acc-test") + destinationCidr := "::/0" resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { - testAccPreCheck(t) - }, + PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, CheckDestroy: testAccCheckAWSRouteDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSRouteConfigIpv6PeeringConnection(), + Config: testAccAWSRouteConfigIpv6VpcPeeringConnection(rName, destinationCidr), Check: resource.ComposeTestCheckFunc( - testAccCheckAWSRouteExists("aws_route.pc", &route), + testAccCheckAWSRouteExists(resourceName, &route), + testAccCheckAWSRouteVpcPeeringConnectionRoute(pcxResourceName, &route), + resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", ""), + resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", destinationCidr), ), }, { - ResourceName: "aws_route.pc", + ResourceName: resourceName, ImportState: true, - ImportStateIdFunc: testAccAWSRouteImportStateIdFunc("aws_route.pc"), + ImportStateIdFunc: testAccAWSRouteImportStateIdFunc(resourceName), ImportStateVerify: true, }, }, @@ -513,6 +518,25 @@ func testAccCheckAWSRouteNetworkInterfaceRoute(n string, route *ec2.Route) resou } } +func testAccCheckAWSRouteVpcPeeringConnectionRoute(n string, route *ec2.Route) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s\n", n) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("No ID is set") + } + + if gwId := aws.StringValue(route.VpcPeeringConnectionId); gwId != rs.Primary.ID { + return fmt.Errorf("VPC Peering Connection ID (Expected=%s, Actual=%s)\n", rs.Primary.ID, gwId) + } + + return nil + } +} + func testAccCheckAWSRouteNumberOfRoutes(routeTable *ec2.RouteTable, n int) resource.TestCheckFunc { return func(s *terraform.State) error { if len := len(routeTable.Routes); len != n { @@ -722,38 +746,50 @@ resource "aws_route" "test" { `, rName, destinationCidr)) } -func testAccAWSRouteConfigIpv6PeeringConnection() string { +func testAccAWSRouteConfigIpv6VpcPeeringConnection(rName, destinationCidr string) string { return fmt.Sprintf(` -resource "aws_vpc" "foo" { +resource "aws_vpc" "source" { cidr_block = "10.0.0.0/16" assign_generated_ipv6_cidr_block = true tags = { - Name = "terraform-testacc-route-ipv6-peering-connection" + Name = %[1]q } } -resource "aws_vpc" "bar" { +resource "aws_vpc" "target" { cidr_block = "10.1.0.0/16" assign_generated_ipv6_cidr_block = true + + tags = { + Name = %[1]q + } } -resource "aws_vpc_peering_connection" "foo" { - vpc_id = aws_vpc.foo.id - peer_vpc_id = aws_vpc.bar.id +resource "aws_vpc_peering_connection" "test" { + vpc_id = aws_vpc.source.id + peer_vpc_id = aws_vpc.target.id auto_accept = true + + tags = { + Name = %[1]q + } } -resource "aws_route_table" "peering" { - vpc_id = aws_vpc.foo.id +resource "aws_route_table" "test" { + vpc_id = aws_vpc.source.id + + tags = { + Name = %[1]q + } } -resource "aws_route" "pc" { - route_table_id = aws_route_table.peering.id - destination_ipv6_cidr_block = aws_vpc.bar.ipv6_cidr_block - vpc_peering_connection_id = aws_vpc_peering_connection.foo.id +resource "aws_route" "test" { + route_table_id = aws_route_table.test.id + destination_ipv6_cidr_block = %[2]q + vpc_peering_connection_id = aws_vpc_peering_connection.test.id } -`) +`, rName, destinationCidr) } func testAccAWSRouteConfigIpv6EgressOnlyInternetGateway(rName, destinationCidr string) string { From ce80327646c73ac59429b4ae3eb1d3c7ed56db7f Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 26 Jun 2020 15:23:25 -0400 Subject: [PATCH 09/40] r/aws_route: Tidy up 'TestAccAWSRoute_TransitGatewayID_DestinationCidrBlock' and rename tests. Acceptance test output: $ make testacc TEST=./aws/ TESTARGS='-run=TestAccAWSRoute_' ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws/ -v -count 1 -parallel 2 -run=TestAccAWSRoute_ -timeout 120m === RUN TestAccAWSRoute_basic === PAUSE TestAccAWSRoute_basic === RUN TestAccAWSRoute_disappears === PAUSE TestAccAWSRoute_disappears === RUN TestAccAWSRoute_IPv6_To_EgressOnlyInternetGateway === PAUSE TestAccAWSRoute_IPv6_To_EgressOnlyInternetGateway === RUN TestAccAWSRoute_IPv6_To_InternetGateway === PAUSE TestAccAWSRoute_IPv6_To_InternetGateway === RUN TestAccAWSRoute_IPv6_To_Instance === PAUSE TestAccAWSRoute_IPv6_To_Instance === RUN TestAccAWSRoute_IPv6_To_NetworkInterface === PAUSE TestAccAWSRoute_IPv6_To_NetworkInterface === RUN TestAccAWSRoute_IPv6_To_VpcPeeringConnection === PAUSE TestAccAWSRoute_IPv6_To_VpcPeeringConnection === RUN TestAccAWSRoute_IPv4_To_InternetGateway === PAUSE TestAccAWSRoute_IPv4_To_InternetGateway === RUN TestAccAWSRoute_DoesNotCrashWithVpcEndpoint === PAUSE TestAccAWSRoute_DoesNotCrashWithVpcEndpoint === RUN TestAccAWSRoute_IPv4_To_TransitGateway === PAUSE TestAccAWSRoute_IPv4_To_TransitGateway === RUN TestAccAWSRoute_ConditionalCidrBlock === PAUSE TestAccAWSRoute_ConditionalCidrBlock === CONT TestAccAWSRoute_basic === CONT TestAccAWSRoute_IPv6_To_VpcPeeringConnection --- PASS: TestAccAWSRoute_IPv6_To_VpcPeeringConnection (42.94s) === CONT TestAccAWSRoute_ConditionalCidrBlock --- PASS: TestAccAWSRoute_basic (51.95s) === CONT TestAccAWSRoute_IPv4_To_TransitGateway --- PASS: TestAccAWSRoute_ConditionalCidrBlock (76.30s) === CONT TestAccAWSRoute_DoesNotCrashWithVpcEndpoint --- PASS: TestAccAWSRoute_DoesNotCrashWithVpcEndpoint (61.41s) === CONT TestAccAWSRoute_IPv4_To_InternetGateway --- PASS: TestAccAWSRoute_IPv4_To_InternetGateway (76.58s) === CONT TestAccAWSRoute_IPv6_To_InternetGateway --- PASS: TestAccAWSRoute_IPv6_To_InternetGateway (53.22s) === CONT TestAccAWSRoute_IPv6_To_NetworkInterface --- PASS: TestAccAWSRoute_IPv6_To_NetworkInterface (47.85s) === CONT TestAccAWSRoute_IPv6_To_Instance --- PASS: TestAccAWSRoute_IPv4_To_TransitGateway (315.51s) === CONT TestAccAWSRoute_IPv6_To_EgressOnlyInternetGateway --- PASS: TestAccAWSRoute_IPv6_To_EgressOnlyInternetGateway (59.04s) === CONT TestAccAWSRoute_disappears --- PASS: TestAccAWSRoute_disappears (47.96s) --- PASS: TestAccAWSRoute_IPv6_To_Instance (129.66s) PASS ok github.com/terraform-providers/terraform-provider-aws/aws 488.049s --- aws/resource_aws_route_test.go | 86 ++++++++++++++++++++++++++-------- 1 file changed, 67 insertions(+), 19 deletions(-) diff --git a/aws/resource_aws_route_test.go b/aws/resource_aws_route_test.go index 80ec5a447644..6a23372db486 100644 --- a/aws/resource_aws_route_test.go +++ b/aws/resource_aws_route_test.go @@ -69,7 +69,7 @@ func TestAccAWSRoute_disappears(t *testing.T) { }) } -func TestAccAWSRoute_ipv6ToEgressOnlyInternetGateway(t *testing.T) { +func TestAccAWSRoute_IPv6_To_EgressOnlyInternetGateway(t *testing.T) { var route ec2.Route resourceName := "aws_route.test" eoigwResourceName := "aws_egress_only_internet_gateway.test" @@ -105,7 +105,7 @@ func TestAccAWSRoute_ipv6ToEgressOnlyInternetGateway(t *testing.T) { }) } -func TestAccAWSRoute_ipv6ToInternetGateway(t *testing.T) { +func TestAccAWSRoute_IPv6_To_InternetGateway(t *testing.T) { var route ec2.Route resourceName := "aws_route.test" igwResourceName := "aws_internet_gateway.test" @@ -136,7 +136,7 @@ func TestAccAWSRoute_ipv6ToInternetGateway(t *testing.T) { }) } -func TestAccAWSRoute_ipv6ToInstance(t *testing.T) { +func TestAccAWSRoute_IPv6_To_Instance(t *testing.T) { var route ec2.Route resourceName := "aws_route.test" instanceResourceName := "aws_instance.test" @@ -167,7 +167,7 @@ func TestAccAWSRoute_ipv6ToInstance(t *testing.T) { }) } -func TestAccAWSRoute_ipv6ToNetworkInterface(t *testing.T) { +func TestAccAWSRoute_IPv6_To_NetworkInterface(t *testing.T) { var route ec2.Route resourceName := "aws_route.test" eniResourceName := "aws_network_interface.test" @@ -200,7 +200,7 @@ func TestAccAWSRoute_ipv6ToNetworkInterface(t *testing.T) { }) } -func TestAccAWSRoute_ipv6ToVpcPeeringConnection(t *testing.T) { +func TestAccAWSRoute_IPv6_To_VpcPeeringConnection(t *testing.T) { var route ec2.Route resourceName := "aws_route.test" pcxResourceName := "aws_vpc_peering_connection.test" @@ -231,7 +231,7 @@ func TestAccAWSRoute_ipv6ToVpcPeeringConnection(t *testing.T) { }) } -func TestAccAWSRoute_ipv4ToInternetGateway(t *testing.T) { +func TestAccAWSRoute_IPv4_To_InternetGateway(t *testing.T) { var route ec2.Route var routeTable ec2.RouteTable resourceName := "aws_route.test" @@ -278,7 +278,7 @@ func TestAccAWSRoute_ipv4ToInternetGateway(t *testing.T) { }) } -func TestAccAWSRoute_doesNotCrashWithVpcEndpoint(t *testing.T) { +func TestAccAWSRoute_DoesNotCrashWithVpcEndpoint(t *testing.T) { var route ec2.Route var routeTable ec2.RouteTable resourceName := "aws_route.test" @@ -308,10 +308,12 @@ func TestAccAWSRoute_doesNotCrashWithVpcEndpoint(t *testing.T) { }) } -func TestAccAWSRoute_TransitGatewayID_DestinationCidrBlock(t *testing.T) { +func TestAccAWSRoute_IPv4_To_TransitGateway(t *testing.T) { var route ec2.Route resourceName := "aws_route.test" transitGatewayResourceName := "aws_ec2_transit_gateway.test" + rName := acctest.RandomWithPrefix("tf-acc-test") + destinationCidr := "10.3.0.0/16" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -319,9 +321,12 @@ func TestAccAWSRoute_TransitGatewayID_DestinationCidrBlock(t *testing.T) { CheckDestroy: testAccCheckAWSRouteDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSRouteConfigTransitGatewayIDDestinatationCidrBlock(), + Config: testAccAWSRouteConfigIpv4TransitGateway(rName, destinationCidr), Check: resource.ComposeTestCheckFunc( testAccCheckAWSRouteExists(resourceName, &route), + testAccCheckAWSRouteTransitGatewayRoute(transitGatewayResourceName, &route), + resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", destinationCidr), + resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), resource.TestCheckResourceAttrPair(resourceName, "transit_gateway_id", transitGatewayResourceName, "id"), ), }, @@ -518,6 +523,25 @@ func testAccCheckAWSRouteNetworkInterfaceRoute(n string, route *ec2.Route) resou } } +func testAccCheckAWSRouteTransitGatewayRoute(n string, route *ec2.Route) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s\n", n) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("No ID is set") + } + + if gwId := aws.StringValue(route.TransitGatewayId); gwId != rs.Primary.ID { + return fmt.Errorf("Transit Gateway ID (Expected=%s, Actual=%s)\n", rs.Primary.ID, gwId) + } + + return nil + } +} + func testAccCheckAWSRouteVpcPeeringConnectionRoute(n string, route *ec2.Route) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] @@ -872,16 +896,24 @@ resource "aws_vpc_endpoint" "test" { `, rName) } -func testAccAWSRouteConfigTransitGatewayIDDestinatationCidrBlock() string { - return testAccAvailableAZsNoOptInDefaultExcludeConfig() + - fmt.Sprintf(` -# IncorrectState: Transit Gateway is not available in availability zone usw2-az4 +func testAccAWSRouteConfigIpv4TransitGateway(rName, destinationCidr string) string { + return fmt.Sprintf(` +data "aws_availability_zones" "available" { + # IncorrectState: Transit Gateway is not available in availability zone us-west-2d + exclude_zone_ids = ["usw2-az4"] + state = "available" + + filter { + name = "opt-in-status" + values = ["opt-in-not-required"] + } +} resource "aws_vpc" "test" { cidr_block = "10.0.0.0/16" tags = { - Name = "tf-acc-test-ec2-route-transit-gateway-id" + Name = %[1]q } } @@ -891,24 +923,40 @@ resource "aws_subnet" "test" { vpc_id = aws_vpc.test.id tags = { - Name = "tf-acc-test-ec2-route-transit-gateway-id" + Name = %[1]q } } -resource "aws_ec2_transit_gateway" "test" {} +resource "aws_ec2_transit_gateway" "test" { + tags = { + Name = %[1]q + } +} resource "aws_ec2_transit_gateway_vpc_attachment" "test" { subnet_ids = [aws_subnet.test.id] transit_gateway_id = aws_ec2_transit_gateway.test.id vpc_id = aws_vpc.test.id + + tags = { + Name = %[1]q + } +} + +resource "aws_route_table" "test" { + vpc_id = aws_vpc.test.id + + tags = { + Name = %[1]q + } } resource "aws_route" "test" { - destination_cidr_block = "0.0.0.0/0" - route_table_id = aws_vpc.test.default_route_table_id + destination_cidr_block = %[2]q + route_table_id = aws_route_table.test.id transit_gateway_id = aws_ec2_transit_gateway_vpc_attachment.test.transit_gateway_id } -`) +`, rName, destinationCidr) } func testAccAWSRouteConfigConditionalIpv4Ipv6(rName string, ipv6Route bool) string { From 8c6dc6cdf74d35daaef9a31fc6b6601e94ac4dd8 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 26 Jun 2020 15:44:59 -0400 Subject: [PATCH 10/40] r/aws_route: Add 'TestAccAWSRoute_IPv4_To_Instance'. Acceptance test output: $ make testacc TEST=./aws/ TESTARGS='-run=TestAccAWSRoute_IPv4_To_Instance' ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws/ -v -count 1 -parallel 20 -run=TestAccAWSRoute_IPv4_To_Instance -timeout 120m === RUN TestAccAWSRoute_IPv4_To_Instance === PAUSE TestAccAWSRoute_IPv4_To_Instance === CONT TestAccAWSRoute_IPv4_To_Instance --- PASS: TestAccAWSRoute_IPv4_To_Instance (87.65s) PASS ok github.com/terraform-providers/terraform-provider-aws/aws 87.699s --- aws/resource_aws_route_test.go | 91 ++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/aws/resource_aws_route_test.go b/aws/resource_aws_route_test.go index 6a23372db486..9c4f5fd568b9 100644 --- a/aws/resource_aws_route_test.go +++ b/aws/resource_aws_route_test.go @@ -278,6 +278,37 @@ func TestAccAWSRoute_IPv4_To_InternetGateway(t *testing.T) { }) } +func TestAccAWSRoute_IPv4_To_Instance(t *testing.T) { + var route ec2.Route + resourceName := "aws_route.test" + instanceResourceName := "aws_instance.test" + rName := acctest.RandomWithPrefix("tf-acc-test") + destinationCidr := "10.3.0.0/16" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSRouteDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSRouteConfigIpv4Instance(rName, destinationCidr), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSRouteExists(resourceName, &route), + testAccCheckAWSRouteInstanceRoute(instanceResourceName, &route), + resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", destinationCidr), + resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateIdFunc: testAccAWSRouteImportStateIdFunc(resourceName), + ImportStateVerify: true, + }, + }, + }) +} + func TestAccAWSRoute_DoesNotCrashWithVpcEndpoint(t *testing.T) { var route ec2.Route var routeTable ec2.RouteTable @@ -1009,3 +1040,63 @@ resource "aws_route" "test" { } `, rName, ipv6Route) } + +func testAccAWSRouteConfigIpv4Instance(rName, destinationCidr string) string { + return composeConfig( + testAccLatestAmazonLinuxHvmEbsAmiConfig(), + testAccAvailableEc2InstanceTypeForRegion("t3.micro", "t2.micro"), + fmt.Sprintf(` +data "aws_availability_zones" "current" { + # Exclude usw2-az4 (us-west-2d) as it has limited instance types. + blacklisted_zone_ids = ["usw2-az4"] + state = "available" + + filter { + name = "opt-in-status" + values = ["opt-in-not-required"] + } +} + +resource "aws_vpc" "test" { + cidr_block = "10.1.0.0/16" + + tags = { + Name = %[1]q + } +} + +resource "aws_subnet" "test" { + cidr_block = "10.1.1.0/24" + vpc_id = aws_vpc.test.id + availability_zone = data.aws_availability_zones.current.names[0] + + tags = { + Name = %[1]q + } +} + +resource "aws_instance" "test" { + ami = data.aws_ami.amzn-ami-minimal-hvm-ebs.id + instance_type = data.aws_ec2_instance_type_offering.available.instance_type + subnet_id = aws_subnet.test.id + + tags = { + Name = %[1]q + } +} + +resource "aws_route_table" "test" { + vpc_id = aws_vpc.test.id + + tags = { + Name = %[1]q + } +} + +resource "aws_route" "test" { + route_table_id = aws_route_table.test.id + destination_cidr_block = %[2]q + instance_id = aws_instance.test.id +} +`, rName, destinationCidr)) +} From c02f9a8f2af0a113c6b20d2863c3121579e5dba5 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 26 Jun 2020 15:53:32 -0400 Subject: [PATCH 11/40] r/aws_route: Add 'TestAccAWSRoute_IPv4_To_NetworkInterface'. Acceptance test output: $ make testacc TEST=./aws/ TESTARGS='-run=TestAccAWSRoute_IPv4_To_NetworkInterface' ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws/ -v -count 1 -parallel 20 -run=TestAccAWSRoute_IPv4_To_NetworkInterface -timeout 120m === RUN TestAccAWSRoute_IPv4_To_NetworkInterface === PAUSE TestAccAWSRoute_IPv4_To_NetworkInterface === CONT TestAccAWSRoute_IPv4_To_NetworkInterface --- PASS: TestAccAWSRoute_IPv4_To_NetworkInterface (47.04s) PASS ok github.com/terraform-providers/terraform-provider-aws/aws 47.100s --- aws/resource_aws_route_test.go | 95 ++++++++++++++++++++++++++++++++-- 1 file changed, 92 insertions(+), 3 deletions(-) diff --git a/aws/resource_aws_route_test.go b/aws/resource_aws_route_test.go index 9c4f5fd568b9..16ae4816ba48 100644 --- a/aws/resource_aws_route_test.go +++ b/aws/resource_aws_route_test.go @@ -309,6 +309,39 @@ func TestAccAWSRoute_IPv4_To_Instance(t *testing.T) { }) } +func TestAccAWSRoute_IPv4_To_NetworkInterface(t *testing.T) { + var route ec2.Route + resourceName := "aws_route.test" + eniResourceName := "aws_network_interface.test" + rName := acctest.RandomWithPrefix("tf-acc-test") + destinationCidr := "10.3.0.0/16" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSRouteDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSRouteConfigIpv4NetworkInterface(rName, destinationCidr), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSRouteExists(resourceName, &route), + testAccCheckAWSRouteNetworkInterfaceRoute(eniResourceName, &route), + resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", destinationCidr), + resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateIdFunc: testAccAWSRouteImportStateIdFunc(resourceName), + ImportStateVerify: true, + }, + }, + }) +} + func TestAccAWSRoute_DoesNotCrashWithVpcEndpoint(t *testing.T) { var route ec2.Route var routeTable ec2.RouteTable @@ -1094,9 +1127,65 @@ resource "aws_route_table" "test" { } resource "aws_route" "test" { - route_table_id = aws_route_table.test.id - destination_cidr_block = %[2]q - instance_id = aws_instance.test.id + route_table_id = aws_route_table.test.id + destination_cidr_block = %[2]q + instance_id = aws_instance.test.id } `, rName, destinationCidr)) } + +func testAccAWSRouteConfigIpv4NetworkInterface(rName, destinationCidr string) string { + return fmt.Sprintf(` +data "aws_availability_zones" "current" { + # Exclude usw2-az4 (us-west-2d) as it has limited instance types. + blacklisted_zone_ids = ["usw2-az4"] + state = "available" + + filter { + name = "opt-in-status" + values = ["opt-in-not-required"] + } +} + +resource "aws_vpc" "test" { + cidr_block = "10.1.0.0/16" + + tags = { + Name = %[1]q + } +} + +resource "aws_subnet" "test" { + cidr_block = "10.1.1.0/24" + vpc_id = aws_vpc.test.id + availability_zone = data.aws_availability_zones.current.names[0] + + tags = { + Name = %[1]q + } +} + +resource "aws_network_interface" "test" { + subnet_id = aws_subnet.test.id + + tags = { + Name = %[1]q + } +} + + +resource "aws_route_table" "test" { + vpc_id = aws_vpc.test.id + + tags = { + Name = %[1]q + } +} + +resource "aws_route" "test" { + route_table_id = aws_route_table.test.id + destination_cidr_block = %[2]q + network_interface_id = aws_network_interface.test.id +} +`, rName, destinationCidr) +} From 5dc50de9c911e17af089730792a46d01dcf57e3f Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 26 Jun 2020 16:03:14 -0400 Subject: [PATCH 12/40] r/aws_route: Add 'TestAccAWSRoute_IPv4_To_VpcPeeringConnection'. Acceptance test output: $ make testacc TEST=./aws/ TESTARGS='-run=TestAccAWSRoute_IPv4_To_VpcPeeringConnection' ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws/ -v -count 1 -parallel 20 -run=TestAccAWSRoute_IPv4_To_VpcPeeringConnection -timeout 120m === RUN TestAccAWSRoute_IPv4_To_VpcPeeringConnection === PAUSE TestAccAWSRoute_IPv4_To_VpcPeeringConnection === CONT TestAccAWSRoute_IPv4_To_VpcPeeringConnection --- PASS: TestAccAWSRoute_IPv4_To_VpcPeeringConnection (42.88s) PASS ok github.com/terraform-providers/terraform-provider-aws/aws 42.928s --- aws/resource_aws_route_test.go | 75 ++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/aws/resource_aws_route_test.go b/aws/resource_aws_route_test.go index 16ae4816ba48..fbe669d80adb 100644 --- a/aws/resource_aws_route_test.go +++ b/aws/resource_aws_route_test.go @@ -342,6 +342,37 @@ func TestAccAWSRoute_IPv4_To_NetworkInterface(t *testing.T) { }) } +func TestAccAWSRoute_IPv4_To_VpcPeeringConnection(t *testing.T) { + var route ec2.Route + resourceName := "aws_route.test" + pcxResourceName := "aws_vpc_peering_connection.test" + rName := acctest.RandomWithPrefix("tf-acc-test") + destinationCidr := "10.3.0.0/16" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSRouteDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSRouteConfigIpv4VpcPeeringConnection(rName, destinationCidr), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSRouteExists(resourceName, &route), + testAccCheckAWSRouteVpcPeeringConnectionRoute(pcxResourceName, &route), + resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", destinationCidr), + resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateIdFunc: testAccAWSRouteImportStateIdFunc(resourceName), + ImportStateVerify: true, + }, + }, + }) +} + func TestAccAWSRoute_DoesNotCrashWithVpcEndpoint(t *testing.T) { var route ec2.Route var routeTable ec2.RouteTable @@ -1189,3 +1220,47 @@ resource "aws_route" "test" { } `, rName, destinationCidr) } + +func testAccAWSRouteConfigIpv4VpcPeeringConnection(rName, destinationCidr string) string { + return fmt.Sprintf(` +resource "aws_vpc" "source" { + cidr_block = "10.0.0.0/16" + + tags = { + Name = %[1]q + } +} + +resource "aws_vpc" "target" { + cidr_block = "10.1.0.0/16" + + tags = { + Name = %[1]q + } +} + +resource "aws_vpc_peering_connection" "test" { + vpc_id = aws_vpc.source.id + peer_vpc_id = aws_vpc.target.id + auto_accept = true + + tags = { + Name = %[1]q + } +} + +resource "aws_route_table" "test" { + vpc_id = aws_vpc.source.id + + tags = { + Name = %[1]q + } +} + +resource "aws_route" "test" { + route_table_id = aws_route_table.test.id + destination_cidr_block = %[2]q + vpc_peering_connection_id = aws_vpc_peering_connection.test.id +} +`, rName, destinationCidr) +} From 84cd68804bacfd817e97161884429ba3a0857785 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 26 Jun 2020 16:20:38 -0400 Subject: [PATCH 13/40] r/aws_route: Add 'TestAccAWSRoute_IPv4_To_NatGateway'. Acceptance test output: $ make testacc TEST=./aws/ TESTARGS='-run=TestAccAWSRoute_IPv4_To_NatGateway' ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws/ -v -count 1 -parallel 20 -run=TestAccAWSRoute_IPv4_To_NatGateway -timeout 120m === RUN TestAccAWSRoute_IPv4_To_NatGateway === PAUSE TestAccAWSRoute_IPv4_To_NatGateway === CONT TestAccAWSRoute_IPv4_To_NatGateway --- PASS: TestAccAWSRoute_IPv4_To_NatGateway (195.61s) PASS ok github.com/terraform-providers/terraform-provider-aws/aws 195.647s --- aws/resource_aws_route_test.go | 114 +++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) diff --git a/aws/resource_aws_route_test.go b/aws/resource_aws_route_test.go index fbe669d80adb..a81c94c1b946 100644 --- a/aws/resource_aws_route_test.go +++ b/aws/resource_aws_route_test.go @@ -373,6 +373,37 @@ func TestAccAWSRoute_IPv4_To_VpcPeeringConnection(t *testing.T) { }) } +func TestAccAWSRoute_IPv4_To_NatGateway(t *testing.T) { + var route ec2.Route + resourceName := "aws_route.test" + ngwResourceName := "aws_nat_gateway.test" + rName := acctest.RandomWithPrefix("tf-acc-test") + destinationCidr := "10.3.0.0/16" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSRouteDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSRouteConfigIpv4NatGateway(rName, destinationCidr), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSRouteExists(resourceName, &route), + testAccCheckAWSRouteNatGatewayRoute(ngwResourceName, &route), + resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", destinationCidr), + resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateIdFunc: testAccAWSRouteImportStateIdFunc(resourceName), + ImportStateVerify: true, + }, + }, + }) +} + func TestAccAWSRoute_DoesNotCrashWithVpcEndpoint(t *testing.T) { var route ec2.Route var routeTable ec2.RouteTable @@ -599,6 +630,25 @@ func testAccCheckAWSRouteInstanceRoute(n string, route *ec2.Route) resource.Test } } +func testAccCheckAWSRouteNatGatewayRoute(n string, route *ec2.Route) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s\n", n) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("No ID is set") + } + + if gwId := aws.StringValue(route.NatGatewayId); gwId != rs.Primary.ID { + return fmt.Errorf("NAT Gateway ID (Expected=%s, Actual=%s)\n", rs.Primary.ID, gwId) + } + + return nil + } +} + func testAccCheckAWSRouteNetworkInterfaceRoute(n string, route *ec2.Route) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] @@ -1264,3 +1314,67 @@ resource "aws_route" "test" { } `, rName, destinationCidr) } + +func testAccAWSRouteConfigIpv4NatGateway(rName, destinationCidr string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { + cidr_block = "10.1.0.0/16" + + tags = { + Name = %[1]q + } +} + +resource "aws_subnet" "test" { + cidr_block = "10.1.1.0/24" + vpc_id = aws_vpc.test.id + + map_public_ip_on_launch = true + + tags = { + Name = %[1]q + } +} + +resource "aws_internet_gateway" "test" { + vpc_id = "${aws_vpc.test.id}" + + tags = { + Name = %[1]q + } +} + +resource "aws_eip" "test" { + vpc = true + + tags = { + Name = %[1]q + } +} + +resource "aws_nat_gateway" "test" { + allocation_id = aws_eip.test.id + subnet_id = aws_subnet.test.id + + tags = { + Name = %[1]q + } + + depends_on = [aws_internet_gateway.test] +} + +resource "aws_route_table" "test" { + vpc_id = aws_vpc.test.id + + tags = { + Name = %[1]q + } +} + +resource "aws_route" "test" { + route_table_id = aws_route_table.test.id + destination_cidr_block = %[2]q + nat_gateway_id = aws_nat_gateway.test.id +} +`, rName, destinationCidr) +} From 81d4e6dace823424740e5f88a3a02fc03f028efc Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 26 Jun 2020 17:54:33 -0400 Subject: [PATCH 14/40] r/aws_route: Comment out failing target update test. Acceptance test output: $ make testacc TEST=./aws/ TESTARGS='-run=TestAccAWSRoute_' ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws/ -v -count 1 -parallel 1 -run=TestAccAWSRoute_ -timeout 120m === RUN TestAccAWSRoute_basic === PAUSE TestAccAWSRoute_basic === RUN TestAccAWSRoute_disappears === PAUSE TestAccAWSRoute_disappears === RUN TestAccAWSRoute_IPv6_To_EgressOnlyInternetGateway === PAUSE TestAccAWSRoute_IPv6_To_EgressOnlyInternetGateway === RUN TestAccAWSRoute_IPv6_To_InternetGateway === PAUSE TestAccAWSRoute_IPv6_To_InternetGateway === RUN TestAccAWSRoute_IPv6_To_Instance === PAUSE TestAccAWSRoute_IPv6_To_Instance === RUN TestAccAWSRoute_IPv6_To_NetworkInterface === PAUSE TestAccAWSRoute_IPv6_To_NetworkInterface === RUN TestAccAWSRoute_IPv6_To_VpcPeeringConnection === PAUSE TestAccAWSRoute_IPv6_To_VpcPeeringConnection === RUN TestAccAWSRoute_IPv4_To_InternetGateway === PAUSE TestAccAWSRoute_IPv4_To_InternetGateway === RUN TestAccAWSRoute_IPv4_To_Instance === PAUSE TestAccAWSRoute_IPv4_To_Instance === RUN TestAccAWSRoute_IPv4_To_NetworkInterface === PAUSE TestAccAWSRoute_IPv4_To_NetworkInterface === RUN TestAccAWSRoute_IPv4_To_VpcPeeringConnection === PAUSE TestAccAWSRoute_IPv4_To_VpcPeeringConnection === RUN TestAccAWSRoute_IPv4_To_NatGateway === PAUSE TestAccAWSRoute_IPv4_To_NatGateway === RUN TestAccAWSRoute_DoesNotCrashWithVpcEndpoint === PAUSE TestAccAWSRoute_DoesNotCrashWithVpcEndpoint === RUN TestAccAWSRoute_IPv4_To_TransitGateway === PAUSE TestAccAWSRoute_IPv4_To_TransitGateway === RUN TestAccAWSRoute_ConditionalCidrBlock === PAUSE TestAccAWSRoute_ConditionalCidrBlock === CONT TestAccAWSRoute_basic --- PASS: TestAccAWSRoute_basic (52.44s) === CONT TestAccAWSRoute_ConditionalCidrBlock --- PASS: TestAccAWSRoute_ConditionalCidrBlock (76.36s) === CONT TestAccAWSRoute_IPv4_To_TransitGateway --- PASS: TestAccAWSRoute_IPv4_To_TransitGateway (358.76s) === CONT TestAccAWSRoute_DoesNotCrashWithVpcEndpoint --- PASS: TestAccAWSRoute_DoesNotCrashWithVpcEndpoint (62.15s) === CONT TestAccAWSRoute_IPv4_To_NatGateway --- PASS: TestAccAWSRoute_IPv4_To_NatGateway (195.36s) === CONT TestAccAWSRoute_IPv4_To_VpcPeeringConnection --- PASS: TestAccAWSRoute_IPv4_To_VpcPeeringConnection (43.17s) === CONT TestAccAWSRoute_IPv4_To_NetworkInterface --- PASS: TestAccAWSRoute_IPv4_To_NetworkInterface (46.84s) === CONT TestAccAWSRoute_IPv4_To_Instance --- PASS: TestAccAWSRoute_IPv4_To_Instance (120.01s) === CONT TestAccAWSRoute_IPv4_To_InternetGateway --- PASS: TestAccAWSRoute_IPv4_To_InternetGateway (77.57s) === CONT TestAccAWSRoute_IPv6_To_VpcPeeringConnection --- PASS: TestAccAWSRoute_IPv6_To_VpcPeeringConnection (42.36s) === CONT TestAccAWSRoute_IPv6_To_NetworkInterface --- PASS: TestAccAWSRoute_IPv6_To_NetworkInterface (48.01s) === CONT TestAccAWSRoute_IPv6_To_Instance --- PASS: TestAccAWSRoute_IPv6_To_Instance (119.62s) === CONT TestAccAWSRoute_IPv6_To_InternetGateway --- PASS: TestAccAWSRoute_IPv6_To_InternetGateway (51.75s) === CONT TestAccAWSRoute_IPv6_To_EgressOnlyInternetGateway --- PASS: TestAccAWSRoute_IPv6_To_EgressOnlyInternetGateway (58.58s) === CONT TestAccAWSRoute_disappears --- PASS: TestAccAWSRoute_disappears (47.56s) PASS ok github.com/terraform-providers/terraform-provider-aws/aws 1400.609s --- aws/resource_aws_route_test.go | 275 +++++++++++++++++++++++++++++++-- 1 file changed, 258 insertions(+), 17 deletions(-) diff --git a/aws/resource_aws_route_test.go b/aws/resource_aws_route_test.go index a81c94c1b946..6362e4dfa907 100644 --- a/aws/resource_aws_route_test.go +++ b/aws/resource_aws_route_test.go @@ -404,6 +404,106 @@ func TestAccAWSRoute_IPv4_To_NatGateway(t *testing.T) { }) } +/* +func TestAccAWSRoute_IPv4_Update_Target(t *testing.T) { + var route ec2.Route + resourceName := "aws_route.test" + vgwResourceName := "aws_vpn_gateway.test" + instanceResourceName := "aws_instance.test" + igwResourceName := "aws_internet_gateway.test" + eniResourceName := "aws_network_interface.test" + pcxResourceName := "aws_vpc_peering_connection.test" + ngwResourceName := "aws_nat_gateway.test" + //tgwResourceName := "aws_ec2_transit_gateway.test" + rName := acctest.RandomWithPrefix("tf-acc-test") + destinationCidr := "10.3.0.0/16" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSRouteDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSRouteConfigIpv4FlexiTarget(rName, destinationCidr, "gateway_id", vgwResourceName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSRouteExists(resourceName, &route), + testAccCheckAWSRouteGatewayRoute(vgwResourceName, &route), + resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", destinationCidr), + resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), + resource.TestCheckResourceAttrPair(resourceName, "gateway_id", vgwResourceName, "id"), + ), + }, + { + Config: testAccAWSRouteConfigIpv4FlexiTarget(rName, destinationCidr, "instance_id", instanceResourceName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSRouteExists(resourceName, &route), + testAccCheckAWSRouteInstanceRoute(instanceResourceName, &route), + resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", destinationCidr), + resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), + resource.TestCheckResourceAttrPair(resourceName, "instance_id", instanceResourceName, "id"), + ), + }, + { + Config: testAccAWSRouteConfigIpv4FlexiTarget(rName, destinationCidr, "gateway_id", igwResourceName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSRouteExists(resourceName, &route), + testAccCheckAWSRouteGatewayRoute(igwResourceName, &route), + resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", destinationCidr), + resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), + resource.TestCheckResourceAttrPair(resourceName, "gateway_id", igwResourceName, "id"), + ), + }, + { + Config: testAccAWSRouteConfigIpv4FlexiTarget(rName, destinationCidr, "network_interface_id", eniResourceName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSRouteExists(resourceName, &route), + testAccCheckAWSRouteNetworkInterfaceRoute(eniResourceName, &route), + resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", destinationCidr), + resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), + resource.TestCheckResourceAttrPair(resourceName, "network_interface_id", eniResourceName, "id"), + ), + }, + { + Config: testAccAWSRouteConfigIpv4FlexiTarget(rName, destinationCidr, "vpc_peering_connection_id", pcxResourceName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSRouteExists(resourceName, &route), + testAccCheckAWSRouteVpcPeeringConnectionRoute(pcxResourceName, &route), + resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", destinationCidr), + resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), + resource.TestCheckResourceAttrPair(resourceName, "vpc_peering_connection_id", pcxResourceName, "id"), + ), + }, + { + Config: testAccAWSRouteConfigIpv4FlexiTarget(rName, destinationCidr, "nat_gateway_id", ngwResourceName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSRouteExists(resourceName, &route), + testAccCheckAWSRouteNatGatewayRoute(ngwResourceName, &route), + resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", destinationCidr), + resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), + resource.TestCheckResourceAttrPair(resourceName, "nat_gateway_id", ngwResourceName, "id"), + ), + }, + // { + // Config: testAccAWSRouteConfigIpv4FlexiTarget(rName, destinationCidr, "transit_gateway_id", tgwResourceName), + // Check: resource.ComposeTestCheckFunc( + // testAccCheckAWSRouteExists(resourceName, &route), + // testAccCheckAWSRouteTransitGatewayRoute(tgwResourceName, &route), + // resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", destinationCidr), + // resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), + // resource.TestCheckResourceAttrPair(resourceName, "transit_gateway_id", tgwResourceName, "id"), + // ), + // }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateIdFunc: testAccAWSRouteImportStateIdFunc(resourceName), + ImportStateVerify: true, + }, + }, + }) +} +*/ + func TestAccAWSRoute_DoesNotCrashWithVpcEndpoint(t *testing.T) { var route ec2.Route var routeTable ec2.RouteTable @@ -437,7 +537,7 @@ func TestAccAWSRoute_DoesNotCrashWithVpcEndpoint(t *testing.T) { func TestAccAWSRoute_IPv4_To_TransitGateway(t *testing.T) { var route ec2.Route resourceName := "aws_route.test" - transitGatewayResourceName := "aws_ec2_transit_gateway.test" + tgwResourceName := "aws_ec2_transit_gateway.test" rName := acctest.RandomWithPrefix("tf-acc-test") destinationCidr := "10.3.0.0/16" @@ -450,10 +550,10 @@ func TestAccAWSRoute_IPv4_To_TransitGateway(t *testing.T) { Config: testAccAWSRouteConfigIpv4TransitGateway(rName, destinationCidr), Check: resource.ComposeTestCheckFunc( testAccCheckAWSRouteExists(resourceName, &route), - testAccCheckAWSRouteTransitGatewayRoute(transitGatewayResourceName, &route), + testAccCheckAWSRouteTransitGatewayRoute(tgwResourceName, &route), resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", destinationCidr), resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), - resource.TestCheckResourceAttrPair(resourceName, "transit_gateway_id", transitGatewayResourceName, "id"), + resource.TestCheckResourceAttrPair(resourceName, "transit_gateway_id", tgwResourceName, "id"), ), }, { @@ -834,7 +934,6 @@ resource "aws_network_interface" "test" { } } - resource "aws_route_table" "test" { vpc_id = aws_vpc.test.id @@ -917,8 +1016,8 @@ resource "aws_route" "test" { func testAccAWSRouteConfigIpv6VpcPeeringConnection(rName, destinationCidr string) string { return fmt.Sprintf(` -resource "aws_vpc" "source" { - cidr_block = "10.0.0.0/16" +resource "aws_vpc" "test" { + cidr_block = "10.1.0.0/16" assign_generated_ipv6_cidr_block = true tags = { @@ -927,7 +1026,7 @@ resource "aws_vpc" "source" { } resource "aws_vpc" "target" { - cidr_block = "10.1.0.0/16" + cidr_block = "10.0.0.0/16" assign_generated_ipv6_cidr_block = true tags = { @@ -936,7 +1035,7 @@ resource "aws_vpc" "target" { } resource "aws_vpc_peering_connection" "test" { - vpc_id = aws_vpc.source.id + vpc_id = aws_vpc.test.id peer_vpc_id = aws_vpc.target.id auto_accept = true @@ -946,7 +1045,7 @@ resource "aws_vpc_peering_connection" "test" { } resource "aws_route_table" "test" { - vpc_id = aws_vpc.source.id + vpc_id = aws_vpc.test.id tags = { Name = %[1]q @@ -1055,7 +1154,7 @@ data "aws_availability_zones" "available" { } resource "aws_vpc" "test" { - cidr_block = "10.0.0.0/16" + cidr_block = "10.1.0.0/16" tags = { Name = %[1]q @@ -1064,7 +1163,7 @@ resource "aws_vpc" "test" { resource "aws_subnet" "test" { availability_zone = data.aws_availability_zones.available.names[0] - cidr_block = "10.0.0.0/24" + cidr_block = "10.1.1.0/24" vpc_id = aws_vpc.test.id tags = { @@ -1254,7 +1353,6 @@ resource "aws_network_interface" "test" { } } - resource "aws_route_table" "test" { vpc_id = aws_vpc.test.id @@ -1273,8 +1371,8 @@ resource "aws_route" "test" { func testAccAWSRouteConfigIpv4VpcPeeringConnection(rName, destinationCidr string) string { return fmt.Sprintf(` -resource "aws_vpc" "source" { - cidr_block = "10.0.0.0/16" +resource "aws_vpc" "test" { + cidr_block = "10.1.0.0/16" tags = { Name = %[1]q @@ -1282,7 +1380,7 @@ resource "aws_vpc" "source" { } resource "aws_vpc" "target" { - cidr_block = "10.1.0.0/16" + cidr_block = "10.0.0.0/16" tags = { Name = %[1]q @@ -1290,7 +1388,7 @@ resource "aws_vpc" "target" { } resource "aws_vpc_peering_connection" "test" { - vpc_id = aws_vpc.source.id + vpc_id = aws_vpc.test.id peer_vpc_id = aws_vpc.target.id auto_accept = true @@ -1300,7 +1398,7 @@ resource "aws_vpc_peering_connection" "test" { } resource "aws_route_table" "test" { - vpc_id = aws_vpc.source.id + vpc_id = aws_vpc.test.id tags = { Name = %[1]q @@ -1378,3 +1476,146 @@ resource "aws_route" "test" { } `, rName, destinationCidr) } + +/* +func testAccAWSRouteConfigIpv4FlexiTarget(rName, destinationCidr, targetAttribute, targetValue string) string { + return composeConfig( + testAccLatestAmazonLinuxHvmEbsAmiConfig(), + testAccAvailableEc2InstanceTypeForRegion("t3.micro", "t2.micro"), + fmt.Sprintf(` +data "aws_availability_zones" "current" { + # Exclude usw2-az4 (us-west-2d) as it has limited instance types. + # IncorrectState: Transit Gateway is not available in availability zone us-west-2d + blacklisted_zone_ids = ["usw2-az4"] + state = "available" + + filter { + name = "opt-in-status" + values = ["opt-in-not-required"] + } +} + +resource "aws_vpc" "test" { + cidr_block = "10.1.0.0/16" + + tags = { + Name = %[1]q + } +} + +resource "aws_vpn_gateway" "test" { + vpc_id = aws_vpc.test.id + + tags = { + Name = %[1]q + } +} + +resource "aws_internet_gateway" "test" { + vpc_id = aws_vpc.test.id + + tags = { + Name = %[1]q + } +} + +resource "aws_subnet" "test" { + cidr_block = "10.1.1.0/24" + vpc_id = aws_vpc.test.id + availability_zone = data.aws_availability_zones.current.names[0] + + map_public_ip_on_launch = true + + tags = { + Name = %[1]q + } +} + +resource "aws_instance" "test" { + ami = data.aws_ami.amzn-ami-minimal-hvm-ebs.id + instance_type = data.aws_ec2_instance_type_offering.available.instance_type + subnet_id = aws_subnet.test.id + + tags = { + Name = %[1]q + } +} + +// resource "aws_ec2_transit_gateway" "test" { +// tags = { +// Name = %[1]q +// } +// } + +// resource "aws_ec2_transit_gateway_vpc_attachment" "test" { +// subnet_ids = [aws_subnet.test.id] +// transit_gateway_id = aws_ec2_transit_gateway.test.id +// vpc_id = aws_vpc.test.id + +// tags = { +// Name = %[1]q +// } +// } + +resource "aws_network_interface" "test" { + subnet_id = aws_subnet.test.id + + tags = { + Name = %[1]q + } +} + +resource "aws_vpc" "target" { + cidr_block = "10.0.0.0/16" + + tags = { + Name = %[1]q + } +} + +resource "aws_vpc_peering_connection" "test" { + vpc_id = aws_vpc.test.id + peer_vpc_id = aws_vpc.target.id + auto_accept = true + + tags = { + Name = %[1]q + } +} + +resource "aws_eip" "test" { + vpc = true + + tags = { + Name = %[1]q + } +} + +resource "aws_nat_gateway" "test" { + allocation_id = aws_eip.test.id + subnet_id = aws_subnet.test.id + + tags = { + Name = %[1]q + } + + depends_on = [aws_internet_gateway.test] +} + +resource "aws_route_table" "test" { + vpc_id = aws_vpc.test.id + + tags = { + Name = %[1]q + } +} + +resource "aws_route" "test" { + route_table_id = aws_route_table.test.id + destination_cidr_block = %[2]q + + %[3]s = %[4]s.id +} +`, rName, destinationCidr, targetAttribute, targetValue)) +} +*/ From f8a9f6ee21cf017886fd103f6a7587d74f6f6abc Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Sat, 27 Jun 2020 17:17:52 -0400 Subject: [PATCH 15/40] r/aws_route: Add 'TestAccAWSRoute_IPv4_To_VpnGateway'. Acceptance test output: $ make testacc TEST=./aws/ TESTARGS='-run=TestAccAWSRoute_IPv4_To_VpnGateway' ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws/ -v -count 1 -parallel 20 -run=TestAccAWSRoute_IPv4_To_VpnGateway -timeout 120m === RUN TestAccAWSRoute_IPv4_To_VpnGateway === PAUSE TestAccAWSRoute_IPv4_To_VpnGateway === CONT TestAccAWSRoute_IPv4_To_VpnGateway --- PASS: TestAccAWSRoute_IPv4_To_VpnGateway (63.35s) PASS ok github.com/terraform-providers/terraform-provider-aws/aws 63.423s --- aws/resource_aws_route_test.go | 247 ++------------------------------- 1 file changed, 14 insertions(+), 233 deletions(-) diff --git a/aws/resource_aws_route_test.go b/aws/resource_aws_route_test.go index 6362e4dfa907..0159c704ed42 100644 --- a/aws/resource_aws_route_test.go +++ b/aws/resource_aws_route_test.go @@ -231,15 +231,12 @@ func TestAccAWSRoute_IPv6_To_VpcPeeringConnection(t *testing.T) { }) } -func TestAccAWSRoute_IPv4_To_InternetGateway(t *testing.T) { +func TestAccAWSRoute_IPv4_To_VpnGateway(t *testing.T) { var route ec2.Route - var routeTable ec2.RouteTable resourceName := "aws_route.test" - igwResourceName := "aws_internet_gateway.test" - rtResourceName := "aws_route_table.test" + vgwResourceName := "aws_vpn_gateway.test" rName := acctest.RandomWithPrefix("tf-acc-test") destinationCidr := "10.3.0.0/16" - changedDestinationCidr := "10.2.0.0/16" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -247,25 +244,18 @@ func TestAccAWSRoute_IPv4_To_InternetGateway(t *testing.T) { CheckDestroy: testAccCheckAWSRouteDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSRouteConfigIpv4InternetGateway(rName, destinationCidr), + Config: testAccAWSRouteConfigIpv4VpnGateway(rName, destinationCidr), Check: resource.ComposeTestCheckFunc( testAccCheckAWSRouteExists(resourceName, &route), - testAccCheckAWSRouteGatewayRoute(igwResourceName, &route), - testAccCheckRouteTableExists(rtResourceName, &routeTable), - testAccCheckAWSRouteNumberOfRoutes(&routeTable, 2), resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", destinationCidr), resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), - ), - }, - { - Config: testAccAWSRouteConfigIpv4InternetGateway(rName, changedDestinationCidr), - Check: resource.ComposeTestCheckFunc( - testAccCheckAWSRouteExists(resourceName, &route), - testAccCheckAWSRouteGatewayRoute(igwResourceName, &route), - testAccCheckRouteTableExists(rtResourceName, &routeTable), - testAccCheckAWSRouteNumberOfRoutes(&routeTable, 2), - resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", changedDestinationCidr), - resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), + resource.TestCheckResourceAttr(resourceName, "egress_only_gateway_id", ""), + resource.TestCheckResourceAttrPair(resourceName, "gateway_id", vgwResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "instance_id", ""), + resource.TestCheckResourceAttr(resourceName, "nat_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "network_interface_id", ""), + resource.TestCheckResourceAttr(resourceName, "transit_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "vpc_peering_connection_id", ""), ), }, { @@ -404,106 +394,6 @@ func TestAccAWSRoute_IPv4_To_NatGateway(t *testing.T) { }) } -/* -func TestAccAWSRoute_IPv4_Update_Target(t *testing.T) { - var route ec2.Route - resourceName := "aws_route.test" - vgwResourceName := "aws_vpn_gateway.test" - instanceResourceName := "aws_instance.test" - igwResourceName := "aws_internet_gateway.test" - eniResourceName := "aws_network_interface.test" - pcxResourceName := "aws_vpc_peering_connection.test" - ngwResourceName := "aws_nat_gateway.test" - //tgwResourceName := "aws_ec2_transit_gateway.test" - rName := acctest.RandomWithPrefix("tf-acc-test") - destinationCidr := "10.3.0.0/16" - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckAWSRouteDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAWSRouteConfigIpv4FlexiTarget(rName, destinationCidr, "gateway_id", vgwResourceName), - Check: resource.ComposeTestCheckFunc( - testAccCheckAWSRouteExists(resourceName, &route), - testAccCheckAWSRouteGatewayRoute(vgwResourceName, &route), - resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", destinationCidr), - resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), - resource.TestCheckResourceAttrPair(resourceName, "gateway_id", vgwResourceName, "id"), - ), - }, - { - Config: testAccAWSRouteConfigIpv4FlexiTarget(rName, destinationCidr, "instance_id", instanceResourceName), - Check: resource.ComposeTestCheckFunc( - testAccCheckAWSRouteExists(resourceName, &route), - testAccCheckAWSRouteInstanceRoute(instanceResourceName, &route), - resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", destinationCidr), - resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), - resource.TestCheckResourceAttrPair(resourceName, "instance_id", instanceResourceName, "id"), - ), - }, - { - Config: testAccAWSRouteConfigIpv4FlexiTarget(rName, destinationCidr, "gateway_id", igwResourceName), - Check: resource.ComposeTestCheckFunc( - testAccCheckAWSRouteExists(resourceName, &route), - testAccCheckAWSRouteGatewayRoute(igwResourceName, &route), - resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", destinationCidr), - resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), - resource.TestCheckResourceAttrPair(resourceName, "gateway_id", igwResourceName, "id"), - ), - }, - { - Config: testAccAWSRouteConfigIpv4FlexiTarget(rName, destinationCidr, "network_interface_id", eniResourceName), - Check: resource.ComposeTestCheckFunc( - testAccCheckAWSRouteExists(resourceName, &route), - testAccCheckAWSRouteNetworkInterfaceRoute(eniResourceName, &route), - resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", destinationCidr), - resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), - resource.TestCheckResourceAttrPair(resourceName, "network_interface_id", eniResourceName, "id"), - ), - }, - { - Config: testAccAWSRouteConfigIpv4FlexiTarget(rName, destinationCidr, "vpc_peering_connection_id", pcxResourceName), - Check: resource.ComposeTestCheckFunc( - testAccCheckAWSRouteExists(resourceName, &route), - testAccCheckAWSRouteVpcPeeringConnectionRoute(pcxResourceName, &route), - resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", destinationCidr), - resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), - resource.TestCheckResourceAttrPair(resourceName, "vpc_peering_connection_id", pcxResourceName, "id"), - ), - }, - { - Config: testAccAWSRouteConfigIpv4FlexiTarget(rName, destinationCidr, "nat_gateway_id", ngwResourceName), - Check: resource.ComposeTestCheckFunc( - testAccCheckAWSRouteExists(resourceName, &route), - testAccCheckAWSRouteNatGatewayRoute(ngwResourceName, &route), - resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", destinationCidr), - resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), - resource.TestCheckResourceAttrPair(resourceName, "nat_gateway_id", ngwResourceName, "id"), - ), - }, - // { - // Config: testAccAWSRouteConfigIpv4FlexiTarget(rName, destinationCidr, "transit_gateway_id", tgwResourceName), - // Check: resource.ComposeTestCheckFunc( - // testAccCheckAWSRouteExists(resourceName, &route), - // testAccCheckAWSRouteTransitGatewayRoute(tgwResourceName, &route), - // resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", destinationCidr), - // resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), - // resource.TestCheckResourceAttrPair(resourceName, "transit_gateway_id", tgwResourceName, "id"), - // ), - // }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateIdFunc: testAccAWSRouteImportStateIdFunc(resourceName), - ImportStateVerify: true, - }, - }, - }) -} -*/ - func TestAccAWSRoute_DoesNotCrashWithVpcEndpoint(t *testing.T) { var route ec2.Route var routeTable ec2.RouteTable @@ -1477,24 +1367,8 @@ resource "aws_route" "test" { `, rName, destinationCidr) } -/* -func testAccAWSRouteConfigIpv4FlexiTarget(rName, destinationCidr, targetAttribute, targetValue string) string { - return composeConfig( - testAccLatestAmazonLinuxHvmEbsAmiConfig(), - testAccAvailableEc2InstanceTypeForRegion("t3.micro", "t2.micro"), - fmt.Sprintf(` -data "aws_availability_zones" "current" { - # Exclude usw2-az4 (us-west-2d) as it has limited instance types. - # IncorrectState: Transit Gateway is not available in availability zone us-west-2d - blacklisted_zone_ids = ["usw2-az4"] - state = "available" - - filter { - name = "opt-in-status" - values = ["opt-in-not-required"] - } -} - +func testAccAWSRouteConfigIpv4VpnGateway(rName, destinationCidr string) string { + return fmt.Sprintf(` resource "aws_vpc" "test" { cidr_block = "10.1.0.0/16" @@ -1511,97 +1385,6 @@ resource "aws_vpn_gateway" "test" { } } -resource "aws_internet_gateway" "test" { - vpc_id = aws_vpc.test.id - - tags = { - Name = %[1]q - } -} - -resource "aws_subnet" "test" { - cidr_block = "10.1.1.0/24" - vpc_id = aws_vpc.test.id - availability_zone = data.aws_availability_zones.current.names[0] - - map_public_ip_on_launch = true - - tags = { - Name = %[1]q - } -} - -resource "aws_instance" "test" { - ami = data.aws_ami.amzn-ami-minimal-hvm-ebs.id - instance_type = data.aws_ec2_instance_type_offering.available.instance_type - subnet_id = aws_subnet.test.id - - tags = { - Name = %[1]q - } -} - -// resource "aws_ec2_transit_gateway" "test" { -// tags = { -// Name = %[1]q -// } -// } - -// resource "aws_ec2_transit_gateway_vpc_attachment" "test" { -// subnet_ids = [aws_subnet.test.id] -// transit_gateway_id = aws_ec2_transit_gateway.test.id -// vpc_id = aws_vpc.test.id - -// tags = { -// Name = %[1]q -// } -// } - -resource "aws_network_interface" "test" { - subnet_id = aws_subnet.test.id - - tags = { - Name = %[1]q - } -} - -resource "aws_vpc" "target" { - cidr_block = "10.0.0.0/16" - - tags = { - Name = %[1]q - } -} - -resource "aws_vpc_peering_connection" "test" { - vpc_id = aws_vpc.test.id - peer_vpc_id = aws_vpc.target.id - auto_accept = true - - tags = { - Name = %[1]q - } -} - -resource "aws_eip" "test" { - vpc = true - - tags = { - Name = %[1]q - } -} - -resource "aws_nat_gateway" "test" { - allocation_id = aws_eip.test.id - subnet_id = aws_subnet.test.id - - tags = { - Name = %[1]q - } - - depends_on = [aws_internet_gateway.test] -} - resource "aws_route_table" "test" { vpc_id = aws_vpc.test.id @@ -1613,9 +1396,7 @@ resource "aws_route_table" "test" { resource "aws_route" "test" { route_table_id = aws_route_table.test.id destination_cidr_block = %[2]q - - %[3]s = %[4]s.id + gateway_id = aws_vpn_gateway.test.id } -`, rName, destinationCidr, targetAttribute, targetValue)) +`, rName, destinationCidr) } -*/ From ffa69260587a14d02f669ac5e0558af03d39b14d Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Sat, 27 Jun 2020 17:23:09 -0400 Subject: [PATCH 16/40] r/aws_route: Add 'TestAccAWSRoute_IPv6_To_VpnGateway'. Acceptance test output: $ make testacc TEST=./aws/ TESTARGS='-run=TestAccAWSRoute_IPv6_To_VpnGateway' ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws/ -v -count 1 -parallel 20 -run=TestAccAWSRoute_IPv6_To_VpnGateway -timeout 120m === RUN TestAccAWSRoute_IPv6_To_VpnGateway === PAUSE TestAccAWSRoute_IPv6_To_VpnGateway === CONT TestAccAWSRoute_IPv6_To_VpnGateway --- PASS: TestAccAWSRoute_IPv6_To_VpnGateway (56.25s) PASS ok github.com/terraform-providers/terraform-provider-aws/aws 56.281s --- aws/resource_aws_route_test.go | 72 ++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/aws/resource_aws_route_test.go b/aws/resource_aws_route_test.go index 0159c704ed42..fc5f776f7d3a 100644 --- a/aws/resource_aws_route_test.go +++ b/aws/resource_aws_route_test.go @@ -231,6 +231,43 @@ func TestAccAWSRoute_IPv6_To_VpcPeeringConnection(t *testing.T) { }) } +func TestAccAWSRoute_IPv6_To_VpnGateway(t *testing.T) { + var route ec2.Route + resourceName := "aws_route.test" + vgwResourceName := "aws_vpn_gateway.test" + rName := acctest.RandomWithPrefix("tf-acc-test") + destinationCidr := "::/0" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSRouteDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSRouteConfigIpv6VpnGateway(rName, destinationCidr), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSRouteExists(resourceName, &route), + resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", ""), + resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", destinationCidr), + resource.TestCheckResourceAttr(resourceName, "egress_only_gateway_id", ""), + resource.TestCheckResourceAttrPair(resourceName, "gateway_id", vgwResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "instance_id", ""), + resource.TestCheckResourceAttr(resourceName, "nat_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "network_interface_id", ""), + resource.TestCheckResourceAttr(resourceName, "transit_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "vpc_peering_connection_id", ""), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateIdFunc: testAccAWSRouteImportStateIdFunc(resourceName), + ImportStateVerify: true, + }, + }, + }) +} + func TestAccAWSRoute_IPv4_To_VpnGateway(t *testing.T) { var route ec2.Route resourceName := "aws_route.test" @@ -1400,3 +1437,38 @@ resource "aws_route" "test" { } `, rName, destinationCidr) } + +func testAccAWSRouteConfigIpv6VpnGateway(rName, destinationCidr string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { + cidr_block = "10.1.0.0/16" + assign_generated_ipv6_cidr_block = true + + tags = { + Name = %[1]q + } +} + +resource "aws_vpn_gateway" "test" { + vpc_id = aws_vpc.test.id + + tags = { + Name = %[1]q + } +} + +resource "aws_route_table" "test" { + vpc_id = aws_vpc.test.id + + tags = { + Name = %[1]q + } +} + +resource "aws_route" "test" { + route_table_id = aws_route_table.test.id + destination_ipv6_cidr_block = %[2]q + gateway_id = aws_vpn_gateway.test.id +} +`, rName, destinationCidr) +} From 23c67d9a9785a8a13854b98ef36790e718bd6cfd Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Sat, 27 Jun 2020 17:52:11 -0400 Subject: [PATCH 17/40] r/aws_route: Test computed attributes. --- aws/resource_aws_route_test.go | 274 ++++++++++++++++----------------- 1 file changed, 129 insertions(+), 145 deletions(-) diff --git a/aws/resource_aws_route_test.go b/aws/resource_aws_route_test.go index fc5f776f7d3a..a1be69887899 100644 --- a/aws/resource_aws_route_test.go +++ b/aws/resource_aws_route_test.go @@ -4,13 +4,13 @@ import ( "fmt" "testing" - "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" "github.com/hashicorp/terraform-plugin-sdk/helper/acctest" "github.com/hashicorp/terraform-plugin-sdk/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/terraform" ) +// IPv4 to Internet Gateway. func TestAccAWSRoute_basic(t *testing.T) { var route ec2.Route var routeTable ec2.RouteTable @@ -29,11 +29,21 @@ func TestAccAWSRoute_basic(t *testing.T) { Config: testAccAWSRouteConfigIpv4InternetGateway(rName, destinationCidr), Check: resource.ComposeTestCheckFunc( testAccCheckAWSRouteExists(resourceName, &route), - testAccCheckAWSRouteGatewayRoute(igwResourceName, &route), testAccCheckRouteTableExists(rtResourceName, &routeTable), testAccCheckAWSRouteNumberOfRoutes(&routeTable, 2), resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", destinationCidr), resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), + resource.TestCheckResourceAttr(resourceName, "destination_prefix_list_id", ""), + resource.TestCheckResourceAttr(resourceName, "egress_only_gateway_id", ""), + resource.TestCheckResourceAttrPair(resourceName, "gateway_id", igwResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "instance_id", ""), + resource.TestCheckResourceAttr(resourceName, "instance_owner_id", ""), + resource.TestCheckResourceAttr(resourceName, "nat_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "network_interface_id", ""), + resource.TestCheckResourceAttr(resourceName, "origin", ec2.RouteOriginCreateRoute), + resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateActive), + resource.TestCheckResourceAttr(resourceName, "transit_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "vpc_peering_connection_id", ""), ), }, { @@ -85,9 +95,19 @@ func TestAccAWSRoute_IPv6_To_EgressOnlyInternetGateway(t *testing.T) { Config: testAccAWSRouteConfigIpv6EgressOnlyInternetGateway(rName, destinationCidr), Check: resource.ComposeTestCheckFunc( testAccCheckAWSRouteExists(resourceName, &route), - testAccCheckAWSRouteEgressOnlyInternetGatewayRoute(eoigwResourceName, &route), resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", ""), resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", destinationCidr), + resource.TestCheckResourceAttr(resourceName, "destination_prefix_list_id", ""), + resource.TestCheckResourceAttrPair(resourceName, "egress_only_gateway_id", eoigwResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "instance_id", ""), + resource.TestCheckResourceAttr(resourceName, "instance_owner_id", ""), + resource.TestCheckResourceAttr(resourceName, "nat_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "network_interface_id", ""), + resource.TestCheckResourceAttr(resourceName, "origin", ec2.RouteOriginCreateRoute), + resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateActive), + resource.TestCheckResourceAttr(resourceName, "transit_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "vpc_peering_connection_id", ""), ), }, { @@ -121,9 +141,19 @@ func TestAccAWSRoute_IPv6_To_InternetGateway(t *testing.T) { Config: testAccAWSRouteConfigIpv6InternetGateway(rName, destinationCidr), Check: resource.ComposeTestCheckFunc( testAccCheckAWSRouteExists(resourceName, &route), - testAccCheckAWSRouteGatewayRoute(igwResourceName, &route), resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", ""), resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", destinationCidr), + resource.TestCheckResourceAttr(resourceName, "destination_prefix_list_id", ""), + resource.TestCheckResourceAttr(resourceName, "egress_only_gateway_id", ""), + resource.TestCheckResourceAttrPair(resourceName, "gateway_id", igwResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "instance_id", ""), + resource.TestCheckResourceAttr(resourceName, "instance_owner_id", ""), + resource.TestCheckResourceAttr(resourceName, "nat_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "network_interface_id", ""), + resource.TestCheckResourceAttr(resourceName, "origin", ec2.RouteOriginCreateRoute), + resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateActive), + resource.TestCheckResourceAttr(resourceName, "transit_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "vpc_peering_connection_id", ""), ), }, { @@ -152,9 +182,19 @@ func TestAccAWSRoute_IPv6_To_Instance(t *testing.T) { Config: testAccAWSRouteConfigIpv6Instance(rName, destinationCidr), Check: resource.ComposeTestCheckFunc( testAccCheckAWSRouteExists(resourceName, &route), - testAccCheckAWSRouteInstanceRoute(instanceResourceName, &route), resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", ""), resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", destinationCidr), + resource.TestCheckResourceAttr(resourceName, "destination_prefix_list_id", ""), + resource.TestCheckResourceAttr(resourceName, "egress_only_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "gateway_id", ""), + resource.TestCheckResourceAttrPair(resourceName, "instance_id", instanceResourceName, "id"), + testAccCheckResourceAttrAccountID(resourceName, "instance_owner_id"), + resource.TestCheckResourceAttr(resourceName, "nat_gateway_id", ""), + resource.TestCheckResourceAttrPair(resourceName, "network_interface_id", instanceResourceName, "primary_network_interface_id"), + resource.TestCheckResourceAttr(resourceName, "origin", ec2.RouteOriginCreateRoute), + resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateActive), + resource.TestCheckResourceAttr(resourceName, "transit_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "vpc_peering_connection_id", ""), ), }, { @@ -185,9 +225,19 @@ func TestAccAWSRoute_IPv6_To_NetworkInterface(t *testing.T) { Config: testAccAWSRouteConfigIpv6NetworkInterface(rName, destinationCidr), Check: resource.ComposeTestCheckFunc( testAccCheckAWSRouteExists(resourceName, &route), - testAccCheckAWSRouteNetworkInterfaceRoute(eniResourceName, &route), resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", ""), resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", destinationCidr), + resource.TestCheckResourceAttr(resourceName, "destination_prefix_list_id", ""), + resource.TestCheckResourceAttr(resourceName, "egress_only_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "instance_id", ""), + resource.TestCheckResourceAttr(resourceName, "instance_owner_id", ""), + resource.TestCheckResourceAttr(resourceName, "nat_gateway_id", ""), + resource.TestCheckResourceAttrPair(resourceName, "network_interface_id", eniResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "origin", ec2.RouteOriginCreateRoute), + resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateActive), + resource.TestCheckResourceAttr(resourceName, "transit_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "vpc_peering_connection_id", ""), ), }, { @@ -216,9 +266,19 @@ func TestAccAWSRoute_IPv6_To_VpcPeeringConnection(t *testing.T) { Config: testAccAWSRouteConfigIpv6VpcPeeringConnection(rName, destinationCidr), Check: resource.ComposeTestCheckFunc( testAccCheckAWSRouteExists(resourceName, &route), - testAccCheckAWSRouteVpcPeeringConnectionRoute(pcxResourceName, &route), resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", ""), resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", destinationCidr), + resource.TestCheckResourceAttr(resourceName, "destination_prefix_list_id", ""), + resource.TestCheckResourceAttr(resourceName, "egress_only_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "instance_id", ""), + resource.TestCheckResourceAttr(resourceName, "instance_owner_id", ""), + resource.TestCheckResourceAttr(resourceName, "nat_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "network_interface_id", ""), + resource.TestCheckResourceAttr(resourceName, "origin", ec2.RouteOriginCreateRoute), + resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateActive), + resource.TestCheckResourceAttr(resourceName, "transit_gateway_id", ""), + resource.TestCheckResourceAttrPair(resourceName, "vpc_peering_connection_id", pcxResourceName, "id"), ), }, { @@ -249,11 +309,15 @@ func TestAccAWSRoute_IPv6_To_VpnGateway(t *testing.T) { testAccCheckAWSRouteExists(resourceName, &route), resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", ""), resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", destinationCidr), + resource.TestCheckResourceAttr(resourceName, "destination_prefix_list_id", ""), resource.TestCheckResourceAttr(resourceName, "egress_only_gateway_id", ""), resource.TestCheckResourceAttrPair(resourceName, "gateway_id", vgwResourceName, "id"), resource.TestCheckResourceAttr(resourceName, "instance_id", ""), + resource.TestCheckResourceAttr(resourceName, "instance_owner_id", ""), resource.TestCheckResourceAttr(resourceName, "nat_gateway_id", ""), resource.TestCheckResourceAttr(resourceName, "network_interface_id", ""), + resource.TestCheckResourceAttr(resourceName, "origin", ec2.RouteOriginCreateRoute), + resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateActive), resource.TestCheckResourceAttr(resourceName, "transit_gateway_id", ""), resource.TestCheckResourceAttr(resourceName, "vpc_peering_connection_id", ""), ), @@ -286,11 +350,15 @@ func TestAccAWSRoute_IPv4_To_VpnGateway(t *testing.T) { testAccCheckAWSRouteExists(resourceName, &route), resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", destinationCidr), resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), + resource.TestCheckResourceAttr(resourceName, "destination_prefix_list_id", ""), resource.TestCheckResourceAttr(resourceName, "egress_only_gateway_id", ""), resource.TestCheckResourceAttrPair(resourceName, "gateway_id", vgwResourceName, "id"), resource.TestCheckResourceAttr(resourceName, "instance_id", ""), + resource.TestCheckResourceAttr(resourceName, "instance_owner_id", ""), resource.TestCheckResourceAttr(resourceName, "nat_gateway_id", ""), resource.TestCheckResourceAttr(resourceName, "network_interface_id", ""), + resource.TestCheckResourceAttr(resourceName, "origin", ec2.RouteOriginCreateRoute), + resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateActive), resource.TestCheckResourceAttr(resourceName, "transit_gateway_id", ""), resource.TestCheckResourceAttr(resourceName, "vpc_peering_connection_id", ""), ), @@ -321,9 +389,19 @@ func TestAccAWSRoute_IPv4_To_Instance(t *testing.T) { Config: testAccAWSRouteConfigIpv4Instance(rName, destinationCidr), Check: resource.ComposeTestCheckFunc( testAccCheckAWSRouteExists(resourceName, &route), - testAccCheckAWSRouteInstanceRoute(instanceResourceName, &route), resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", destinationCidr), resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), + resource.TestCheckResourceAttr(resourceName, "destination_prefix_list_id", ""), + resource.TestCheckResourceAttr(resourceName, "egress_only_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "gateway_id", ""), + resource.TestCheckResourceAttrPair(resourceName, "instance_id", instanceResourceName, "id"), + testAccCheckResourceAttrAccountID(resourceName, "instance_owner_id"), + resource.TestCheckResourceAttr(resourceName, "nat_gateway_id", ""), + resource.TestCheckResourceAttrPair(resourceName, "network_interface_id", instanceResourceName, "primary_network_interface_id"), + resource.TestCheckResourceAttr(resourceName, "origin", ec2.RouteOriginCreateRoute), + resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateActive), + resource.TestCheckResourceAttr(resourceName, "transit_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "vpc_peering_connection_id", ""), ), }, { @@ -354,9 +432,19 @@ func TestAccAWSRoute_IPv4_To_NetworkInterface(t *testing.T) { Config: testAccAWSRouteConfigIpv4NetworkInterface(rName, destinationCidr), Check: resource.ComposeTestCheckFunc( testAccCheckAWSRouteExists(resourceName, &route), - testAccCheckAWSRouteNetworkInterfaceRoute(eniResourceName, &route), resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", destinationCidr), resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), + resource.TestCheckResourceAttr(resourceName, "destination_prefix_list_id", ""), + resource.TestCheckResourceAttr(resourceName, "egress_only_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "instance_id", ""), + resource.TestCheckResourceAttr(resourceName, "instance_owner_id", ""), + resource.TestCheckResourceAttr(resourceName, "nat_gateway_id", ""), + resource.TestCheckResourceAttrPair(resourceName, "network_interface_id", eniResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "origin", ec2.RouteOriginCreateRoute), + resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateActive), + resource.TestCheckResourceAttr(resourceName, "transit_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "vpc_peering_connection_id", ""), ), }, { @@ -385,9 +473,19 @@ func TestAccAWSRoute_IPv4_To_VpcPeeringConnection(t *testing.T) { Config: testAccAWSRouteConfigIpv4VpcPeeringConnection(rName, destinationCidr), Check: resource.ComposeTestCheckFunc( testAccCheckAWSRouteExists(resourceName, &route), - testAccCheckAWSRouteVpcPeeringConnectionRoute(pcxResourceName, &route), resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", destinationCidr), resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), + resource.TestCheckResourceAttr(resourceName, "destination_prefix_list_id", ""), + resource.TestCheckResourceAttr(resourceName, "egress_only_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "instance_id", ""), + resource.TestCheckResourceAttr(resourceName, "instance_owner_id", ""), + resource.TestCheckResourceAttr(resourceName, "nat_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "network_interface_id", ""), + resource.TestCheckResourceAttr(resourceName, "origin", ec2.RouteOriginCreateRoute), + resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateActive), + resource.TestCheckResourceAttr(resourceName, "transit_gateway_id", ""), + resource.TestCheckResourceAttrPair(resourceName, "vpc_peering_connection_id", pcxResourceName, "id"), ), }, { @@ -416,9 +514,19 @@ func TestAccAWSRoute_IPv4_To_NatGateway(t *testing.T) { Config: testAccAWSRouteConfigIpv4NatGateway(rName, destinationCidr), Check: resource.ComposeTestCheckFunc( testAccCheckAWSRouteExists(resourceName, &route), - testAccCheckAWSRouteNatGatewayRoute(ngwResourceName, &route), resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", destinationCidr), resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), + resource.TestCheckResourceAttr(resourceName, "destination_prefix_list_id", ""), + resource.TestCheckResourceAttr(resourceName, "egress_only_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "instance_id", ""), + resource.TestCheckResourceAttr(resourceName, "instance_owner_id", ""), + resource.TestCheckResourceAttrPair(resourceName, "nat_gateway_id", ngwResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "network_interface_id", ""), + resource.TestCheckResourceAttr(resourceName, "origin", ec2.RouteOriginCreateRoute), + resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateActive), + resource.TestCheckResourceAttr(resourceName, "transit_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "vpc_peering_connection_id", ""), ), }, { @@ -477,10 +585,19 @@ func TestAccAWSRoute_IPv4_To_TransitGateway(t *testing.T) { Config: testAccAWSRouteConfigIpv4TransitGateway(rName, destinationCidr), Check: resource.ComposeTestCheckFunc( testAccCheckAWSRouteExists(resourceName, &route), - testAccCheckAWSRouteTransitGatewayRoute(tgwResourceName, &route), resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", destinationCidr), resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), + resource.TestCheckResourceAttr(resourceName, "destination_prefix_list_id", ""), + resource.TestCheckResourceAttr(resourceName, "egress_only_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "instance_id", ""), + resource.TestCheckResourceAttr(resourceName, "instance_owner_id", ""), + resource.TestCheckResourceAttr(resourceName, "nat_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "network_interface_id", ""), + resource.TestCheckResourceAttr(resourceName, "origin", ec2.RouteOriginCreateRoute), + resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateActive), resource.TestCheckResourceAttrPair(resourceName, "transit_gateway_id", tgwResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "vpc_peering_connection_id", ""), ), }, { @@ -600,139 +717,6 @@ func testAccAWSRouteImportStateIdFunc(resourceName string) resource.ImportStateI } } -func testAccCheckAWSRouteEgressOnlyInternetGatewayRoute(n string, route *ec2.Route) resource.TestCheckFunc { - return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[n] - if !ok { - return fmt.Errorf("Not found: %s\n", n) - } - - if rs.Primary.ID == "" { - return fmt.Errorf("No ID is set") - } - - if gwId := aws.StringValue(route.EgressOnlyInternetGatewayId); gwId != rs.Primary.ID { - return fmt.Errorf("Egress Only Internet Gateway ID (Expected=%s, Actual=%s)\n", rs.Primary.ID, gwId) - } - - return nil - } -} - -func testAccCheckAWSRouteGatewayRoute(n string, route *ec2.Route) resource.TestCheckFunc { - return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[n] - if !ok { - return fmt.Errorf("Not found: %s\n", n) - } - - if rs.Primary.ID == "" { - return fmt.Errorf("No ID is set") - } - - if gwId := aws.StringValue(route.GatewayId); gwId != rs.Primary.ID { - return fmt.Errorf("Internet Gateway ID (Expected=%s, Actual=%s)\n", rs.Primary.ID, gwId) - } - - return nil - } -} - -func testAccCheckAWSRouteInstanceRoute(n string, route *ec2.Route) resource.TestCheckFunc { - return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[n] - if !ok { - return fmt.Errorf("Not found: %s\n", n) - } - - if rs.Primary.ID == "" { - return fmt.Errorf("No ID is set") - } - - if gwId := aws.StringValue(route.InstanceId); gwId != rs.Primary.ID { - return fmt.Errorf("Instance ID (Expected=%s, Actual=%s)\n", rs.Primary.ID, gwId) - } - - return nil - } -} - -func testAccCheckAWSRouteNatGatewayRoute(n string, route *ec2.Route) resource.TestCheckFunc { - return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[n] - if !ok { - return fmt.Errorf("Not found: %s\n", n) - } - - if rs.Primary.ID == "" { - return fmt.Errorf("No ID is set") - } - - if gwId := aws.StringValue(route.NatGatewayId); gwId != rs.Primary.ID { - return fmt.Errorf("NAT Gateway ID (Expected=%s, Actual=%s)\n", rs.Primary.ID, gwId) - } - - return nil - } -} - -func testAccCheckAWSRouteNetworkInterfaceRoute(n string, route *ec2.Route) resource.TestCheckFunc { - return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[n] - if !ok { - return fmt.Errorf("Not found: %s\n", n) - } - - if rs.Primary.ID == "" { - return fmt.Errorf("No ID is set") - } - - if gwId := aws.StringValue(route.NetworkInterfaceId); gwId != rs.Primary.ID { - return fmt.Errorf("Network Interface ID (Expected=%s, Actual=%s)\n", rs.Primary.ID, gwId) - } - - return nil - } -} - -func testAccCheckAWSRouteTransitGatewayRoute(n string, route *ec2.Route) resource.TestCheckFunc { - return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[n] - if !ok { - return fmt.Errorf("Not found: %s\n", n) - } - - if rs.Primary.ID == "" { - return fmt.Errorf("No ID is set") - } - - if gwId := aws.StringValue(route.TransitGatewayId); gwId != rs.Primary.ID { - return fmt.Errorf("Transit Gateway ID (Expected=%s, Actual=%s)\n", rs.Primary.ID, gwId) - } - - return nil - } -} - -func testAccCheckAWSRouteVpcPeeringConnectionRoute(n string, route *ec2.Route) resource.TestCheckFunc { - return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[n] - if !ok { - return fmt.Errorf("Not found: %s\n", n) - } - - if rs.Primary.ID == "" { - return fmt.Errorf("No ID is set") - } - - if gwId := aws.StringValue(route.VpcPeeringConnectionId); gwId != rs.Primary.ID { - return fmt.Errorf("VPC Peering Connection ID (Expected=%s, Actual=%s)\n", rs.Primary.ID, gwId) - } - - return nil - } -} - func testAccCheckAWSRouteNumberOfRoutes(routeTable *ec2.RouteTable, n int) resource.TestCheckFunc { return func(s *terraform.State) error { if len := len(routeTable.Routes); len != n { From a493e561970a2f6757153b663a980d215af806f2 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Sat, 27 Jun 2020 18:16:15 -0400 Subject: [PATCH 18/40] r/aws_route: Changes for #13766, #13771. Acceptance test output: $ make testacc TEST=./aws/ TESTARGS='-run=TestAccAWSRoute_' ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws/ -v -count 1 -parallel 2 -run=TestAccAWSRoute_ -timeout 120m === RUN TestAccAWSRoute_basic === PAUSE TestAccAWSRoute_basic === RUN TestAccAWSRoute_disappears === PAUSE TestAccAWSRoute_disappears === RUN TestAccAWSRoute_IPv6_To_EgressOnlyInternetGateway === PAUSE TestAccAWSRoute_IPv6_To_EgressOnlyInternetGateway === RUN TestAccAWSRoute_IPv6_To_InternetGateway === PAUSE TestAccAWSRoute_IPv6_To_InternetGateway === RUN TestAccAWSRoute_IPv6_To_Instance === PAUSE TestAccAWSRoute_IPv6_To_Instance === RUN TestAccAWSRoute_IPv6_To_NetworkInterface === PAUSE TestAccAWSRoute_IPv6_To_NetworkInterface === RUN TestAccAWSRoute_IPv6_To_VpcPeeringConnection === PAUSE TestAccAWSRoute_IPv6_To_VpcPeeringConnection === RUN TestAccAWSRoute_IPv6_To_VpnGateway === PAUSE TestAccAWSRoute_IPv6_To_VpnGateway === RUN TestAccAWSRoute_IPv4_To_VpnGateway === PAUSE TestAccAWSRoute_IPv4_To_VpnGateway === RUN TestAccAWSRoute_IPv4_To_Instance === PAUSE TestAccAWSRoute_IPv4_To_Instance === RUN TestAccAWSRoute_IPv4_To_NetworkInterface === PAUSE TestAccAWSRoute_IPv4_To_NetworkInterface === RUN TestAccAWSRoute_IPv4_To_VpcPeeringConnection === PAUSE TestAccAWSRoute_IPv4_To_VpcPeeringConnection === RUN TestAccAWSRoute_IPv4_To_NatGateway === PAUSE TestAccAWSRoute_IPv4_To_NatGateway === RUN TestAccAWSRoute_DoesNotCrashWithVpcEndpoint === PAUSE TestAccAWSRoute_DoesNotCrashWithVpcEndpoint === RUN TestAccAWSRoute_IPv4_To_TransitGateway === PAUSE TestAccAWSRoute_IPv4_To_TransitGateway === RUN TestAccAWSRoute_ConditionalCidrBlock === PAUSE TestAccAWSRoute_ConditionalCidrBlock === CONT TestAccAWSRoute_basic === CONT TestAccAWSRoute_IPv4_To_Instance --- PASS: TestAccAWSRoute_basic (52.59s) === CONT TestAccAWSRoute_ConditionalCidrBlock --- PASS: TestAccAWSRoute_ConditionalCidrBlock (76.45s) === CONT TestAccAWSRoute_IPv4_To_TransitGateway --- PASS: TestAccAWSRoute_IPv4_To_Instance (129.99s) === CONT TestAccAWSRoute_DoesNotCrashWithVpcEndpoint --- PASS: TestAccAWSRoute_DoesNotCrashWithVpcEndpoint (63.26s) === CONT TestAccAWSRoute_IPv4_To_NatGateway --- PASS: TestAccAWSRoute_IPv4_To_NatGateway (205.43s) === CONT TestAccAWSRoute_IPv4_To_VpcPeeringConnection --- PASS: TestAccAWSRoute_IPv4_To_VpcPeeringConnection (43.54s) === CONT TestAccAWSRoute_IPv4_To_NetworkInterface --- PASS: TestAccAWSRoute_IPv4_To_NetworkInterface (33.36s) === CONT TestAccAWSRoute_IPv6_To_NetworkInterface --- PASS: TestAccAWSRoute_IPv4_To_TransitGateway (347.29s) === CONT TestAccAWSRoute_IPv4_To_VpnGateway --- PASS: TestAccAWSRoute_IPv6_To_NetworkInterface (33.84s) === CONT TestAccAWSRoute_IPv6_To_VpnGateway --- PASS: TestAccAWSRoute_IPv4_To_VpnGateway (55.26s) === CONT TestAccAWSRoute_IPv6_To_VpcPeeringConnection --- PASS: TestAccAWSRoute_IPv6_To_VpnGateway (62.51s) === CONT TestAccAWSRoute_IPv6_To_InternetGateway --- PASS: TestAccAWSRoute_IPv6_To_VpcPeeringConnection (42.95s) === CONT TestAccAWSRoute_IPv6_To_Instance --- PASS: TestAccAWSRoute_IPv6_To_InternetGateway (52.13s) === CONT TestAccAWSRoute_IPv6_To_EgressOnlyInternetGateway --- PASS: TestAccAWSRoute_IPv6_To_EgressOnlyInternetGateway (59.35s) === CONT TestAccAWSRoute_disappears --- PASS: TestAccAWSRoute_IPv6_To_Instance (119.68s) --- PASS: TestAccAWSRoute_disappears (48.50s) PASS ok github.com/terraform-providers/terraform-provider-aws/aws 731.979s --- aws/resource_aws_route_test.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/aws/resource_aws_route_test.go b/aws/resource_aws_route_test.go index a1be69887899..e8bb62c9c423 100644 --- a/aws/resource_aws_route_test.go +++ b/aws/resource_aws_route_test.go @@ -235,7 +235,7 @@ func TestAccAWSRoute_IPv6_To_NetworkInterface(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "nat_gateway_id", ""), resource.TestCheckResourceAttrPair(resourceName, "network_interface_id", eniResourceName, "id"), resource.TestCheckResourceAttr(resourceName, "origin", ec2.RouteOriginCreateRoute), - resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateActive), + resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateBlackhole), resource.TestCheckResourceAttr(resourceName, "transit_gateway_id", ""), resource.TestCheckResourceAttr(resourceName, "vpc_peering_connection_id", ""), ), @@ -442,7 +442,7 @@ func TestAccAWSRoute_IPv4_To_NetworkInterface(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "nat_gateway_id", ""), resource.TestCheckResourceAttrPair(resourceName, "network_interface_id", eniResourceName, "id"), resource.TestCheckResourceAttr(resourceName, "origin", ec2.RouteOriginCreateRoute), - resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateActive), + resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateBlackhole), resource.TestCheckResourceAttr(resourceName, "transit_gateway_id", ""), resource.TestCheckResourceAttr(resourceName, "vpc_peering_connection_id", ""), ), @@ -808,8 +808,8 @@ func testAccAWSRouteConfigIpv6NetworkInterface(rName, destinationCidr string) st return fmt.Sprintf(` data "aws_availability_zones" "current" { # Exclude usw2-az4 (us-west-2d) as it has limited instance types. - blacklisted_zone_ids = ["usw2-az4"] - state = "available" + exclude_zone_ids = ["usw2-az4"] + state = "available" filter { name = "opt-in-status" @@ -868,8 +868,8 @@ func testAccAWSRouteConfigIpv6Instance(rName, destinationCidr string) string { fmt.Sprintf(` data "aws_availability_zones" "current" { # Exclude usw2-az4 (us-west-2d) as it has limited instance types. - blacklisted_zone_ids = ["usw2-az4"] - state = "available" + exclude_zone_ids = ["usw2-az4"] + state = "available" filter { name = "opt-in-status" @@ -1172,8 +1172,8 @@ func testAccAWSRouteConfigIpv4Instance(rName, destinationCidr string) string { fmt.Sprintf(` data "aws_availability_zones" "current" { # Exclude usw2-az4 (us-west-2d) as it has limited instance types. - blacklisted_zone_ids = ["usw2-az4"] - state = "available" + exclude_zone_ids = ["usw2-az4"] + state = "available" filter { name = "opt-in-status" @@ -1229,8 +1229,8 @@ func testAccAWSRouteConfigIpv4NetworkInterface(rName, destinationCidr string) st return fmt.Sprintf(` data "aws_availability_zones" "current" { # Exclude usw2-az4 (us-west-2d) as it has limited instance types. - blacklisted_zone_ids = ["usw2-az4"] - state = "available" + exclude_zone_ids = ["usw2-az4"] + state = "available" filter { name = "opt-in-status" From 36c2963a09492ba25bc62b76f8c2db4da249d2bb Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Mon, 29 Jun 2020 09:08:39 -0400 Subject: [PATCH 19/40] r/aws_route: 'testAccCheckAWSRouteNumberOfRoutes' -> 'testAccCheckAWSRouteTableNumberOfRoutes'. --- aws/resource_aws_route_table_test.go | 10 ++++++++++ aws/resource_aws_route_test.go | 14 ++------------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/aws/resource_aws_route_table_test.go b/aws/resource_aws_route_table_test.go index 235a70c083fb..2b10ab2b1463 100644 --- a/aws/resource_aws_route_table_test.go +++ b/aws/resource_aws_route_table_test.go @@ -555,6 +555,16 @@ func TestAccAWSRouteTable_ConditionalCidrBlock(t *testing.T) { }) } +func testAccCheckAWSRouteTableNumberOfRoutes(routeTable *ec2.RouteTable, n int) resource.TestCheckFunc { + return func(s *terraform.State) error { + if len := len(routeTable.Routes); len != n { + return fmt.Errorf("Route Table has incorrect number of routes (Expected=%d, Actual=%d)\n", n, len) + } + + return nil + } +} + const testAccRouteTableConfig = ` resource "aws_vpc" "test" { cidr_block = "10.1.0.0/16" diff --git a/aws/resource_aws_route_test.go b/aws/resource_aws_route_test.go index e8bb62c9c423..7428b89c89ee 100644 --- a/aws/resource_aws_route_test.go +++ b/aws/resource_aws_route_test.go @@ -30,7 +30,7 @@ func TestAccAWSRoute_basic(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckAWSRouteExists(resourceName, &route), testAccCheckRouteTableExists(rtResourceName, &routeTable), - testAccCheckAWSRouteNumberOfRoutes(&routeTable, 2), + testAccCheckAWSRouteTableNumberOfRoutes(&routeTable, 2), resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", destinationCidr), resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), resource.TestCheckResourceAttr(resourceName, "destination_prefix_list_id", ""), @@ -556,7 +556,7 @@ func TestAccAWSRoute_DoesNotCrashWithVpcEndpoint(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckAWSRouteExists(resourceName, &route), testAccCheckRouteTableExists(rtResourceName, &routeTable), - testAccCheckAWSRouteNumberOfRoutes(&routeTable, 3), + testAccCheckAWSRouteTableNumberOfRoutes(&routeTable, 3), ), }, { @@ -717,16 +717,6 @@ func testAccAWSRouteImportStateIdFunc(resourceName string) resource.ImportStateI } } -func testAccCheckAWSRouteNumberOfRoutes(routeTable *ec2.RouteTable, n int) resource.TestCheckFunc { - return func(s *terraform.State) error { - if len := len(routeTable.Routes); len != n { - return fmt.Errorf("Route Table has incorrect number of routes (Expected=%d, Actual=%d)\n", n, len) - } - - return nil - } -} - func testAccAWSRouteConfigIpv4InternetGateway(rName, destinationCidr string) string { return fmt.Sprintf(` resource "aws_vpc" "test" { From 63097dbabc04cbe007f77d3499cc85e53fc6aa80 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Mon, 29 Jun 2020 09:16:49 -0400 Subject: [PATCH 20/40] r/aws_route: Add 'TestAccAWSRoute_routeTableDisappears'. Acceptance test output: $ make testacc TEST=./aws/ TESTARGS='-run=TestAccAWSRoute_routeTableDisappears' ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws/ -v -count 1 -parallel 20 -run=TestAccAWSRoute_routeTableDisappears -timeout 120m === RUN TestAccAWSRoute_routeTableDisappears === PAUSE TestAccAWSRoute_routeTableDisappears === CONT TestAccAWSRoute_routeTableDisappears --- PASS: TestAccAWSRoute_routeTableDisappears (48.84s) PASS ok github.com/terraform-providers/terraform-provider-aws/aws 48.910s --- aws/resource_aws_route_test.go | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/aws/resource_aws_route_test.go b/aws/resource_aws_route_test.go index 7428b89c89ee..4de5d82aa0d5 100644 --- a/aws/resource_aws_route_test.go +++ b/aws/resource_aws_route_test.go @@ -79,6 +79,30 @@ func TestAccAWSRoute_disappears(t *testing.T) { }) } +func TestAccAWSRoute_routeTableDisappears(t *testing.T) { + var route ec2.Route + resourceName := "aws_route.test" + rtResourceName := "aws_route_table.test" + rName := acctest.RandomWithPrefix("tf-acc-test") + destinationCidr := "10.3.0.0/16" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSRouteDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSRouteConfigIpv4InternetGateway(rName, destinationCidr), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSRouteExists(resourceName, &route), + testAccCheckResourceDisappears(testAccProvider, resourceAwsRouteTable(), rtResourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + func TestAccAWSRoute_IPv6_To_EgressOnlyInternetGateway(t *testing.T) { var route ec2.Route resourceName := "aws_route.test" From c0bf64658c0938d0cc2f3c5616f912e558baafaa Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 1 Jul 2020 09:53:57 -0400 Subject: [PATCH 21/40] r/aws_route: Rework 'TestAccAWSRoute_ConditionalCidrBlock'. Acceptance test output: $ make testacc TEST=./aws/ TESTARGS='-run=TestAccAWSRoute_ConditionalCidrBlock' ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws/ -v -count 1 -parallel 20 -run=TestAccAWSRoute_ConditionalCidrBlock -timeout 120m === RUN TestAccAWSRoute_ConditionalCidrBlock === PAUSE TestAccAWSRoute_ConditionalCidrBlock === CONT TestAccAWSRoute_ConditionalCidrBlock --- PASS: TestAccAWSRoute_ConditionalCidrBlock (76.68s) PASS ok github.com/terraform-providers/terraform-provider-aws/aws 76.752s --- aws/resource_aws_route_test.go | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/aws/resource_aws_route_test.go b/aws/resource_aws_route_test.go index 4de5d82aa0d5..7dadd1f24f12 100644 --- a/aws/resource_aws_route_test.go +++ b/aws/resource_aws_route_test.go @@ -638,6 +638,8 @@ func TestAccAWSRoute_ConditionalCidrBlock(t *testing.T) { var route ec2.Route resourceName := "aws_route.test" rName := acctest.RandomWithPrefix("tf-acc-test") + destinationCidr := "10.2.0.0/16" + destinationIpv6Cidr := "::/0" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -645,19 +647,19 @@ func TestAccAWSRoute_ConditionalCidrBlock(t *testing.T) { CheckDestroy: testAccCheckAWSRouteDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSRouteConfigConditionalIpv4Ipv6(rName, false), + Config: testAccAWSRouteConfigConditionalIpv4Ipv6(rName, destinationCidr, destinationIpv6Cidr, false), Check: resource.ComposeTestCheckFunc( testAccCheckAWSRouteExists(resourceName, &route), - resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", "0.0.0.0/0"), + resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", destinationCidr), resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), ), }, { - Config: testAccAWSRouteConfigConditionalIpv4Ipv6(rName, true), + Config: testAccAWSRouteConfigConditionalIpv4Ipv6(rName, destinationCidr, destinationIpv6Cidr, true), Check: resource.ComposeTestCheckFunc( testAccCheckAWSRouteExists(resourceName, &route), resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", ""), - resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", "::/0"), + resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", destinationIpv6Cidr), ), }, { @@ -1128,7 +1130,7 @@ resource "aws_route" "test" { `, rName, destinationCidr) } -func testAccAWSRouteConfigConditionalIpv4Ipv6(rName string, ipv6Route bool) string { +func testAccAWSRouteConfigConditionalIpv4Ipv6(rName, destinationCidr, destinationIpv6Cidr string, ipv6Route bool) string { return fmt.Sprintf(` resource "aws_vpc" "test" { cidr_block = "10.1.0.0/16" @@ -1139,14 +1141,6 @@ resource "aws_vpc" "test" { } } -resource "aws_egress_only_internet_gateway" "test" { - vpc_id = aws_vpc.test.id - - tags = { - Name = %[1]q - } -} - resource "aws_internet_gateway" "test" { vpc_id = aws_vpc.test.id @@ -1164,9 +1158,9 @@ resource "aws_route_table" "test" { } locals { - ipv6 = %[2]t - destination = "0.0.0.0/0" - destination_ipv6 = "::/0" + ipv6 = %[4]t + destination = %[2]q + destination_ipv6 = %[3]q } resource "aws_route" "test" { @@ -1176,7 +1170,7 @@ resource "aws_route" "test" { destination_cidr_block = local.ipv6 ? "" : local.destination destination_ipv6_cidr_block = local.ipv6 ? local.destination_ipv6 : "" } -`, rName, ipv6Route) +`, rName, destinationCidr, destinationIpv6Cidr, ipv6Route) } func testAccAWSRouteConfigIpv4Instance(rName, destinationCidr string) string { @@ -1360,7 +1354,7 @@ resource "aws_subnet" "test" { } resource "aws_internet_gateway" "test" { - vpc_id = "${aws_vpc.test.id}" + vpc_id = aws_vpc.test.id tags = { Name = %[1]q From 176993f06615e0b26ba4547491c5841f1dc2eda0 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Sat, 4 Jul 2020 17:20:17 -0400 Subject: [PATCH 22/40] r/aws_route: Add 'TestAccAWSRoute_IPv4_To_NetworkInterface_Attached' to test route to ENI attached to an instance. Acceptance test output: $ make testacc TEST=./aws/ TESTARGS='-run=TestAccAWSRoute_IPv4_To_NetworkInterface_Attached' ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws/ -v -count 1 -parallel 20 -run=TestAccAWSRoute_IPv4_To_NetworkInterface_Attached -timeout 120m === RUN TestAccAWSRoute_IPv4_To_NetworkInterface_Attached === PAUSE TestAccAWSRoute_IPv4_To_NetworkInterface_Attached === CONT TestAccAWSRoute_IPv4_To_NetworkInterface_Attached --- PASS: TestAccAWSRoute_IPv4_To_NetworkInterface_Attached (113.54s) PASS ok github.com/terraform-providers/terraform-provider-aws/aws 113.607s --- aws/resource_aws_route_test.go | 131 +++++++++++++++++++++++++++++++-- 1 file changed, 125 insertions(+), 6 deletions(-) diff --git a/aws/resource_aws_route_test.go b/aws/resource_aws_route_test.go index 7dadd1f24f12..67ffd7e9de5d 100644 --- a/aws/resource_aws_route_test.go +++ b/aws/resource_aws_route_test.go @@ -231,7 +231,7 @@ func TestAccAWSRoute_IPv6_To_Instance(t *testing.T) { }) } -func TestAccAWSRoute_IPv6_To_NetworkInterface(t *testing.T) { +func TestAccAWSRoute_IPv6_To_NetworkInterface_Unattached(t *testing.T) { var route ec2.Route resourceName := "aws_route.test" eniResourceName := "aws_network_interface.test" @@ -246,7 +246,7 @@ func TestAccAWSRoute_IPv6_To_NetworkInterface(t *testing.T) { CheckDestroy: testAccCheckAWSRouteDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSRouteConfigIpv6NetworkInterface(rName, destinationCidr), + Config: testAccAWSRouteConfigIpv6NetworkInterfaceUnattached(rName, destinationCidr), Check: resource.ComposeTestCheckFunc( testAccCheckAWSRouteExists(resourceName, &route), resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", ""), @@ -438,7 +438,7 @@ func TestAccAWSRoute_IPv4_To_Instance(t *testing.T) { }) } -func TestAccAWSRoute_IPv4_To_NetworkInterface(t *testing.T) { +func TestAccAWSRoute_IPv4_To_NetworkInterface_Unattached(t *testing.T) { var route ec2.Route resourceName := "aws_route.test" eniResourceName := "aws_network_interface.test" @@ -453,7 +453,7 @@ func TestAccAWSRoute_IPv4_To_NetworkInterface(t *testing.T) { CheckDestroy: testAccCheckAWSRouteDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSRouteConfigIpv4NetworkInterface(rName, destinationCidr), + Config: testAccAWSRouteConfigIpv4NetworkInterfaceUnattached(rName, destinationCidr), Check: resource.ComposeTestCheckFunc( testAccCheckAWSRouteExists(resourceName, &route), resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", destinationCidr), @@ -481,6 +481,50 @@ func TestAccAWSRoute_IPv4_To_NetworkInterface(t *testing.T) { }) } +func TestAccAWSRoute_IPv4_To_NetworkInterface_Attached(t *testing.T) { + var route ec2.Route + resourceName := "aws_route.test" + eniResourceName := "aws_network_interface.test" + instanceResourceName := "aws_instance.test" + rName := acctest.RandomWithPrefix("tf-acc-test") + destinationCidr := "10.3.0.0/16" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSRouteDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSRouteConfigIpv4NetworkInterfaceAttached(rName, destinationCidr), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSRouteExists(resourceName, &route), + resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", destinationCidr), + resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), + resource.TestCheckResourceAttr(resourceName, "destination_prefix_list_id", ""), + resource.TestCheckResourceAttr(resourceName, "egress_only_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "gateway_id", ""), + resource.TestCheckResourceAttrPair(resourceName, "instance_id", instanceResourceName, "id"), + testAccCheckResourceAttrAccountID(resourceName, "instance_owner_id"), + resource.TestCheckResourceAttr(resourceName, "nat_gateway_id", ""), + resource.TestCheckResourceAttrPair(resourceName, "network_interface_id", eniResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "origin", ec2.RouteOriginCreateRoute), + resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateActive), + resource.TestCheckResourceAttr(resourceName, "transit_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "vpc_peering_connection_id", ""), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateIdFunc: testAccAWSRouteImportStateIdFunc(resourceName), + ImportStateVerify: true, + }, + }, + }) +} + func TestAccAWSRoute_IPv4_To_VpcPeeringConnection(t *testing.T) { var route ec2.Route resourceName := "aws_route.test" @@ -820,7 +864,7 @@ resource "aws_route" "test" { `, rName, destinationCidr) } -func testAccAWSRouteConfigIpv6NetworkInterface(rName, destinationCidr string) string { +func testAccAWSRouteConfigIpv6NetworkInterfaceUnattached(rName, destinationCidr string) string { return fmt.Sprintf(` data "aws_availability_zones" "current" { # Exclude usw2-az4 (us-west-2d) as it has limited instance types. @@ -1233,7 +1277,7 @@ resource "aws_route" "test" { `, rName, destinationCidr)) } -func testAccAWSRouteConfigIpv4NetworkInterface(rName, destinationCidr string) string { +func testAccAWSRouteConfigIpv4NetworkInterfaceUnattached(rName, destinationCidr string) string { return fmt.Sprintf(` data "aws_availability_zones" "current" { # Exclude usw2-az4 (us-west-2d) as it has limited instance types. @@ -1288,6 +1332,81 @@ resource "aws_route" "test" { `, rName, destinationCidr) } +func testAccAWSRouteConfigIpv4NetworkInterfaceAttached(rName, destinationCidr string) string { + return composeConfig( + testAccLatestAmazonLinuxHvmEbsAmiConfig(), + testAccAvailableEc2InstanceTypeForRegion("t3.micro", "t2.micro"), + fmt.Sprintf(` +data "aws_availability_zones" "current" { + # Exclude usw2-az4 (us-west-2d) as it has limited instance types. + exclude_zone_ids = ["usw2-az4"] + state = "available" + + filter { + name = "opt-in-status" + values = ["opt-in-not-required"] + } +} + +resource "aws_vpc" "test" { + cidr_block = "10.1.0.0/16" + + tags = { + Name = %[1]q + } +} + +resource "aws_subnet" "test" { + cidr_block = "10.1.1.0/24" + vpc_id = aws_vpc.test.id + availability_zone = data.aws_availability_zones.current.names[0] + + tags = { + Name = %[1]q + } +} + +resource "aws_network_interface" "test" { + subnet_id = aws_subnet.test.id + + tags = { + Name = %[1]q + } +} + +resource "aws_instance" "test" { + ami = data.aws_ami.amzn-ami-minimal-hvm-ebs.id + instance_type = data.aws_ec2_instance_type_offering.available.instance_type + + network_interface { + device_index = 0 + network_interface_id = aws_network_interface.test.id + } + + tags = { + Name = %[1]q + } +} + +resource "aws_route_table" "test" { + vpc_id = aws_vpc.test.id + + tags = { + Name = %[1]q + } +} + +resource "aws_route" "test" { + route_table_id = aws_route_table.test.id + destination_cidr_block = %[2]q + network_interface_id = aws_network_interface.test.id + + # Wait for the ENI attachment. + depends_on = [aws_instance.test] +} +`, rName, destinationCidr)) +} + func testAccAWSRouteConfigIpv4VpcPeeringConnection(rName, destinationCidr string) string { return fmt.Sprintf(` resource "aws_vpc" "test" { From c2b78d025da247fe7ae8d622e3357d75f3e2ba8f Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Sat, 4 Jul 2020 17:32:48 -0400 Subject: [PATCH 23/40] r/aws_route: Add 'TestAccAWSRoute_IPv4_To_NetworkInterface_TwoAttachments' to test route to 2 ENIs attached to the same instance (#2270). Acceptance test output (failure expected): $ make testacc TEST=./aws/ TESTARGS='-run=TestAccAWSRoute_IPv4_To_NetworkInterface_TwoAttachments' ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws/ -v -count 1 -parallel 20 -run=TestAccAWSRoute_IPv4_To_NetworkInterface_TwoAttachments -timeout 120m === RUN TestAccAWSRoute_IPv4_To_NetworkInterface_TwoAttachments === PAUSE TestAccAWSRoute_IPv4_To_NetworkInterface_TwoAttachments === CONT TestAccAWSRoute_IPv4_To_NetworkInterface_TwoAttachments --- FAIL: TestAccAWSRoute_IPv4_To_NetworkInterface_TwoAttachments (127.29s) testing.go:684: Step 1 error: errors during apply: Error: InvalidInstanceID: There are multiple interfaces attached to instance 'i-005065eb4850f01a4'. Please specify an interface ID for the operation instead. status code: 400, request id: f601a6af-729a-4830-835b-be8887b0c3ee on /tmp/tf-test358593801/main.tf line 98: (source code not available) FAIL FAIL github.com/terraform-providers/terraform-provider-aws/aws 127.347s FAIL GNUmakefile:26: recipe for target 'testacc' failed make: *** [testacc] Error 1 --- aws/resource_aws_route_test.go | 152 +++++++++++++++++++++++++++++++++ 1 file changed, 152 insertions(+) diff --git a/aws/resource_aws_route_test.go b/aws/resource_aws_route_test.go index 67ffd7e9de5d..e55ff734a1e0 100644 --- a/aws/resource_aws_route_test.go +++ b/aws/resource_aws_route_test.go @@ -525,6 +525,70 @@ func TestAccAWSRoute_IPv4_To_NetworkInterface_Attached(t *testing.T) { }) } +func TestAccAWSRoute_IPv4_To_NetworkInterface_TwoAttachments(t *testing.T) { + var route ec2.Route + resourceName := "aws_route.test" + eni1ResourceName := "aws_network_interface.test1" + eni2ResourceName := "aws_network_interface.test2" + instanceResourceName := "aws_instance.test" + rName := acctest.RandomWithPrefix("tf-acc-test") + destinationCidr := "10.3.0.0/16" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSRouteDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSRouteConfigIpv4NetworkInterfaceTwoAttachments(rName, destinationCidr, eni1ResourceName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSRouteExists(resourceName, &route), + resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", destinationCidr), + resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), + resource.TestCheckResourceAttr(resourceName, "destination_prefix_list_id", ""), + resource.TestCheckResourceAttr(resourceName, "egress_only_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "gateway_id", ""), + resource.TestCheckResourceAttrPair(resourceName, "instance_id", instanceResourceName, "id"), + testAccCheckResourceAttrAccountID(resourceName, "instance_owner_id"), + resource.TestCheckResourceAttr(resourceName, "nat_gateway_id", ""), + resource.TestCheckResourceAttrPair(resourceName, "network_interface_id", eni1ResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "origin", ec2.RouteOriginCreateRoute), + resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateActive), + resource.TestCheckResourceAttr(resourceName, "transit_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "vpc_peering_connection_id", ""), + ), + }, + { + Config: testAccAWSRouteConfigIpv4NetworkInterfaceTwoAttachments(rName, destinationCidr, eni2ResourceName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSRouteExists(resourceName, &route), + resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", destinationCidr), + resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), + resource.TestCheckResourceAttr(resourceName, "destination_prefix_list_id", ""), + resource.TestCheckResourceAttr(resourceName, "egress_only_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "gateway_id", ""), + resource.TestCheckResourceAttrPair(resourceName, "instance_id", instanceResourceName, "id"), + testAccCheckResourceAttrAccountID(resourceName, "instance_owner_id"), + resource.TestCheckResourceAttr(resourceName, "nat_gateway_id", ""), + resource.TestCheckResourceAttrPair(resourceName, "network_interface_id", eni2ResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "origin", ec2.RouteOriginCreateRoute), + resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateActive), + resource.TestCheckResourceAttr(resourceName, "transit_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "vpc_peering_connection_id", ""), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateIdFunc: testAccAWSRouteImportStateIdFunc(resourceName), + ImportStateVerify: true, + }, + }, + }) +} + func TestAccAWSRoute_IPv4_To_VpcPeeringConnection(t *testing.T) { var route ec2.Route resourceName := "aws_route.test" @@ -1407,6 +1471,94 @@ resource "aws_route" "test" { `, rName, destinationCidr)) } +func testAccAWSRouteConfigIpv4NetworkInterfaceTwoAttachments(rName, destinationCidr, targetResourceName string) string { + return composeConfig( + testAccLatestAmazonLinuxHvmEbsAmiConfig(), + testAccAvailableEc2InstanceTypeForRegion("t3.micro", "t2.micro"), + fmt.Sprintf(` +data "aws_availability_zones" "current" { + # Exclude usw2-az4 (us-west-2d) as it has limited instance types. + exclude_zone_ids = ["usw2-az4"] + state = "available" + + filter { + name = "opt-in-status" + values = ["opt-in-not-required"] + } +} + +resource "aws_vpc" "test" { + cidr_block = "10.1.0.0/16" + + tags = { + Name = %[1]q + } +} + +resource "aws_subnet" "test" { + cidr_block = "10.1.1.0/24" + vpc_id = aws_vpc.test.id + availability_zone = data.aws_availability_zones.current.names[0] + + tags = { + Name = %[1]q + } +} + +resource "aws_network_interface" "test1" { + subnet_id = aws_subnet.test.id + + tags = { + Name = %[1]q + } +} + +resource "aws_network_interface" "test2" { + subnet_id = aws_subnet.test.id + + tags = { + Name = %[1]q + } +} + +resource "aws_instance" "test" { + ami = data.aws_ami.amzn-ami-minimal-hvm-ebs.id + instance_type = data.aws_ec2_instance_type_offering.available.instance_type + + network_interface { + device_index = 0 + network_interface_id = aws_network_interface.test1.id + } + + network_interface { + device_index = 1 + network_interface_id = aws_network_interface.test2.id + } + + tags = { + Name = %[1]q + } +} + +resource "aws_route_table" "test" { + vpc_id = aws_vpc.test.id + + tags = { + Name = %[1]q + } +} + +resource "aws_route" "test" { + route_table_id = aws_route_table.test.id + destination_cidr_block = %[2]q + network_interface_id = %[3]s.id + + # Wait for the ENI attachment. + depends_on = [aws_instance.test] +} +`, rName, destinationCidr, targetResourceName)) +} + func testAccAWSRouteConfigIpv4VpcPeeringConnection(rName, destinationCidr string) string { return fmt.Sprintf(` resource "aws_vpc" "test" { From 42bd9bc74f3dc569a787d15d3beafa1f7357da99 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Sat, 4 Jul 2020 17:36:55 -0400 Subject: [PATCH 24/40] r/aws_route: Comment out failing 'TestAccAWSRoute_IPv4_To_NetworkInterface_TwoAttachments'. --- aws/resource_aws_route_test.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/aws/resource_aws_route_test.go b/aws/resource_aws_route_test.go index e55ff734a1e0..3ba8cf2bd824 100644 --- a/aws/resource_aws_route_test.go +++ b/aws/resource_aws_route_test.go @@ -525,6 +525,7 @@ func TestAccAWSRoute_IPv4_To_NetworkInterface_Attached(t *testing.T) { }) } +/* func TestAccAWSRoute_IPv4_To_NetworkInterface_TwoAttachments(t *testing.T) { var route ec2.Route resourceName := "aws_route.test" @@ -588,6 +589,7 @@ func TestAccAWSRoute_IPv4_To_NetworkInterface_TwoAttachments(t *testing.T) { }, }) } +*/ func TestAccAWSRoute_IPv4_To_VpcPeeringConnection(t *testing.T) { var route ec2.Route @@ -1471,6 +1473,7 @@ resource "aws_route" "test" { `, rName, destinationCidr)) } +/* func testAccAWSRouteConfigIpv4NetworkInterfaceTwoAttachments(rName, destinationCidr, targetResourceName string) string { return composeConfig( testAccLatestAmazonLinuxHvmEbsAmiConfig(), @@ -1558,6 +1561,7 @@ resource "aws_route" "test" { } `, rName, destinationCidr, targetResourceName)) } +*/ func testAccAWSRouteConfigIpv4VpcPeeringConnection(rName, destinationCidr string) string { return fmt.Sprintf(` From fd956d860ee8407bb6d1117fbf8edf19be765f2d Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Mon, 6 Jul 2020 16:00:12 -0400 Subject: [PATCH 25/40] r/aws_route: Use 'available' as the name of the 'aws_availability_zones' data source. --- aws/resource_aws_route_test.go | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/aws/resource_aws_route_test.go b/aws/resource_aws_route_test.go index 3ba8cf2bd824..e92eb2dcf519 100644 --- a/aws/resource_aws_route_test.go +++ b/aws/resource_aws_route_test.go @@ -932,7 +932,7 @@ resource "aws_route" "test" { func testAccAWSRouteConfigIpv6NetworkInterfaceUnattached(rName, destinationCidr string) string { return fmt.Sprintf(` -data "aws_availability_zones" "current" { +data "aws_availability_zones" "available" { # Exclude usw2-az4 (us-west-2d) as it has limited instance types. exclude_zone_ids = ["usw2-az4"] state = "available" @@ -955,7 +955,7 @@ resource "aws_vpc" "test" { resource "aws_subnet" "test" { cidr_block = "10.1.1.0/24" vpc_id = aws_vpc.test.id - availability_zone = data.aws_availability_zones.current.names[0] + availability_zone = data.aws_availability_zones.available.names[0] ipv6_cidr_block = cidrsubnet(aws_vpc.test.ipv6_cidr_block, 8, 1) tags = { @@ -992,7 +992,7 @@ func testAccAWSRouteConfigIpv6Instance(rName, destinationCidr string) string { testAccLatestAmazonLinuxHvmEbsAmiConfig(), testAccAvailableEc2InstanceTypeForRegion("t3.micro", "t2.micro"), fmt.Sprintf(` -data "aws_availability_zones" "current" { +data "aws_availability_zones" "available" { # Exclude usw2-az4 (us-west-2d) as it has limited instance types. exclude_zone_ids = ["usw2-az4"] state = "available" @@ -1015,7 +1015,7 @@ resource "aws_vpc" "test" { resource "aws_subnet" "test" { cidr_block = "10.1.1.0/24" vpc_id = aws_vpc.test.id - availability_zone = data.aws_availability_zones.current.names[0] + availability_zone = data.aws_availability_zones.available.names[0] ipv6_cidr_block = cidrsubnet(aws_vpc.test.ipv6_cidr_block, 8, 1) tags = { @@ -1288,7 +1288,7 @@ func testAccAWSRouteConfigIpv4Instance(rName, destinationCidr string) string { testAccLatestAmazonLinuxHvmEbsAmiConfig(), testAccAvailableEc2InstanceTypeForRegion("t3.micro", "t2.micro"), fmt.Sprintf(` -data "aws_availability_zones" "current" { +data "aws_availability_zones" "available" { # Exclude usw2-az4 (us-west-2d) as it has limited instance types. exclude_zone_ids = ["usw2-az4"] state = "available" @@ -1310,7 +1310,7 @@ resource "aws_vpc" "test" { resource "aws_subnet" "test" { cidr_block = "10.1.1.0/24" vpc_id = aws_vpc.test.id - availability_zone = data.aws_availability_zones.current.names[0] + availability_zone = data.aws_availability_zones.available.names[0] tags = { Name = %[1]q @@ -1345,7 +1345,7 @@ resource "aws_route" "test" { func testAccAWSRouteConfigIpv4NetworkInterfaceUnattached(rName, destinationCidr string) string { return fmt.Sprintf(` -data "aws_availability_zones" "current" { +data "aws_availability_zones" "available" { # Exclude usw2-az4 (us-west-2d) as it has limited instance types. exclude_zone_ids = ["usw2-az4"] state = "available" @@ -1367,7 +1367,7 @@ resource "aws_vpc" "test" { resource "aws_subnet" "test" { cidr_block = "10.1.1.0/24" vpc_id = aws_vpc.test.id - availability_zone = data.aws_availability_zones.current.names[0] + availability_zone = data.aws_availability_zones.available.names[0] tags = { Name = %[1]q @@ -1403,7 +1403,7 @@ func testAccAWSRouteConfigIpv4NetworkInterfaceAttached(rName, destinationCidr st testAccLatestAmazonLinuxHvmEbsAmiConfig(), testAccAvailableEc2InstanceTypeForRegion("t3.micro", "t2.micro"), fmt.Sprintf(` -data "aws_availability_zones" "current" { +data "aws_availability_zones" "available" { # Exclude usw2-az4 (us-west-2d) as it has limited instance types. exclude_zone_ids = ["usw2-az4"] state = "available" @@ -1425,7 +1425,7 @@ resource "aws_vpc" "test" { resource "aws_subnet" "test" { cidr_block = "10.1.1.0/24" vpc_id = aws_vpc.test.id - availability_zone = data.aws_availability_zones.current.names[0] + availability_zone = data.aws_availability_zones.available.names[0] tags = { Name = %[1]q @@ -1479,7 +1479,7 @@ func testAccAWSRouteConfigIpv4NetworkInterfaceTwoAttachments(rName, destinationC testAccLatestAmazonLinuxHvmEbsAmiConfig(), testAccAvailableEc2InstanceTypeForRegion("t3.micro", "t2.micro"), fmt.Sprintf(` -data "aws_availability_zones" "current" { +data "aws_availability_zones" "available" { # Exclude usw2-az4 (us-west-2d) as it has limited instance types. exclude_zone_ids = ["usw2-az4"] state = "available" @@ -1501,7 +1501,7 @@ resource "aws_vpc" "test" { resource "aws_subnet" "test" { cidr_block = "10.1.1.0/24" vpc_id = aws_vpc.test.id - availability_zone = data.aws_availability_zones.current.names[0] + availability_zone = data.aws_availability_zones.available.names[0] tags = { Name = %[1]q From 141714e091beb6bbeff9ec86ec365d190c09f995 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 15 Jul 2020 16:55:25 -0400 Subject: [PATCH 26/40] r/aws_route: Use Amazon NAT instance AMI for instance tests. Acceptance test output: $ make testacc TEST=./aws/ TESTARGS='-run=TestAccAWSRoute_IPv6_To_Instance' ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws/ -v -count 1 -parallel 20 -run=TestAccAWSRoute_IPv6_To_Instance -timeout 120m === RUN TestAccAWSRoute_IPv6_To_Instance === PAUSE TestAccAWSRoute_IPv6_To_Instance === CONT TestAccAWSRoute_IPv6_To_Instance --- PASS: TestAccAWSRoute_IPv6_To_Instance (128.20s) PASS ok github.com/terraform-providers/terraform-provider-aws/aws 128.262s $ make testacc TEST=./aws/ TESTARGS='-run=TestAccAWSRoute_IPv4_To_Instance' ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws/ -v -count 1 -parallel 20 -run=TestAccAWSRoute_IPv4_To_Instance -timeout 120m === RUN TestAccAWSRoute_IPv4_To_Instance === PAUSE TestAccAWSRoute_IPv4_To_Instance === CONT TestAccAWSRoute_IPv4_To_Instance --- PASS: TestAccAWSRoute_IPv4_To_Instance (116.72s) PASS ok github.com/terraform-providers/terraform-provider-aws/aws 116.766s $ make testacc TEST=./aws/ TESTARGS='-run=TestAccAWSRoute_IPv4_To_NetworkInterface_Attached' ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws/ -v -count 1 -parallel 20 -run=TestAccAWSRoute_IPv4_To_NetworkInterface_Attached -timeout 120m === RUN TestAccAWSRoute_IPv4_To_NetworkInterface_Attached === PAUSE TestAccAWSRoute_IPv4_To_NetworkInterface_Attached === CONT TestAccAWSRoute_IPv4_To_NetworkInterface_Attached --- PASS: TestAccAWSRoute_IPv4_To_NetworkInterface_Attached (330.31s) PASS ok github.com/terraform-providers/terraform-provider-aws/aws 330.352s --- aws/resource_aws_route_table_test.go | 18 ++++++++++++++++++ aws/resource_aws_route_test.go | 16 ++++++++-------- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/aws/resource_aws_route_table_test.go b/aws/resource_aws_route_table_test.go index 2b10ab2b1463..9dd3d7dcee0b 100644 --- a/aws/resource_aws_route_table_test.go +++ b/aws/resource_aws_route_table_test.go @@ -1004,3 +1004,21 @@ resource "aws_route_table" "test" { } `, rName, ipv6Route) } + +// testAccLatestAmazonNatInstanceAmiConfig returns the configuration for a data source that +// describes the latest Amazon NAT instance AMI. +// See https://docs.aws.amazon.com/vpc/latest/userguide/VPC_NAT_Instance.html#nat-instance-ami. +// The data source is named 'amzn-ami-nat-instance'. +func testAccLatestAmazonNatInstanceAmiConfig() string { + return fmt.Sprintf(` +data "aws_ami" "amzn-ami-nat-instance" { + most_recent = true + owners = ["amazon"] + + filter { + name = "name" + values = ["amzn-ami-vpc-nat-*"] + } +} +`) +} diff --git a/aws/resource_aws_route_test.go b/aws/resource_aws_route_test.go index e92eb2dcf519..b14ee77c8a63 100644 --- a/aws/resource_aws_route_test.go +++ b/aws/resource_aws_route_test.go @@ -989,7 +989,7 @@ resource "aws_route" "test" { func testAccAWSRouteConfigIpv6Instance(rName, destinationCidr string) string { return composeConfig( - testAccLatestAmazonLinuxHvmEbsAmiConfig(), + testAccLatestAmazonNatInstanceAmiConfig(), testAccAvailableEc2InstanceTypeForRegion("t3.micro", "t2.micro"), fmt.Sprintf(` data "aws_availability_zones" "available" { @@ -1024,7 +1024,7 @@ resource "aws_subnet" "test" { } resource "aws_instance" "test" { - ami = data.aws_ami.amzn-ami-minimal-hvm-ebs.id + ami = data.aws_ami.amzn-ami-nat-instance.id instance_type = data.aws_ec2_instance_type_offering.available.instance_type subnet_id = aws_subnet.test.id @@ -1285,7 +1285,7 @@ resource "aws_route" "test" { func testAccAWSRouteConfigIpv4Instance(rName, destinationCidr string) string { return composeConfig( - testAccLatestAmazonLinuxHvmEbsAmiConfig(), + testAccLatestAmazonNatInstanceAmiConfig(), testAccAvailableEc2InstanceTypeForRegion("t3.micro", "t2.micro"), fmt.Sprintf(` data "aws_availability_zones" "available" { @@ -1318,7 +1318,7 @@ resource "aws_subnet" "test" { } resource "aws_instance" "test" { - ami = data.aws_ami.amzn-ami-minimal-hvm-ebs.id + ami = data.aws_ami.amzn-ami-nat-instance.id instance_type = data.aws_ec2_instance_type_offering.available.instance_type subnet_id = aws_subnet.test.id @@ -1400,7 +1400,7 @@ resource "aws_route" "test" { func testAccAWSRouteConfigIpv4NetworkInterfaceAttached(rName, destinationCidr string) string { return composeConfig( - testAccLatestAmazonLinuxHvmEbsAmiConfig(), + testAccLatestAmazonNatInstanceAmiConfig(), testAccAvailableEc2InstanceTypeForRegion("t3.micro", "t2.micro"), fmt.Sprintf(` data "aws_availability_zones" "available" { @@ -1441,7 +1441,7 @@ resource "aws_network_interface" "test" { } resource "aws_instance" "test" { - ami = data.aws_ami.amzn-ami-minimal-hvm-ebs.id + ami = data.aws_ami.amzn-ami-nat-instance.id instance_type = data.aws_ec2_instance_type_offering.available.instance_type network_interface { @@ -1476,7 +1476,7 @@ resource "aws_route" "test" { /* func testAccAWSRouteConfigIpv4NetworkInterfaceTwoAttachments(rName, destinationCidr, targetResourceName string) string { return composeConfig( - testAccLatestAmazonLinuxHvmEbsAmiConfig(), + testAccLatestAmazonNatInstanceAmiConfig(), testAccAvailableEc2InstanceTypeForRegion("t3.micro", "t2.micro"), fmt.Sprintf(` data "aws_availability_zones" "available" { @@ -1525,7 +1525,7 @@ resource "aws_network_interface" "test2" { } resource "aws_instance" "test" { - ami = data.aws_ami.amzn-ami-minimal-hvm-ebs.id + ami = data.aws_ami.amzn-ami-nat-instance.id instance_type = data.aws_ec2_instance_type_offering.available.instance_type network_interface { From 36faae16dac3ba6bda905695098071599d40221d Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Sun, 9 Aug 2020 18:02:18 -0400 Subject: [PATCH 27/40] Use 'testAccAvailableAZsNoOptInDefaultExcludeConfig'. --- aws/resource_aws_route_test.go | 99 ++++++---------------------------- 1 file changed, 16 insertions(+), 83 deletions(-) diff --git a/aws/resource_aws_route_test.go b/aws/resource_aws_route_test.go index b14ee77c8a63..486d80acb25a 100644 --- a/aws/resource_aws_route_test.go +++ b/aws/resource_aws_route_test.go @@ -931,18 +931,9 @@ resource "aws_route" "test" { } func testAccAWSRouteConfigIpv6NetworkInterfaceUnattached(rName, destinationCidr string) string { - return fmt.Sprintf(` -data "aws_availability_zones" "available" { - # Exclude usw2-az4 (us-west-2d) as it has limited instance types. - exclude_zone_ids = ["usw2-az4"] - state = "available" - - filter { - name = "opt-in-status" - values = ["opt-in-not-required"] - } -} - + return composeConfig( + testAccAvailableAZsNoOptInDefaultExcludeConfig(), + fmt.Sprintf(` resource "aws_vpc" "test" { cidr_block = "10.1.0.0/16" assign_generated_ipv6_cidr_block = true @@ -984,25 +975,15 @@ resource "aws_route" "test" { destination_ipv6_cidr_block = %[2]q network_interface_id = aws_network_interface.test.id } -`, rName, destinationCidr) +`, rName, destinationCidr)) } func testAccAWSRouteConfigIpv6Instance(rName, destinationCidr string) string { return composeConfig( testAccLatestAmazonNatInstanceAmiConfig(), + testAccAvailableAZsNoOptInDefaultExcludeConfig(), testAccAvailableEc2InstanceTypeForRegion("t3.micro", "t2.micro"), fmt.Sprintf(` -data "aws_availability_zones" "available" { - # Exclude usw2-az4 (us-west-2d) as it has limited instance types. - exclude_zone_ids = ["usw2-az4"] - state = "available" - - filter { - name = "opt-in-status" - values = ["opt-in-not-required"] - } -} - resource "aws_vpc" "test" { cidr_block = "10.1.0.0/16" assign_generated_ipv6_cidr_block = true @@ -1178,18 +1159,9 @@ resource "aws_vpc_endpoint" "test" { } func testAccAWSRouteConfigIpv4TransitGateway(rName, destinationCidr string) string { - return fmt.Sprintf(` -data "aws_availability_zones" "available" { - # IncorrectState: Transit Gateway is not available in availability zone us-west-2d - exclude_zone_ids = ["usw2-az4"] - state = "available" - - filter { - name = "opt-in-status" - values = ["opt-in-not-required"] - } -} - + return composeConfig( + testAccAvailableAZsNoOptInDefaultExcludeConfig(), + fmt.Sprintf(` resource "aws_vpc" "test" { cidr_block = "10.1.0.0/16" @@ -1237,7 +1209,7 @@ resource "aws_route" "test" { route_table_id = aws_route_table.test.id transit_gateway_id = aws_ec2_transit_gateway_vpc_attachment.test.transit_gateway_id } -`, rName, destinationCidr) +`, rName, destinationCidr)) } func testAccAWSRouteConfigConditionalIpv4Ipv6(rName, destinationCidr, destinationIpv6Cidr string, ipv6Route bool) string { @@ -1286,19 +1258,9 @@ resource "aws_route" "test" { func testAccAWSRouteConfigIpv4Instance(rName, destinationCidr string) string { return composeConfig( testAccLatestAmazonNatInstanceAmiConfig(), + testAccAvailableAZsNoOptInDefaultExcludeConfig(), testAccAvailableEc2InstanceTypeForRegion("t3.micro", "t2.micro"), fmt.Sprintf(` -data "aws_availability_zones" "available" { - # Exclude usw2-az4 (us-west-2d) as it has limited instance types. - exclude_zone_ids = ["usw2-az4"] - state = "available" - - filter { - name = "opt-in-status" - values = ["opt-in-not-required"] - } -} - resource "aws_vpc" "test" { cidr_block = "10.1.0.0/16" @@ -1344,18 +1306,9 @@ resource "aws_route" "test" { } func testAccAWSRouteConfigIpv4NetworkInterfaceUnattached(rName, destinationCidr string) string { - return fmt.Sprintf(` -data "aws_availability_zones" "available" { - # Exclude usw2-az4 (us-west-2d) as it has limited instance types. - exclude_zone_ids = ["usw2-az4"] - state = "available" - - filter { - name = "opt-in-status" - values = ["opt-in-not-required"] - } -} - + return composeConfig( + testAccAvailableAZsNoOptInDefaultExcludeConfig(), + fmt.Sprintf(` resource "aws_vpc" "test" { cidr_block = "10.1.0.0/16" @@ -1395,25 +1348,15 @@ resource "aws_route" "test" { destination_cidr_block = %[2]q network_interface_id = aws_network_interface.test.id } -`, rName, destinationCidr) +`, rName, destinationCidr)) } func testAccAWSRouteConfigIpv4NetworkInterfaceAttached(rName, destinationCidr string) string { return composeConfig( testAccLatestAmazonNatInstanceAmiConfig(), + testAccAvailableAZsNoOptInDefaultExcludeConfig(), testAccAvailableEc2InstanceTypeForRegion("t3.micro", "t2.micro"), fmt.Sprintf(` -data "aws_availability_zones" "available" { - # Exclude usw2-az4 (us-west-2d) as it has limited instance types. - exclude_zone_ids = ["usw2-az4"] - state = "available" - - filter { - name = "opt-in-status" - values = ["opt-in-not-required"] - } -} - resource "aws_vpc" "test" { cidr_block = "10.1.0.0/16" @@ -1477,19 +1420,9 @@ resource "aws_route" "test" { func testAccAWSRouteConfigIpv4NetworkInterfaceTwoAttachments(rName, destinationCidr, targetResourceName string) string { return composeConfig( testAccLatestAmazonNatInstanceAmiConfig(), + testAccAvailableAZsNoOptInDefaultExcludeConfig(), testAccAvailableEc2InstanceTypeForRegion("t3.micro", "t2.micro"), fmt.Sprintf(` -data "aws_availability_zones" "available" { - # Exclude usw2-az4 (us-west-2d) as it has limited instance types. - exclude_zone_ids = ["usw2-az4"] - state = "available" - - filter { - name = "opt-in-status" - values = ["opt-in-not-required"] - } -} - resource "aws_vpc" "test" { cidr_block = "10.1.0.0/16" From ba1983d8e8011a6b264cf00c9f729f4e63a2aaa7 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Sat, 27 Jun 2020 18:38:35 -0400 Subject: [PATCH 28/40] r/aws_route: Add 'TestAccAWSRoute_IPv4_Update_Target'. Currently fails. --- aws/resource_aws_route_test.go | 302 +++++++++++++++++++++++++++++++++ 1 file changed, 302 insertions(+) diff --git a/aws/resource_aws_route_test.go b/aws/resource_aws_route_test.go index 486d80acb25a..cd03ac543cfe 100644 --- a/aws/resource_aws_route_test.go +++ b/aws/resource_aws_route_test.go @@ -782,6 +782,167 @@ func TestAccAWSRoute_ConditionalCidrBlock(t *testing.T) { }) } +func TestAccAWSRoute_IPv4_Update_Target(t *testing.T) { + var route ec2.Route + resourceName := "aws_route.test" + vgwResourceName := "aws_vpn_gateway.test" + instanceResourceName := "aws_instance.test" + igwResourceName := "aws_internet_gateway.test" + eniResourceName := "aws_network_interface.test" + pcxResourceName := "aws_vpc_peering_connection.test" + ngwResourceName := "aws_nat_gateway.test" + tgwResourceName := "aws_ec2_transit_gateway.test" + rName := acctest.RandomWithPrefix("tf-acc-test") + destinationCidr := "10.3.0.0/16" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSRouteDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSRouteConfigIpv4FlexiTarget(rName, destinationCidr, "instance_id", instanceResourceName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSRouteExists(resourceName, &route), + resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", destinationCidr), + resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), + resource.TestCheckResourceAttr(resourceName, "destination_prefix_list_id", ""), + resource.TestCheckResourceAttr(resourceName, "egress_only_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "gateway_id", ""), + resource.TestCheckResourceAttrPair(resourceName, "instance_id", instanceResourceName, "id"), + testAccCheckResourceAttrAccountID(resourceName, "instance_owner_id"), + resource.TestCheckResourceAttr(resourceName, "nat_gateway_id", ""), + resource.TestCheckResourceAttrPair(resourceName, "network_interface_id", instanceResourceName, "primary_network_interface_id"), + resource.TestCheckResourceAttr(resourceName, "origin", ec2.RouteOriginCreateRoute), + resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateActive), + resource.TestCheckResourceAttr(resourceName, "transit_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "vpc_peering_connection_id", ""), + ), + }, + { + Config: testAccAWSRouteConfigIpv4FlexiTarget(rName, destinationCidr, "gateway_id", igwResourceName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSRouteExists(resourceName, &route), + resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", destinationCidr), + resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), + resource.TestCheckResourceAttr(resourceName, "destination_prefix_list_id", ""), + resource.TestCheckResourceAttr(resourceName, "egress_only_gateway_id", ""), + resource.TestCheckResourceAttrPair(resourceName, "gateway_id", igwResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "instance_id", ""), + resource.TestCheckResourceAttr(resourceName, "instance_owner_id", ""), + resource.TestCheckResourceAttr(resourceName, "nat_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "network_interface_id", ""), + resource.TestCheckResourceAttr(resourceName, "origin", ec2.RouteOriginCreateRoute), + resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateActive), + resource.TestCheckResourceAttr(resourceName, "transit_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "vpc_peering_connection_id", ""), + ), + }, + { + Config: testAccAWSRouteConfigIpv4FlexiTarget(rName, destinationCidr, "nat_gateway_id", ngwResourceName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSRouteExists(resourceName, &route), + resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", destinationCidr), + resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), + resource.TestCheckResourceAttr(resourceName, "destination_prefix_list_id", ""), + resource.TestCheckResourceAttr(resourceName, "egress_only_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "instance_id", ""), + resource.TestCheckResourceAttr(resourceName, "instance_owner_id", ""), + resource.TestCheckResourceAttrPair(resourceName, "nat_gateway_id", ngwResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "network_interface_id", ""), + resource.TestCheckResourceAttr(resourceName, "origin", ec2.RouteOriginCreateRoute), + resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateActive), + resource.TestCheckResourceAttr(resourceName, "transit_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "vpc_peering_connection_id", ""), + ), + }, + { + Config: testAccAWSRouteConfigIpv4FlexiTarget(rName, destinationCidr, "network_interface_id", eniResourceName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSRouteExists(resourceName, &route), + resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", destinationCidr), + resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), + resource.TestCheckResourceAttr(resourceName, "destination_prefix_list_id", ""), + resource.TestCheckResourceAttr(resourceName, "egress_only_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "instance_id", ""), + resource.TestCheckResourceAttr(resourceName, "instance_owner_id", ""), + resource.TestCheckResourceAttr(resourceName, "nat_gateway_id", ""), + resource.TestCheckResourceAttrPair(resourceName, "network_interface_id", eniResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "origin", ec2.RouteOriginCreateRoute), + resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateBlackhole), + resource.TestCheckResourceAttr(resourceName, "transit_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "vpc_peering_connection_id", ""), + ), + }, + { + Config: testAccAWSRouteConfigIpv4FlexiTarget(rName, destinationCidr, "transit_gateway_id", tgwResourceName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSRouteExists(resourceName, &route), + resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", destinationCidr), + resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), + resource.TestCheckResourceAttr(resourceName, "destination_prefix_list_id", ""), + resource.TestCheckResourceAttr(resourceName, "egress_only_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "instance_id", ""), + resource.TestCheckResourceAttr(resourceName, "instance_owner_id", ""), + resource.TestCheckResourceAttr(resourceName, "nat_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "network_interface_id", ""), + resource.TestCheckResourceAttr(resourceName, "origin", ec2.RouteOriginCreateRoute), + resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateActive), + resource.TestCheckResourceAttrPair(resourceName, "transit_gateway_id", tgwResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "vpc_peering_connection_id", ""), + ), + }, + { + Config: testAccAWSRouteConfigIpv4FlexiTarget(rName, destinationCidr, "vpc_peering_connection_id", pcxResourceName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSRouteExists(resourceName, &route), + resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", destinationCidr), + resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), + resource.TestCheckResourceAttr(resourceName, "destination_prefix_list_id", ""), + resource.TestCheckResourceAttr(resourceName, "egress_only_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "instance_id", ""), + resource.TestCheckResourceAttr(resourceName, "instance_owner_id", ""), + resource.TestCheckResourceAttr(resourceName, "nat_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "network_interface_id", ""), + resource.TestCheckResourceAttr(resourceName, "origin", ec2.RouteOriginCreateRoute), + resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateActive), + resource.TestCheckResourceAttr(resourceName, "transit_gateway_id", ""), + resource.TestCheckResourceAttrPair(resourceName, "vpc_peering_connection_id", pcxResourceName, "id"), + ), + }, + { + Config: testAccAWSRouteConfigIpv4FlexiTarget(rName, destinationCidr, "gateway_id", vgwResourceName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSRouteExists(resourceName, &route), + resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", destinationCidr), + resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), + resource.TestCheckResourceAttr(resourceName, "destination_prefix_list_id", ""), + resource.TestCheckResourceAttr(resourceName, "egress_only_gateway_id", ""), + resource.TestCheckResourceAttrPair(resourceName, "gateway_id", vgwResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "instance_id", ""), + resource.TestCheckResourceAttr(resourceName, "instance_owner_id", ""), + resource.TestCheckResourceAttr(resourceName, "nat_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "network_interface_id", ""), + resource.TestCheckResourceAttr(resourceName, "origin", ec2.RouteOriginCreateRoute), + resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateActive), + resource.TestCheckResourceAttr(resourceName, "transit_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "vpc_peering_connection_id", ""), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateIdFunc: testAccAWSRouteImportStateIdFunc(resourceName), + ImportStateVerify: true, + }, + }, + }) +} + func testAccCheckAWSRouteExists(n string, res *ec2.Route) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] @@ -1672,3 +1833,144 @@ resource "aws_route" "test" { } `, rName, destinationCidr) } + +func testAccAWSRouteConfigIpv4FlexiTarget(rName, destinationCidr, targetAttribute, targetValue string) string { + return composeConfig( + testAccLatestAmazonLinuxHvmEbsAmiConfig(), + testAccAvailableEc2InstanceTypeForRegion("t3.micro", "t2.micro"), + fmt.Sprintf(` +data "aws_availability_zones" "current" { + # Exclude usw2-az4 (us-west-2d) as it has limited instance types. + # IncorrectState: Transit Gateway is not available in availability zone us-west-2d + exclude_zone_ids = ["usw2-az4"] + state = "available" + + filter { + name = "opt-in-status" + values = ["opt-in-not-required"] + } +} + +resource "aws_vpc" "test" { + cidr_block = "10.1.0.0/16" + + tags = { + Name = %[1]q + } +} + +resource "aws_vpn_gateway" "test" { + vpc_id = aws_vpc.test.id + + tags = { + Name = %[1]q + } +} + +resource "aws_internet_gateway" "test" { + vpc_id = aws_vpc.test.id + + tags = { + Name = %[1]q + } +} + +resource "aws_subnet" "test" { + cidr_block = "10.1.1.0/24" + vpc_id = aws_vpc.test.id + availability_zone = data.aws_availability_zones.current.names[0] + + map_public_ip_on_launch = true + + tags = { + Name = %[1]q + } +} + +resource "aws_instance" "test" { + ami = data.aws_ami.amzn-ami-minimal-hvm-ebs.id + instance_type = data.aws_ec2_instance_type_offering.available.instance_type + subnet_id = aws_subnet.test.id + + tags = { + Name = %[1]q + } +} + +resource "aws_ec2_transit_gateway" "test" { + tags = { + Name = %[1]q + } +} + +resource "aws_ec2_transit_gateway_vpc_attachment" "test" { + subnet_ids = [aws_subnet.test.id] + transit_gateway_id = aws_ec2_transit_gateway.test.id + vpc_id = aws_vpc.test.id + + tags = { + Name = %[1]q + } +} + +resource "aws_network_interface" "test" { + subnet_id = aws_subnet.test.id + + tags = { + Name = %[1]q + } +} + +resource "aws_vpc" "target" { + cidr_block = "10.0.0.0/16" + + tags = { + Name = %[1]q + } +} + +resource "aws_vpc_peering_connection" "test" { + vpc_id = aws_vpc.test.id + peer_vpc_id = aws_vpc.target.id + auto_accept = true + + tags = { + Name = %[1]q + } +} + +resource "aws_eip" "test" { + vpc = true + + tags = { + Name = %[1]q + } +} + +resource "aws_nat_gateway" "test" { + allocation_id = aws_eip.test.id + subnet_id = aws_subnet.test.id + + tags = { + Name = %[1]q + } + + depends_on = [aws_internet_gateway.test] +} + +resource "aws_route_table" "test" { + vpc_id = aws_vpc.test.id + + tags = { + Name = %[1]q + } +} + +resource "aws_route" "test" { + route_table_id = aws_route_table.test.id + destination_cidr_block = %[2]q + + %[3]s = %[4]s.id +} +`, rName, destinationCidr, targetAttribute, targetValue)) +} From 9d401789a0546fc4b2c8d3cc93bf862a22d7e1c4 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Sun, 28 Jun 2020 16:50:08 -0400 Subject: [PATCH 29/40] r/aws_route: Add 'TestAccAWSRoute_IPv6_Update_Target'. Currently fails. Acceptance test output: $ make testacc TEST=./aws/ TESTARGS='-run=TestAccAWSRoute_IPv6_Update_Target' ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws/ -v -count 1 -parallel 20 -run=TestAccAWSRoute_IPv6_Update_Target -timeout 120m === RUN TestAccAWSRoute_IPv6_Update_Target === PAUSE TestAccAWSRoute_IPv6_Update_Target === CONT TestAccAWSRoute_IPv6_Update_Target --- FAIL: TestAccAWSRoute_IPv6_Update_Target (152.32s) testing.go:684: Step 1 error: errors during apply: Error: Error: more than 1 target specified. Only 1 of gateway_id, egress_only_gateway_id, nat_gateway_id, instance_id, network_interface_id or vpc_peering_connection_id is allowed. on /tmp/tf-test007003987/main.tf line 131: (source code not available) FAIL FAIL github.com/terraform-providers/terraform-provider-aws/aws 152.371s FAIL GNUmakefile:26: recipe for target 'testacc' failed make: *** [testacc] Error 1 --- aws/resource_aws_route_test.go | 260 +++++++++++++++++++++++++++++++++ 1 file changed, 260 insertions(+) diff --git a/aws/resource_aws_route_test.go b/aws/resource_aws_route_test.go index cd03ac543cfe..fe728d8698ff 100644 --- a/aws/resource_aws_route_test.go +++ b/aws/resource_aws_route_test.go @@ -943,6 +943,147 @@ func TestAccAWSRoute_IPv4_Update_Target(t *testing.T) { }) } +func TestAccAWSRoute_IPv6_Update_Target(t *testing.T) { + var route ec2.Route + resourceName := "aws_route.test" + vgwResourceName := "aws_vpn_gateway.test" + instanceResourceName := "aws_instance.test" + igwResourceName := "aws_internet_gateway.test" + eniResourceName := "aws_network_interface.test" + pcxResourceName := "aws_vpc_peering_connection.test" + eoigwResourceName := "aws_egress_only_internet_gateway.test" + rName := acctest.RandomWithPrefix("tf-acc-test") + destinationCidr := "::/0" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSRouteDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSRouteConfigIpv6FlexiTarget(rName, destinationCidr, "instance_id", instanceResourceName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSRouteExists(resourceName, &route), + resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", ""), + resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", destinationCidr), + resource.TestCheckResourceAttr(resourceName, "destination_prefix_list_id", ""), + resource.TestCheckResourceAttr(resourceName, "egress_only_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "gateway_id", ""), + resource.TestCheckResourceAttrPair(resourceName, "instance_id", instanceResourceName, "id"), + testAccCheckResourceAttrAccountID(resourceName, "instance_owner_id"), + resource.TestCheckResourceAttr(resourceName, "nat_gateway_id", ""), + resource.TestCheckResourceAttrPair(resourceName, "network_interface_id", instanceResourceName, "primary_network_interface_id"), + resource.TestCheckResourceAttr(resourceName, "origin", ec2.RouteOriginCreateRoute), + resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateActive), + resource.TestCheckResourceAttr(resourceName, "transit_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "vpc_peering_connection_id", ""), + ), + }, + { + Config: testAccAWSRouteConfigIpv6FlexiTarget(rName, destinationCidr, "gateway_id", igwResourceName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSRouteExists(resourceName, &route), + resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", ""), + resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", destinationCidr), + resource.TestCheckResourceAttr(resourceName, "destination_prefix_list_id", ""), + resource.TestCheckResourceAttr(resourceName, "egress_only_gateway_id", ""), + resource.TestCheckResourceAttrPair(resourceName, "gateway_id", igwResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "instance_id", ""), + resource.TestCheckResourceAttr(resourceName, "instance_owner_id", ""), + resource.TestCheckResourceAttr(resourceName, "nat_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "network_interface_id", ""), + resource.TestCheckResourceAttr(resourceName, "origin", ec2.RouteOriginCreateRoute), + resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateActive), + resource.TestCheckResourceAttr(resourceName, "transit_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "vpc_peering_connection_id", ""), + ), + }, + { + Config: testAccAWSRouteConfigIpv6FlexiTarget(rName, destinationCidr, "egress_only_gateway_id", eoigwResourceName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSRouteExists(resourceName, &route), + resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", ""), + resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", destinationCidr), + resource.TestCheckResourceAttr(resourceName, "destination_prefix_list_id", ""), + resource.TestCheckResourceAttrPair(resourceName, "egress_only_gateway_id", eoigwResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "instance_id", ""), + resource.TestCheckResourceAttr(resourceName, "instance_owner_id", ""), + resource.TestCheckResourceAttr(resourceName, "nat_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "network_interface_id", ""), + resource.TestCheckResourceAttr(resourceName, "origin", ec2.RouteOriginCreateRoute), + resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateActive), + resource.TestCheckResourceAttr(resourceName, "transit_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "vpc_peering_connection_id", ""), + ), + }, + { + Config: testAccAWSRouteConfigIpv6FlexiTarget(rName, destinationCidr, "network_interface_id", eniResourceName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSRouteExists(resourceName, &route), + resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", ""), + resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", destinationCidr), + resource.TestCheckResourceAttr(resourceName, "destination_prefix_list_id", ""), + resource.TestCheckResourceAttr(resourceName, "egress_only_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "instance_id", ""), + resource.TestCheckResourceAttr(resourceName, "instance_owner_id", ""), + resource.TestCheckResourceAttr(resourceName, "nat_gateway_id", ""), + resource.TestCheckResourceAttrPair(resourceName, "network_interface_id", eniResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "origin", ec2.RouteOriginCreateRoute), + resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateBlackhole), + resource.TestCheckResourceAttr(resourceName, "transit_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "vpc_peering_connection_id", ""), + ), + }, + { + Config: testAccAWSRouteConfigIpv6FlexiTarget(rName, destinationCidr, "vpc_peering_connection_id", pcxResourceName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSRouteExists(resourceName, &route), + resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", ""), + resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", destinationCidr), + resource.TestCheckResourceAttr(resourceName, "destination_prefix_list_id", ""), + resource.TestCheckResourceAttr(resourceName, "egress_only_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "instance_id", ""), + resource.TestCheckResourceAttr(resourceName, "instance_owner_id", ""), + resource.TestCheckResourceAttr(resourceName, "nat_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "network_interface_id", ""), + resource.TestCheckResourceAttr(resourceName, "origin", ec2.RouteOriginCreateRoute), + resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateActive), + resource.TestCheckResourceAttr(resourceName, "transit_gateway_id", ""), + resource.TestCheckResourceAttrPair(resourceName, "vpc_peering_connection_id", pcxResourceName, "id"), + ), + }, + { + Config: testAccAWSRouteConfigIpv6FlexiTarget(rName, destinationCidr, "gateway_id", vgwResourceName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSRouteExists(resourceName, &route), + resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", ""), + resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", destinationCidr), + resource.TestCheckResourceAttr(resourceName, "destination_prefix_list_id", ""), + resource.TestCheckResourceAttr(resourceName, "egress_only_gateway_id", ""), + resource.TestCheckResourceAttrPair(resourceName, "gateway_id", vgwResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "instance_id", ""), + resource.TestCheckResourceAttr(resourceName, "instance_owner_id", ""), + resource.TestCheckResourceAttr(resourceName, "nat_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "network_interface_id", ""), + resource.TestCheckResourceAttr(resourceName, "origin", ec2.RouteOriginCreateRoute), + resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateActive), + resource.TestCheckResourceAttr(resourceName, "transit_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "vpc_peering_connection_id", ""), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateIdFunc: testAccAWSRouteImportStateIdFunc(resourceName), + ImportStateVerify: true, + }, + }, + }) +} + func testAccCheckAWSRouteExists(n string, res *ec2.Route) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] @@ -1974,3 +2115,122 @@ resource "aws_route" "test" { } `, rName, destinationCidr, targetAttribute, targetValue)) } + +func testAccAWSRouteConfigIpv6FlexiTarget(rName, destinationCidr, targetAttribute, targetValue string) string { + return composeConfig( + testAccLatestAmazonLinuxHvmEbsAmiConfig(), + testAccAvailableEc2InstanceTypeForRegion("t3.micro", "t2.micro"), + fmt.Sprintf(` +data "aws_availability_zones" "current" { + # Exclude usw2-az4 (us-west-2d) as it has limited instance types. + # IncorrectState: Transit Gateway is not available in availability zone us-west-2d + exclude_zone_ids = ["usw2-az4"] + state = "available" + + filter { + name = "opt-in-status" + values = ["opt-in-not-required"] + } +} + +resource "aws_vpc" "test" { + cidr_block = "10.1.0.0/16" + assign_generated_ipv6_cidr_block = true + + tags = { + Name = %[1]q + } +} + +resource "aws_vpn_gateway" "test" { + vpc_id = aws_vpc.test.id + + tags = { + Name = %[1]q + } +} + +resource "aws_internet_gateway" "test" { + vpc_id = aws_vpc.test.id + + tags = { + Name = %[1]q + } +} + +resource "aws_subnet" "test" { + cidr_block = "10.1.1.0/24" + vpc_id = aws_vpc.test.id + availability_zone = data.aws_availability_zones.current.names[0] + ipv6_cidr_block = cidrsubnet(aws_vpc.test.ipv6_cidr_block, 8, 1) + + map_public_ip_on_launch = true + + tags = { + Name = %[1]q + } +} + +resource "aws_instance" "test" { + ami = data.aws_ami.amzn-ami-minimal-hvm-ebs.id + instance_type = data.aws_ec2_instance_type_offering.available.instance_type + subnet_id = aws_subnet.test.id + + ipv6_address_count = 1 + + tags = { + Name = %[1]q + } +} + +resource "aws_egress_only_internet_gateway" "test" { + vpc_id = aws_vpc.test.id + + tags = { + Name = %[1]q + } +} + +resource "aws_network_interface" "test" { + subnet_id = aws_subnet.test.id + + tags = { + Name = %[1]q + } +} + +resource "aws_vpc" "target" { + cidr_block = "10.0.0.0/16" + assign_generated_ipv6_cidr_block = true + + tags = { + Name = %[1]q + } +} + +resource "aws_vpc_peering_connection" "test" { + vpc_id = aws_vpc.test.id + peer_vpc_id = aws_vpc.target.id + auto_accept = true + + tags = { + Name = %[1]q + } +} + +resource "aws_route_table" "test" { + vpc_id = aws_vpc.test.id + + tags = { + Name = %[1]q + } +} + +resource "aws_route" "test" { + route_table_id = aws_route_table.test.id + destination_ipv6_cidr_block = %[2]q + + %[3]s = %[4]s.id +} +`, rName, destinationCidr, targetAttribute, targetValue)) +} From 3c1ccbef66a4bffeebca196652a04ce569184ffb Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 1 Jul 2020 18:46:47 -0400 Subject: [PATCH 30/40] r/aws_route: Better validation. Acceptance test output (failures expected): $ make testacc TEST=./aws/ TESTARGS='-run=TestAccAWSRoute_' ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws/ -v -count 1 -parallel 2 -run=TestAccAWSRoute_ -timeout 120m === RUN TestAccAWSRoute_basic === PAUSE TestAccAWSRoute_basic === RUN TestAccAWSRoute_disappears === PAUSE TestAccAWSRoute_disappears === RUN TestAccAWSRoute_routeTableDisappears === PAUSE TestAccAWSRoute_routeTableDisappears === RUN TestAccAWSRoute_IPv6_To_EgressOnlyInternetGateway === PAUSE TestAccAWSRoute_IPv6_To_EgressOnlyInternetGateway === RUN TestAccAWSRoute_IPv6_To_InternetGateway === PAUSE TestAccAWSRoute_IPv6_To_InternetGateway === RUN TestAccAWSRoute_IPv6_To_Instance === PAUSE TestAccAWSRoute_IPv6_To_Instance === RUN TestAccAWSRoute_IPv6_To_NetworkInterface === PAUSE TestAccAWSRoute_IPv6_To_NetworkInterface === RUN TestAccAWSRoute_IPv6_To_VpcPeeringConnection === PAUSE TestAccAWSRoute_IPv6_To_VpcPeeringConnection === RUN TestAccAWSRoute_IPv6_To_VpnGateway === PAUSE TestAccAWSRoute_IPv6_To_VpnGateway === RUN TestAccAWSRoute_IPv4_To_VpnGateway === PAUSE TestAccAWSRoute_IPv4_To_VpnGateway === RUN TestAccAWSRoute_IPv4_To_Instance === PAUSE TestAccAWSRoute_IPv4_To_Instance === RUN TestAccAWSRoute_IPv4_To_NetworkInterface === PAUSE TestAccAWSRoute_IPv4_To_NetworkInterface === RUN TestAccAWSRoute_IPv4_To_VpcPeeringConnection === PAUSE TestAccAWSRoute_IPv4_To_VpcPeeringConnection === RUN TestAccAWSRoute_IPv4_To_NatGateway === PAUSE TestAccAWSRoute_IPv4_To_NatGateway === RUN TestAccAWSRoute_DoesNotCrashWithVpcEndpoint === PAUSE TestAccAWSRoute_DoesNotCrashWithVpcEndpoint === RUN TestAccAWSRoute_IPv4_To_TransitGateway === PAUSE TestAccAWSRoute_IPv4_To_TransitGateway === RUN TestAccAWSRoute_ConditionalCidrBlock === PAUSE TestAccAWSRoute_ConditionalCidrBlock === RUN TestAccAWSRoute_IPv4_Update_Target === PAUSE TestAccAWSRoute_IPv4_Update_Target === RUN TestAccAWSRoute_IPv6_Update_Target === PAUSE TestAccAWSRoute_IPv6_Update_Target === CONT TestAccAWSRoute_basic === CONT TestAccAWSRoute_IPv6_Update_Target --- PASS: TestAccAWSRoute_basic (52.56s) === CONT TestAccAWSRoute_IPv4_Update_Target --- FAIL: TestAccAWSRoute_IPv6_Update_Target (101.24s) testing.go:684: Step 1 error: errors during apply: Error: Error: more than 1 target specified. Only 1 of gateway_id, egress_only_gateway_id, nat_gateway_id, instance_id, network_interface_id or vpc_peering_connection_id is allowed. on /tmp/tf-test041809885/main.tf line 131: (source code not available) === CONT TestAccAWSRoute_ConditionalCidrBlock --- PASS: TestAccAWSRoute_ConditionalCidrBlock (77.26s) === CONT TestAccAWSRoute_IPv4_To_TransitGateway --- FAIL: TestAccAWSRoute_IPv4_Update_Target (370.49s) testing.go:684: Step 1 error: errors during apply: Error: Error: more than 1 target specified. Only 1 of gateway_id, egress_only_gateway_id, nat_gateway_id, instance_id, network_interface_id or vpc_peering_connection_id is allowed. on /tmp/tf-test640007973/main.tf line 153: (source code not available) === CONT TestAccAWSRoute_DoesNotCrashWithVpcEndpoint --- PASS: TestAccAWSRoute_DoesNotCrashWithVpcEndpoint (62.59s) === CONT TestAccAWSRoute_IPv4_To_NatGateway --- PASS: TestAccAWSRoute_IPv4_To_TransitGateway (357.58s) === CONT TestAccAWSRoute_IPv4_To_VpcPeeringConnection --- PASS: TestAccAWSRoute_IPv4_To_VpcPeeringConnection (42.14s) === CONT TestAccAWSRoute_IPv4_To_NetworkInterface --- PASS: TestAccAWSRoute_IPv4_To_NetworkInterface (48.03s) === CONT TestAccAWSRoute_IPv4_To_Instance --- PASS: TestAccAWSRoute_IPv4_To_NatGateway (205.87s) === CONT TestAccAWSRoute_IPv4_To_VpnGateway --- PASS: TestAccAWSRoute_IPv4_To_Instance (97.35s) === CONT TestAccAWSRoute_IPv6_To_VpnGateway --- PASS: TestAccAWSRoute_IPv4_To_VpnGateway (53.36s) === CONT TestAccAWSRoute_IPv6_To_VpcPeeringConnection --- PASS: TestAccAWSRoute_IPv6_To_VpnGateway (62.11s) === CONT TestAccAWSRoute_IPv6_To_NetworkInterface --- PASS: TestAccAWSRoute_IPv6_To_VpcPeeringConnection (41.51s) === CONT TestAccAWSRoute_IPv6_To_Instance --- PASS: TestAccAWSRoute_IPv6_To_NetworkInterface (48.70s) === CONT TestAccAWSRoute_IPv6_To_InternetGateway --- PASS: TestAccAWSRoute_IPv6_To_InternetGateway (52.58s) === CONT TestAccAWSRoute_IPv6_To_EgressOnlyInternetGateway --- PASS: TestAccAWSRoute_IPv6_To_Instance (119.70s) === CONT TestAccAWSRoute_routeTableDisappears --- PASS: TestAccAWSRoute_IPv6_To_EgressOnlyInternetGateway (60.46s) === CONT TestAccAWSRoute_disappears --- PASS: TestAccAWSRoute_routeTableDisappears (48.52s) --- PASS: TestAccAWSRoute_disappears (47.95s) FAIL FAIL github.com/terraform-providers/terraform-provider-aws/aws 995.477s FAIL GNUmakefile:26: recipe for target 'testacc' failed make: *** [testacc] Error 1 --- aws/resource_aws_route.go | 416 +++++++++++++++++++++++--------------- 1 file changed, 251 insertions(+), 165 deletions(-) diff --git a/aws/resource_aws_route.go b/aws/resource_aws_route.go index 7abbf78c4187..39db1a1ca61e 100644 --- a/aws/resource_aws_route.go +++ b/aws/resource_aws_route.go @@ -144,125 +144,57 @@ func resourceAwsRoute() *schema.Resource { func resourceAwsRouteCreate(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).ec2conn - var numTargets int - var setTarget string - allowedTargets := []string{ - "egress_only_gateway_id", - "gateway_id", - "nat_gateway_id", - "instance_id", - "network_interface_id", - "transit_gateway_id", - "vpc_peering_connection_id", - } - // Check if more than 1 target is specified - for _, target := range allowedTargets { - if len(d.Get(target).(string)) > 0 { - numTargets++ - setTarget = target - } + destinationAttr, targetAttr, err := routeDestinationAndTargetAttributes(d) + if err != nil { + return err } - if numTargets > 1 { - return routeTargetValidationError + routeTableID := d.Get("route_table_id").(string) + input := &ec2.CreateRouteInput{ + RouteTableId: aws.String(routeTableID), } - createOpts := &ec2.CreateRouteInput{} - // Formulate CreateRouteInput based on the target type - switch setTarget { - case "gateway_id": - createOpts = &ec2.CreateRouteInput{ - RouteTableId: aws.String(d.Get("route_table_id").(string)), - GatewayId: aws.String(d.Get("gateway_id").(string)), - } - - if v, ok := d.GetOk("destination_cidr_block"); ok { - createOpts.DestinationCidrBlock = aws.String(v.(string)) - } - - if v, ok := d.GetOk("destination_ipv6_cidr_block"); ok { - createOpts.DestinationIpv6CidrBlock = aws.String(v.(string)) - } + var pDestination **string + var routeReader func(*ec2.EC2, string, string) (*ec2.Route, error) + switch destinationAttr { + case "destination_cidr_block": + pDestination = &input.DestinationCidrBlock + routeReader = readIpv4Route + case "destination_ipv6_cidr_block": + pDestination = &input.DestinationIpv6CidrBlock + routeReader = readIpv6Route + default: + return fmt.Errorf("unexpected destination attribute: `%s`", destinationAttr) + } + destination := d.Get(destinationAttr).(string) + *pDestination = aws.String(destination) + var pTarget **string + switch targetAttr { case "egress_only_gateway_id": - createOpts = &ec2.CreateRouteInput{ - RouteTableId: aws.String(d.Get("route_table_id").(string)), - DestinationIpv6CidrBlock: aws.String(d.Get("destination_ipv6_cidr_block").(string)), - EgressOnlyInternetGatewayId: aws.String(d.Get("egress_only_gateway_id").(string)), - } - case "nat_gateway_id": - createOpts = &ec2.CreateRouteInput{ - RouteTableId: aws.String(d.Get("route_table_id").(string)), - DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)), - NatGatewayId: aws.String(d.Get("nat_gateway_id").(string)), - } + pTarget = &input.EgressOnlyInternetGatewayId + case "gateway_id": + pTarget = &input.GatewayId case "instance_id": - createOpts = &ec2.CreateRouteInput{ - RouteTableId: aws.String(d.Get("route_table_id").(string)), - InstanceId: aws.String(d.Get("instance_id").(string)), - } - - if v, ok := d.GetOk("destination_cidr_block"); ok { - createOpts.DestinationCidrBlock = aws.String(v.(string)) - } - - if v, ok := d.GetOk("destination_ipv6_cidr_block"); ok { - createOpts.DestinationIpv6CidrBlock = aws.String(v.(string)) - } - + pTarget = &input.InstanceId + case "nat_gateway_id": + pTarget = &input.NatGatewayId case "network_interface_id": - createOpts = &ec2.CreateRouteInput{ - RouteTableId: aws.String(d.Get("route_table_id").(string)), - NetworkInterfaceId: aws.String(d.Get("network_interface_id").(string)), - } - - if v, ok := d.GetOk("destination_cidr_block"); ok { - createOpts.DestinationCidrBlock = aws.String(v.(string)) - } - - if v, ok := d.GetOk("destination_ipv6_cidr_block"); ok { - createOpts.DestinationIpv6CidrBlock = aws.String(v.(string)) - } - + pTarget = &input.NetworkInterfaceId case "transit_gateway_id": - createOpts = &ec2.CreateRouteInput{ - RouteTableId: aws.String(d.Get("route_table_id").(string)), - TransitGatewayId: aws.String(d.Get("transit_gateway_id").(string)), - } - - if v, ok := d.GetOk("destination_cidr_block"); ok { - createOpts.DestinationCidrBlock = aws.String(v.(string)) - } - - if v, ok := d.GetOk("destination_ipv6_cidr_block"); ok { - createOpts.DestinationIpv6CidrBlock = aws.String(v.(string)) - } - + pTarget = &input.TransitGatewayId case "vpc_peering_connection_id": - createOpts = &ec2.CreateRouteInput{ - RouteTableId: aws.String(d.Get("route_table_id").(string)), - VpcPeeringConnectionId: aws.String(d.Get("vpc_peering_connection_id").(string)), - } - - if v, ok := d.GetOk("destination_cidr_block"); ok { - createOpts.DestinationCidrBlock = aws.String(v.(string)) - } - - if v, ok := d.GetOk("destination_ipv6_cidr_block"); ok { - createOpts.DestinationIpv6CidrBlock = aws.String(v.(string)) - } - + pTarget = &input.VpcPeeringConnectionId default: - return fmt.Errorf("A valid target type is missing. Specify one of the following attributes: %s", strings.Join(allowedTargets, ", ")) + return fmt.Errorf("unexpected target attribute: `%s`", targetAttr) } - log.Printf("[DEBUG] Route create config: %s", createOpts) + *pTarget = aws.String(d.Get(targetAttr).(string)) - // Create the route - var err error + log.Printf("[DEBUG] Creating Route: %s", input) err = resource.Retry(d.Timeout(schema.TimeoutCreate), func() *resource.RetryError { - _, err = conn.CreateRoute(createOpts) + _, err = conn.CreateRoute(input) if isAWSErr(err, "InvalidParameterException", "") { return resource.RetryableError(err) @@ -278,64 +210,43 @@ func resourceAwsRouteCreate(d *schema.ResourceData, meta interface{}) error { return nil }) + if isResourceTimeoutError(err) { - _, err = conn.CreateRoute(createOpts) + _, err = conn.CreateRoute(input) } + if err != nil { - return fmt.Errorf("Error creating route: %s", err) + return fmt.Errorf("error creating route: %s", err) } var route *ec2.Route + err = resource.Retry(d.Timeout(schema.TimeoutCreate), func() *resource.RetryError { + route, err = routeReader(conn, routeTableID, destination) - if v, ok := d.GetOk("destination_cidr_block"); ok { - err = resource.Retry(d.Timeout(schema.TimeoutCreate), func() *resource.RetryError { - route, err = resourceAwsRouteFindRoute(conn, d.Get("route_table_id").(string), v.(string), "") - if err == nil { - if route != nil { - return nil - } else { - err = errors.New("Route not found") - } - } - - return resource.RetryableError(err) - }) - if isResourceTimeoutError(err) { - route, err = resourceAwsRouteFindRoute(conn, d.Get("route_table_id").(string), v.(string), "") - } if err != nil { - return fmt.Errorf("Error finding route after creating it: %s", err) + return resource.RetryableError(err) } + if route == nil { - return fmt.Errorf("Unable to find matching route for Route Table (%s) and destination CIDR block (%s).", d.Get("route_table_id").(string), v) + return resource.RetryableError(fmt.Errorf("route not found")) } + + return nil + }) + + if isResourceTimeoutError(err) { + route, err = routeReader(conn, routeTableID, destination) } - if v, ok := d.GetOk("destination_ipv6_cidr_block"); ok { - err = resource.Retry(d.Timeout(schema.TimeoutCreate), func() *resource.RetryError { - route, err = resourceAwsRouteFindRoute(conn, d.Get("route_table_id").(string), "", v.(string)) - if err == nil { - if route != nil { - return nil - } else { - err = errors.New("Route not found") - } - } + if err != nil { + return fmt.Errorf("error reading route for Route Table (%s) with destination (%s): %s", routeTableID, destination, err) + } - return resource.RetryableError(err) - }) - if isResourceTimeoutError(err) { - route, err = resourceAwsRouteFindRoute(conn, d.Get("route_table_id").(string), "", v.(string)) - } - if err != nil { - return fmt.Errorf("Error finding route after creating it: %s", err) - } - if route == nil { - return fmt.Errorf("Unable to find matching route for Route Table (%s) and destination IPv6 CIDR block (%s).", d.Get("route_table_id").(string), v) - } + if route == nil { + return fmt.Errorf("route in Route Table (%s) with destination (%s) not found", routeTableID, destination) } - d.SetId(resourceAwsRouteID(d, route)) + d.SetId(routeCreateID(routeTableID, destination)) return resourceAwsRouteRead(d, meta) } @@ -343,22 +254,35 @@ func resourceAwsRouteCreate(d *schema.ResourceData, meta interface{}) error { func resourceAwsRouteRead(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).ec2conn - routeTableId := d.Get("route_table_id").(string) - destinationCidrBlock := d.Get("destination_cidr_block").(string) - destinationIpv6CidrBlock := d.Get("destination_ipv6_cidr_block").(string) + destinationAttr := routeDestinationAttr(d) + + routeTableID := d.Get("route_table_id").(string) + + var routeReader func(*ec2.EC2, string, string) (*ec2.Route, error) + switch destinationAttr { + case "destination_cidr_block": + routeReader = readIpv4Route + case "destination_ipv6_cidr_block": + routeReader = readIpv6Route + default: + return fmt.Errorf("unexpected destination attribute: `%s`", destinationAttr) + } + destination := d.Get(destinationAttr).(string) + + route, err := routeReader(conn, routeTableID, destination) - route, err := resourceAwsRouteFindRoute(conn, routeTableId, destinationCidrBlock, destinationIpv6CidrBlock) if isAWSErr(err, "InvalidRouteTableID.NotFound", "") { - log.Printf("[WARN] Route Table (%s) not found, removing from state", routeTableId) + log.Printf("[WARN] Route Table (%s) not found, removing from state", routeTableID) d.SetId("") return nil } + if err != nil { - return err + return fmt.Errorf("error reading route for Route Table (%s) with destination (%s): %s", routeTableID, destination, err) } if route == nil { - log.Printf("[WARN] Matching route not found, removing from state") + log.Printf("[WARN] Route in Route Table (%s) with destination (%s) not found, removing from state", routeTableID, destination) d.SetId("") return nil } @@ -474,21 +398,28 @@ func resourceAwsRouteUpdate(d *schema.ResourceData, meta interface{}) error { func resourceAwsRouteDelete(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).ec2conn - deleteOpts := &ec2.DeleteRouteInput{ - RouteTableId: aws.String(d.Get("route_table_id").(string)), - } - if v, ok := d.GetOk("destination_cidr_block"); ok { - deleteOpts.DestinationCidrBlock = aws.String(v.(string)) + destinationAttr := routeDestinationAttr(d) + + routeTableID := d.Get("route_table_id").(string) + input := &ec2.DeleteRouteInput{ + RouteTableId: aws.String(routeTableID), } - if v, ok := d.GetOk("destination_ipv6_cidr_block"); ok { - deleteOpts.DestinationIpv6CidrBlock = aws.String(v.(string)) + + var pDestination **string + switch destinationAttr { + case "destination_cidr_block": + pDestination = &input.DestinationCidrBlock + case "destination_ipv6_cidr_block": + pDestination = &input.DestinationIpv6CidrBlock + default: + return fmt.Errorf("unexpected destination attribute: `%s`", destinationAttr) } - log.Printf("[DEBUG] Route delete opts: %s", deleteOpts) + destination := d.Get(destinationAttr).(string) + *pDestination = aws.String(destination) err := resource.Retry(d.Timeout(schema.TimeoutDelete), func() *resource.RetryError { - log.Printf("[DEBUG] Trying to delete route with opts %s", deleteOpts) - var err error - _, err = conn.DeleteRoute(deleteOpts) + log.Printf("[DEBUG] Deleting route (%s)", d.Id()) + _, err := conn.DeleteRoute(input) if err == nil { return nil } @@ -503,15 +434,20 @@ func resourceAwsRouteDelete(d *schema.ResourceData, meta interface{}) error { return resource.NonRetryableError(err) }) + if isResourceTimeoutError(err) { - _, err = conn.DeleteRoute(deleteOpts) + log.Printf("[DEBUG] Deleting route (%s)", d.Id()) + _, err = conn.DeleteRoute(input) } + if isAWSErr(err, "InvalidRoute.NotFound", "") { return nil } + if err != nil { - return fmt.Errorf("Error deleting route: %s", err) + return fmt.Errorf("error deleting route for Route Table (%s) with destination (%s): %s", routeTableID, destination, err) } + return nil } @@ -565,3 +501,153 @@ func resourceAwsRouteFindRoute(conn *ec2.EC2, rtbid string, cidr string, ipv6cid return nil, nil } + +// routeDestinationAttr return the route's destination attribute name. +// No validation is done. +func routeDestinationAttr(d *schema.ResourceData) string { + destinationAttrs := []string{"destination_cidr_block", "destination_ipv6_cidr_block"} + + for _, attr := range destinationAttrs { + if v := d.Get(attr).(string); v != "" { + return attr + } + } + + return "" +} + +// routeDestinationAndTargetAttributes return the route's destination and target attribute names. +// It also validates the resource, returning any validation error. +func routeDestinationAndTargetAttributes(d *schema.ResourceData) (string, string, error) { + destinationAttrs := map[string]struct { + ipv4Destination bool + ipv6Destination bool + }{ + "destination_cidr_block": {true, false}, + "destination_ipv6_cidr_block": {false, true}, + } + + destinationAttr := "" + ipv4Destination := false + ipv6Destination := false + for attr, kind := range destinationAttrs { + if v := d.Get(attr).(string); v != "" { + if destinationAttr != "" { + return "", "", fmt.Errorf("`%s` conflicts with `%s`", attr, destinationAttr) + } + + destinationAttr = attr + ipv4Destination = kind.ipv4Destination + ipv6Destination = kind.ipv6Destination + } + } + + if destinationAttr == "" { + keys := []string{} + for k := range destinationAttrs { + keys = append(keys, k) + } + + return "", "", fmt.Errorf("one of `%s` must be specified", strings.Join(keys, "`, `")) + } + + targetAttrs := map[string]struct { + ipv4Destination bool + ipv6Destination bool + }{ + "egress_only_gateway_id": {false, true}, + "gateway_id": {true, true}, + "instance_id": {true, true}, + "nat_gateway_id": {true, false}, + "network_interface_id": {true, true}, + "transit_gateway_id": {true, false}, + "vpc_peering_connection_id": {true, true}, + } + + targetAttr := "" + for attr, allowed := range targetAttrs { + if v := d.Get(attr).(string); v != "" { + if targetAttr != "" { + return "", "", fmt.Errorf("`%s` conflicts with `%s`", attr, targetAttr) + } + + if (ipv4Destination && !allowed.ipv4Destination) || (ipv6Destination && !allowed.ipv6Destination) { + return "", "", fmt.Errorf("`%s` not allowed for `%s` target", destinationAttr, attr) + } + + targetAttr = attr + } + } + + if targetAttr == "" { + keys := []string{} + for k := range targetAttrs { + keys = append(keys, k) + } + + return "", "", fmt.Errorf("one of `%s` must be specified", strings.Join(keys, "`, `")) + } + + return destinationAttr, targetAttr, nil +} + +// TODO +// TODO Move these to a per-service internal package and auto-generate where possible. +// TODO + +// readRouteTable returns the route table corresponding to the specified identifier. +// Returns nil if no route table is found. +func readRouteTable(conn *ec2.EC2, identifier string) (*ec2.RouteTable, error) { + input := &ec2.DescribeRouteTablesInput{ + RouteTableIds: aws.StringSlice([]string{identifier}), + } + + output, err := conn.DescribeRouteTables(input) + if err != nil { + return nil, err + } + + if len(output.RouteTables) == 0 || output.RouteTables[0] == nil { + return nil, nil + } + + return output.RouteTables[0], nil +} + +// readIpv4Route returns the route corresponding to the specified destination. +// Returns nil if no route is found. +func readIpv4Route(conn *ec2.EC2, routeTableID, destinationCidr string) (*ec2.Route, error) { + routeTable, err := readRouteTable(conn, routeTableID) + if err != nil { + return nil, err + } + + for _, route := range routeTable.Routes { + if aws.StringValue(route.DestinationCidrBlock) == destinationCidr { + return route, nil + } + } + + return nil, nil +} + +// readIpv6Route returns the route corresponding to the specified destination. +// Returns nil if no route is found. +func readIpv6Route(conn *ec2.EC2, routeTableID, destinationIpv6Cidr string) (*ec2.Route, error) { + routeTable, err := readRouteTable(conn, routeTableID) + if err != nil { + return nil, err + } + + for _, route := range routeTable.Routes { + if cidrBlocksEqual(aws.StringValue(route.DestinationIpv6CidrBlock), destinationIpv6Cidr) { + return route, nil + } + } + + return nil, nil +} + +func routeCreateID(routeTableID, destination string) string { + return fmt.Sprintf("r-%s%d", routeTableID, hashcode.String(destination)) +} From b35843d3eec3debe876707c5a4bfeba16aaf6d3c Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 3 Jul 2020 17:52:25 -0400 Subject: [PATCH 31/40] r/aws_route: Correctly handle route target updates. Acceptance test output: $ make testacc TEST=./aws/ TESTARGS='-run=TestAccAWSRoute_IPv4_Update_Target' ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws/ -v -count 1 -parallel 2 -run=TestAccAWSRoute_IPv4_Update_Target -timeout 120m === RUN TestAccAWSRoute_IPv4_Update_Target === PAUSE TestAccAWSRoute_IPv4_Update_Target === CONT TestAccAWSRoute_IPv4_Update_Target --- PASS: TestAccAWSRoute_IPv4_Update_Target (495.57s) PASS ok github.com/terraform-providers/terraform-provider-aws/aws 495.621s $ make testacc TEST=./aws/ TESTARGS='-run=TestAccAWSRoute_IPv6_Update_Target' ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws/ -v -count 1 -parallel 2 -run=TestAccAWSRoute_IPv6_Update_Target -timeout 120m === RUN TestAccAWSRoute_IPv6_Update_Target === PAUSE TestAccAWSRoute_IPv6_Update_Target === CONT TestAccAWSRoute_IPv6_Update_Target --- PASS: TestAccAWSRoute_IPv6_Update_Target (246.11s) PASS ok github.com/terraform-providers/terraform-provider-aws/aws 246.176s --- aws/data_source_aws_route.go | 11 ++ aws/resource_aws_route.go | 223 +++++++++------------------------ aws/resource_aws_route_test.go | 102 +++++++-------- 3 files changed, 126 insertions(+), 210 deletions(-) diff --git a/aws/data_source_aws_route.go b/aws/data_source_aws_route.go index 26ebc96405a4..a67731fcbb3b 100644 --- a/aws/data_source_aws_route.go +++ b/aws/data_source_aws_route.go @@ -5,6 +5,7 @@ import ( "log" "github.com/aws/aws-sdk-go/service/ec2" + "github.com/hashicorp/terraform-plugin-sdk/helper/hashcode" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" ) @@ -190,3 +191,13 @@ func getRoutes(table *ec2.RouteTable, d *schema.ResourceData) []*ec2.Route { } return routes } + +// Helper: Create an ID for a route +func resourceAwsRouteID(d *schema.ResourceData, r *ec2.Route) string { + + if r.DestinationIpv6CidrBlock != nil && *r.DestinationIpv6CidrBlock != "" { + return fmt.Sprintf("r-%s%d", d.Get("route_table_id").(string), hashcode.String(*r.DestinationIpv6CidrBlock)) + } + + return fmt.Sprintf("r-%s%d", d.Get("route_table_id").(string), hashcode.String(*r.DestinationCidrBlock)) +} diff --git a/aws/resource_aws_route.go b/aws/resource_aws_route.go index 39db1a1ca61e..748622b8bcfd 100644 --- a/aws/resource_aws_route.go +++ b/aws/resource_aws_route.go @@ -1,7 +1,6 @@ package aws import ( - "errors" "fmt" "log" "strings" @@ -15,12 +14,6 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/helper/validation" ) -// How long to sleep if a limit-exceeded event happens -var routeTargetValidationError = errors.New("Error: more than 1 target specified. Only 1 of gateway_id, " + - "egress_only_gateway_id, nat_gateway_id, instance_id, network_interface_id or " + - "vpc_peering_connection_id is allowed.") - -// AWS Route resource Schema declaration func resourceAwsRoute() *schema.Resource { return &schema.Resource{ Create: resourceAwsRouteCreate, @@ -150,46 +143,44 @@ func resourceAwsRouteCreate(d *schema.ResourceData, meta interface{}) error { return err } + destination := d.Get(destinationAttr).(string) routeTableID := d.Get("route_table_id").(string) input := &ec2.CreateRouteInput{ RouteTableId: aws.String(routeTableID), } - var pDestination **string var routeReader func(*ec2.EC2, string, string) (*ec2.Route, error) + switch destinationAttr { case "destination_cidr_block": - pDestination = &input.DestinationCidrBlock + input.DestinationCidrBlock = aws.String(destination) routeReader = readIpv4Route case "destination_ipv6_cidr_block": - pDestination = &input.DestinationIpv6CidrBlock + input.DestinationIpv6CidrBlock = aws.String(destination) routeReader = readIpv6Route default: return fmt.Errorf("unexpected destination attribute: `%s`", destinationAttr) } - destination := d.Get(destinationAttr).(string) - *pDestination = aws.String(destination) - var pTarget **string + target := aws.String(d.Get(targetAttr).(string)) switch targetAttr { case "egress_only_gateway_id": - pTarget = &input.EgressOnlyInternetGatewayId + input.EgressOnlyInternetGatewayId = target case "gateway_id": - pTarget = &input.GatewayId + input.GatewayId = target case "instance_id": - pTarget = &input.InstanceId + input.InstanceId = target case "nat_gateway_id": - pTarget = &input.NatGatewayId + input.NatGatewayId = target case "network_interface_id": - pTarget = &input.NetworkInterfaceId + input.NetworkInterfaceId = target case "transit_gateway_id": - pTarget = &input.TransitGatewayId + input.TransitGatewayId = target case "vpc_peering_connection_id": - pTarget = &input.VpcPeeringConnectionId + input.VpcPeeringConnectionId = target default: return fmt.Errorf("unexpected target attribute: `%s`", targetAttr) } - *pTarget = aws.String(d.Get(targetAttr).(string)) log.Printf("[DEBUG] Creating Route: %s", input) @@ -216,7 +207,7 @@ func resourceAwsRouteCreate(d *schema.ResourceData, meta interface{}) error { } if err != nil { - return fmt.Errorf("error creating route: %s", err) + return fmt.Errorf("error creating Route: %s", err) } var route *ec2.Route @@ -228,7 +219,7 @@ func resourceAwsRouteCreate(d *schema.ResourceData, meta interface{}) error { } if route == nil { - return resource.RetryableError(fmt.Errorf("route not found")) + return resource.RetryableError(fmt.Errorf("Route not found")) } return nil @@ -239,11 +230,11 @@ func resourceAwsRouteCreate(d *schema.ResourceData, meta interface{}) error { } if err != nil { - return fmt.Errorf("error reading route for Route Table (%s) with destination (%s): %s", routeTableID, destination, err) + return fmt.Errorf("error reading Route for Route Table (%s) with destination (%s): %s", routeTableID, destination, err) } if route == nil { - return fmt.Errorf("route in Route Table (%s) with destination (%s) not found", routeTableID, destination) + return fmt.Errorf("Route in Route Table (%s) with destination (%s) not found", routeTableID, destination) } d.SetId(routeCreateID(routeTableID, destination)) @@ -256,9 +247,11 @@ func resourceAwsRouteRead(d *schema.ResourceData, meta interface{}) error { destinationAttr := routeDestinationAttr(d) + destination := d.Get(destinationAttr).(string) routeTableID := d.Get("route_table_id").(string) var routeReader func(*ec2.EC2, string, string) (*ec2.Route, error) + switch destinationAttr { case "destination_cidr_block": routeReader = readIpv4Route @@ -267,7 +260,6 @@ func resourceAwsRouteRead(d *schema.ResourceData, meta interface{}) error { default: return fmt.Errorf("unexpected destination attribute: `%s`", destinationAttr) } - destination := d.Get(destinationAttr).(string) route, err := routeReader(conn, routeTableID, destination) @@ -278,7 +270,7 @@ func resourceAwsRouteRead(d *schema.ResourceData, meta interface{}) error { } if err != nil { - return fmt.Errorf("error reading route for Route Table (%s) with destination (%s): %s", routeTableID, destination, err) + return fmt.Errorf("error reading Route for Route Table (%s) with destination (%s): %s", routeTableID, destination, err) } if route == nil { @@ -306,93 +298,55 @@ func resourceAwsRouteRead(d *schema.ResourceData, meta interface{}) error { func resourceAwsRouteUpdate(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).ec2conn - var numTargets int - var setTarget string - - allowedTargets := []string{ - "egress_only_gateway_id", - "gateway_id", - "nat_gateway_id", - "network_interface_id", - "instance_id", - "transit_gateway_id", - "vpc_peering_connection_id", - } - // Check if more than 1 target is specified - for _, target := range allowedTargets { - if len(d.Get(target).(string)) > 0 { - numTargets++ - setTarget = target - } + + destinationAttr, targetAttr, err := routeDestinationAndTargetAttributes(d) + if err != nil { + return err } - switch setTarget { - //instance_id is a special case due to the fact that AWS will "discover" the network_interface_id - //when it creates the route and return that data. In the case of an update, we should ignore the - //existing network_interface_id - case "instance_id": - if numTargets > 2 || (numTargets == 2 && len(d.Get("network_interface_id").(string)) == 0) { - return routeTargetValidationError - } + destination := d.Get(destinationAttr).(string) + routeTableID := d.Get("route_table_id").(string) + input := &ec2.ReplaceRouteInput{ + RouteTableId: aws.String(routeTableID), + } + + switch destinationAttr { + case "destination_cidr_block": + input.DestinationCidrBlock = aws.String(destination) + case "destination_ipv6_cidr_block": + input.DestinationIpv6CidrBlock = aws.String(destination) default: - if numTargets > 1 { - return routeTargetValidationError - } + return fmt.Errorf("unexpected destination attribute: `%s`", destinationAttr) } - var replaceOpts *ec2.ReplaceRouteInput - // Formulate ReplaceRouteInput based on the target type - switch setTarget { - case "gateway_id": - replaceOpts = &ec2.ReplaceRouteInput{ - RouteTableId: aws.String(d.Get("route_table_id").(string)), - DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)), - GatewayId: aws.String(d.Get("gateway_id").(string)), - } + target := aws.String(d.Get(targetAttr).(string)) + switch targetAttr { case "egress_only_gateway_id": - replaceOpts = &ec2.ReplaceRouteInput{ - RouteTableId: aws.String(d.Get("route_table_id").(string)), - DestinationIpv6CidrBlock: aws.String(d.Get("destination_ipv6_cidr_block").(string)), - EgressOnlyInternetGatewayId: aws.String(d.Get("egress_only_gateway_id").(string)), - } - case "nat_gateway_id": - replaceOpts = &ec2.ReplaceRouteInput{ - RouteTableId: aws.String(d.Get("route_table_id").(string)), - DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)), - NatGatewayId: aws.String(d.Get("nat_gateway_id").(string)), - } + input.EgressOnlyInternetGatewayId = target + case "gateway_id": + input.GatewayId = target case "instance_id": - replaceOpts = &ec2.ReplaceRouteInput{ - RouteTableId: aws.String(d.Get("route_table_id").(string)), - DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)), - InstanceId: aws.String(d.Get("instance_id").(string)), - } + input.InstanceId = target + case "nat_gateway_id": + input.NatGatewayId = target case "network_interface_id": - replaceOpts = &ec2.ReplaceRouteInput{ - RouteTableId: aws.String(d.Get("route_table_id").(string)), - DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)), - NetworkInterfaceId: aws.String(d.Get("network_interface_id").(string)), - } + input.NetworkInterfaceId = target case "transit_gateway_id": - replaceOpts = &ec2.ReplaceRouteInput{ - RouteTableId: aws.String(d.Get("route_table_id").(string)), - DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)), - TransitGatewayId: aws.String(d.Get("transit_gateway_id").(string)), - } + input.TransitGatewayId = target case "vpc_peering_connection_id": - replaceOpts = &ec2.ReplaceRouteInput{ - RouteTableId: aws.String(d.Get("route_table_id").(string)), - DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)), - VpcPeeringConnectionId: aws.String(d.Get("vpc_peering_connection_id").(string)), - } + input.VpcPeeringConnectionId = target default: - return fmt.Errorf("An invalid target type specified: %s", setTarget) + return fmt.Errorf("unexpected target attribute: `%s`", targetAttr) } - log.Printf("[DEBUG] Route replace config: %s", replaceOpts) - // Replace the route - _, err := conn.ReplaceRoute(replaceOpts) - return err + log.Printf("[DEBUG] Updating Route: %s", input) + _, err = conn.ReplaceRoute(input) + + if err != nil { + return fmt.Errorf("error updating Route for Route Table (%s) with destination (%s): %s", routeTableID, destination, err) + } + + return resourceAwsRouteRead(d, meta) } func resourceAwsRouteDelete(d *schema.ResourceData, meta interface{}) error { @@ -400,25 +354,23 @@ func resourceAwsRouteDelete(d *schema.ResourceData, meta interface{}) error { destinationAttr := routeDestinationAttr(d) + destination := d.Get(destinationAttr).(string) routeTableID := d.Get("route_table_id").(string) input := &ec2.DeleteRouteInput{ RouteTableId: aws.String(routeTableID), } - var pDestination **string switch destinationAttr { case "destination_cidr_block": - pDestination = &input.DestinationCidrBlock + input.DestinationCidrBlock = aws.String(destination) case "destination_ipv6_cidr_block": - pDestination = &input.DestinationIpv6CidrBlock + input.DestinationIpv6CidrBlock = aws.String(destination) default: return fmt.Errorf("unexpected destination attribute: `%s`", destinationAttr) } - destination := d.Get(destinationAttr).(string) - *pDestination = aws.String(destination) err := resource.Retry(d.Timeout(schema.TimeoutDelete), func() *resource.RetryError { - log.Printf("[DEBUG] Deleting route (%s)", d.Id()) + log.Printf("[DEBUG] Deleting Route (%s)", d.Id()) _, err := conn.DeleteRoute(input) if err == nil { return nil @@ -436,7 +388,7 @@ func resourceAwsRouteDelete(d *schema.ResourceData, meta interface{}) error { }) if isResourceTimeoutError(err) { - log.Printf("[DEBUG] Deleting route (%s)", d.Id()) + log.Printf("[DEBUG] Deleting Route (%s)", d.Id()) _, err = conn.DeleteRoute(input) } @@ -445,63 +397,12 @@ func resourceAwsRouteDelete(d *schema.ResourceData, meta interface{}) error { } if err != nil { - return fmt.Errorf("error deleting route for Route Table (%s) with destination (%s): %s", routeTableID, destination, err) + return fmt.Errorf("error deleting Route for Route Table (%s) with destination (%s): %s", routeTableID, destination, err) } return nil } -// Helper: Create an ID for a route -func resourceAwsRouteID(d *schema.ResourceData, r *ec2.Route) string { - - if r.DestinationIpv6CidrBlock != nil && *r.DestinationIpv6CidrBlock != "" { - return fmt.Sprintf("r-%s%d", d.Get("route_table_id").(string), hashcode.String(*r.DestinationIpv6CidrBlock)) - } - - return fmt.Sprintf("r-%s%d", d.Get("route_table_id").(string), hashcode.String(*r.DestinationCidrBlock)) -} - -// resourceAwsRouteFindRoute returns any route whose destination is the specified IPv4 or IPv6 CIDR block. -// Returns nil if the route table exists but no matching destination is found. -func resourceAwsRouteFindRoute(conn *ec2.EC2, rtbid string, cidr string, ipv6cidr string) (*ec2.Route, error) { - routeTableID := rtbid - - findOpts := &ec2.DescribeRouteTablesInput{ - RouteTableIds: []*string{&routeTableID}, - } - - resp, err := conn.DescribeRouteTables(findOpts) - if err != nil { - return nil, err - } - - if len(resp.RouteTables) < 1 || resp.RouteTables[0] == nil { - return nil, nil - } - - if cidr != "" { - for _, route := range (*resp.RouteTables[0]).Routes { - if route.DestinationCidrBlock != nil && *route.DestinationCidrBlock == cidr { - return route, nil - } - } - - return nil, nil - } - - if ipv6cidr != "" { - for _, route := range (*resp.RouteTables[0]).Routes { - if cidrBlocksEqual(aws.StringValue(route.DestinationIpv6CidrBlock), ipv6cidr) { - return route, nil - } - } - - return nil, nil - } - - return nil, nil -} - // routeDestinationAttr return the route's destination attribute name. // No validation is done. func routeDestinationAttr(d *schema.ResourceData) string { @@ -566,7 +467,7 @@ func routeDestinationAndTargetAttributes(d *schema.ResourceData) (string, string targetAttr := "" for attr, allowed := range targetAttrs { - if v := d.Get(attr).(string); v != "" { + if v := d.Get(attr).(string); v != "" && d.HasChange(attr) { if targetAttr != "" { return "", "", fmt.Errorf("`%s` conflicts with `%s`", attr, targetAttr) } diff --git a/aws/resource_aws_route_test.go b/aws/resource_aws_route_test.go index fe728d8698ff..c07a919d7ee8 100644 --- a/aws/resource_aws_route_test.go +++ b/aws/resource_aws_route_test.go @@ -820,14 +820,14 @@ func TestAccAWSRoute_IPv4_Update_Target(t *testing.T) { ), }, { - Config: testAccAWSRouteConfigIpv4FlexiTarget(rName, destinationCidr, "gateway_id", igwResourceName), + Config: testAccAWSRouteConfigIpv4FlexiTarget(rName, destinationCidr, "gateway_id", vgwResourceName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSRouteExists(resourceName, &route), resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", destinationCidr), resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), resource.TestCheckResourceAttr(resourceName, "destination_prefix_list_id", ""), resource.TestCheckResourceAttr(resourceName, "egress_only_gateway_id", ""), - resource.TestCheckResourceAttrPair(resourceName, "gateway_id", igwResourceName, "id"), + resource.TestCheckResourceAttrPair(resourceName, "gateway_id", vgwResourceName, "id"), resource.TestCheckResourceAttr(resourceName, "instance_id", ""), resource.TestCheckResourceAttr(resourceName, "instance_owner_id", ""), resource.TestCheckResourceAttr(resourceName, "nat_gateway_id", ""), @@ -839,17 +839,17 @@ func TestAccAWSRoute_IPv4_Update_Target(t *testing.T) { ), }, { - Config: testAccAWSRouteConfigIpv4FlexiTarget(rName, destinationCidr, "nat_gateway_id", ngwResourceName), + Config: testAccAWSRouteConfigIpv4FlexiTarget(rName, destinationCidr, "gateway_id", igwResourceName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSRouteExists(resourceName, &route), resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", destinationCidr), resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), resource.TestCheckResourceAttr(resourceName, "destination_prefix_list_id", ""), resource.TestCheckResourceAttr(resourceName, "egress_only_gateway_id", ""), - resource.TestCheckResourceAttr(resourceName, "gateway_id", ""), + resource.TestCheckResourceAttrPair(resourceName, "gateway_id", igwResourceName, "id"), resource.TestCheckResourceAttr(resourceName, "instance_id", ""), resource.TestCheckResourceAttr(resourceName, "instance_owner_id", ""), - resource.TestCheckResourceAttrPair(resourceName, "nat_gateway_id", ngwResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "nat_gateway_id", ""), resource.TestCheckResourceAttr(resourceName, "network_interface_id", ""), resource.TestCheckResourceAttr(resourceName, "origin", ec2.RouteOriginCreateRoute), resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateActive), @@ -858,7 +858,7 @@ func TestAccAWSRoute_IPv4_Update_Target(t *testing.T) { ), }, { - Config: testAccAWSRouteConfigIpv4FlexiTarget(rName, destinationCidr, "network_interface_id", eniResourceName), + Config: testAccAWSRouteConfigIpv4FlexiTarget(rName, destinationCidr, "nat_gateway_id", ngwResourceName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSRouteExists(resourceName, &route), resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", destinationCidr), @@ -868,16 +868,16 @@ func TestAccAWSRoute_IPv4_Update_Target(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "gateway_id", ""), resource.TestCheckResourceAttr(resourceName, "instance_id", ""), resource.TestCheckResourceAttr(resourceName, "instance_owner_id", ""), - resource.TestCheckResourceAttr(resourceName, "nat_gateway_id", ""), - resource.TestCheckResourceAttrPair(resourceName, "network_interface_id", eniResourceName, "id"), + resource.TestCheckResourceAttrPair(resourceName, "nat_gateway_id", ngwResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "network_interface_id", ""), resource.TestCheckResourceAttr(resourceName, "origin", ec2.RouteOriginCreateRoute), - resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateBlackhole), + resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateActive), resource.TestCheckResourceAttr(resourceName, "transit_gateway_id", ""), resource.TestCheckResourceAttr(resourceName, "vpc_peering_connection_id", ""), ), }, { - Config: testAccAWSRouteConfigIpv4FlexiTarget(rName, destinationCidr, "transit_gateway_id", tgwResourceName), + Config: testAccAWSRouteConfigIpv4FlexiTarget(rName, destinationCidr, "network_interface_id", eniResourceName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSRouteExists(resourceName, &route), resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", destinationCidr), @@ -888,15 +888,15 @@ func TestAccAWSRoute_IPv4_Update_Target(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "instance_id", ""), resource.TestCheckResourceAttr(resourceName, "instance_owner_id", ""), resource.TestCheckResourceAttr(resourceName, "nat_gateway_id", ""), - resource.TestCheckResourceAttr(resourceName, "network_interface_id", ""), + resource.TestCheckResourceAttrPair(resourceName, "network_interface_id", eniResourceName, "id"), resource.TestCheckResourceAttr(resourceName, "origin", ec2.RouteOriginCreateRoute), - resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateActive), - resource.TestCheckResourceAttrPair(resourceName, "transit_gateway_id", tgwResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateBlackhole), + resource.TestCheckResourceAttr(resourceName, "transit_gateway_id", ""), resource.TestCheckResourceAttr(resourceName, "vpc_peering_connection_id", ""), ), }, { - Config: testAccAWSRouteConfigIpv4FlexiTarget(rName, destinationCidr, "vpc_peering_connection_id", pcxResourceName), + Config: testAccAWSRouteConfigIpv4FlexiTarget(rName, destinationCidr, "transit_gateway_id", tgwResourceName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSRouteExists(resourceName, &route), resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", destinationCidr), @@ -910,19 +910,19 @@ func TestAccAWSRoute_IPv4_Update_Target(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "network_interface_id", ""), resource.TestCheckResourceAttr(resourceName, "origin", ec2.RouteOriginCreateRoute), resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateActive), - resource.TestCheckResourceAttr(resourceName, "transit_gateway_id", ""), - resource.TestCheckResourceAttrPair(resourceName, "vpc_peering_connection_id", pcxResourceName, "id"), + resource.TestCheckResourceAttrPair(resourceName, "transit_gateway_id", tgwResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "vpc_peering_connection_id", ""), ), }, { - Config: testAccAWSRouteConfigIpv4FlexiTarget(rName, destinationCidr, "gateway_id", vgwResourceName), + Config: testAccAWSRouteConfigIpv4FlexiTarget(rName, destinationCidr, "vpc_peering_connection_id", pcxResourceName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSRouteExists(resourceName, &route), resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", destinationCidr), resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), resource.TestCheckResourceAttr(resourceName, "destination_prefix_list_id", ""), resource.TestCheckResourceAttr(resourceName, "egress_only_gateway_id", ""), - resource.TestCheckResourceAttrPair(resourceName, "gateway_id", vgwResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "gateway_id", ""), resource.TestCheckResourceAttr(resourceName, "instance_id", ""), resource.TestCheckResourceAttr(resourceName, "instance_owner_id", ""), resource.TestCheckResourceAttr(resourceName, "nat_gateway_id", ""), @@ -930,7 +930,7 @@ func TestAccAWSRoute_IPv4_Update_Target(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "origin", ec2.RouteOriginCreateRoute), resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateActive), resource.TestCheckResourceAttr(resourceName, "transit_gateway_id", ""), - resource.TestCheckResourceAttr(resourceName, "vpc_peering_connection_id", ""), + resource.TestCheckResourceAttrPair(resourceName, "vpc_peering_connection_id", pcxResourceName, "id"), ), }, { @@ -980,14 +980,14 @@ func TestAccAWSRoute_IPv6_Update_Target(t *testing.T) { ), }, { - Config: testAccAWSRouteConfigIpv6FlexiTarget(rName, destinationCidr, "gateway_id", igwResourceName), + Config: testAccAWSRouteConfigIpv6FlexiTarget(rName, destinationCidr, "gateway_id", vgwResourceName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSRouteExists(resourceName, &route), resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", ""), resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", destinationCidr), resource.TestCheckResourceAttr(resourceName, "destination_prefix_list_id", ""), resource.TestCheckResourceAttr(resourceName, "egress_only_gateway_id", ""), - resource.TestCheckResourceAttrPair(resourceName, "gateway_id", igwResourceName, "id"), + resource.TestCheckResourceAttrPair(resourceName, "gateway_id", vgwResourceName, "id"), resource.TestCheckResourceAttr(resourceName, "instance_id", ""), resource.TestCheckResourceAttr(resourceName, "instance_owner_id", ""), resource.TestCheckResourceAttr(resourceName, "nat_gateway_id", ""), @@ -999,14 +999,14 @@ func TestAccAWSRoute_IPv6_Update_Target(t *testing.T) { ), }, { - Config: testAccAWSRouteConfigIpv6FlexiTarget(rName, destinationCidr, "egress_only_gateway_id", eoigwResourceName), + Config: testAccAWSRouteConfigIpv6FlexiTarget(rName, destinationCidr, "gateway_id", igwResourceName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSRouteExists(resourceName, &route), resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", ""), resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", destinationCidr), resource.TestCheckResourceAttr(resourceName, "destination_prefix_list_id", ""), - resource.TestCheckResourceAttrPair(resourceName, "egress_only_gateway_id", eoigwResourceName, "id"), - resource.TestCheckResourceAttr(resourceName, "gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "egress_only_gateway_id", ""), + resource.TestCheckResourceAttrPair(resourceName, "gateway_id", igwResourceName, "id"), resource.TestCheckResourceAttr(resourceName, "instance_id", ""), resource.TestCheckResourceAttr(resourceName, "instance_owner_id", ""), resource.TestCheckResourceAttr(resourceName, "nat_gateway_id", ""), @@ -1018,26 +1018,26 @@ func TestAccAWSRoute_IPv6_Update_Target(t *testing.T) { ), }, { - Config: testAccAWSRouteConfigIpv6FlexiTarget(rName, destinationCidr, "network_interface_id", eniResourceName), + Config: testAccAWSRouteConfigIpv6FlexiTarget(rName, destinationCidr, "egress_only_gateway_id", eoigwResourceName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSRouteExists(resourceName, &route), resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", ""), resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", destinationCidr), resource.TestCheckResourceAttr(resourceName, "destination_prefix_list_id", ""), - resource.TestCheckResourceAttr(resourceName, "egress_only_gateway_id", ""), + resource.TestCheckResourceAttrPair(resourceName, "egress_only_gateway_id", eoigwResourceName, "id"), resource.TestCheckResourceAttr(resourceName, "gateway_id", ""), resource.TestCheckResourceAttr(resourceName, "instance_id", ""), resource.TestCheckResourceAttr(resourceName, "instance_owner_id", ""), resource.TestCheckResourceAttr(resourceName, "nat_gateway_id", ""), - resource.TestCheckResourceAttrPair(resourceName, "network_interface_id", eniResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "network_interface_id", ""), resource.TestCheckResourceAttr(resourceName, "origin", ec2.RouteOriginCreateRoute), - resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateBlackhole), + resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateActive), resource.TestCheckResourceAttr(resourceName, "transit_gateway_id", ""), resource.TestCheckResourceAttr(resourceName, "vpc_peering_connection_id", ""), ), }, { - Config: testAccAWSRouteConfigIpv6FlexiTarget(rName, destinationCidr, "vpc_peering_connection_id", pcxResourceName), + Config: testAccAWSRouteConfigIpv6FlexiTarget(rName, destinationCidr, "network_interface_id", eniResourceName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSRouteExists(resourceName, &route), resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", ""), @@ -1048,22 +1048,22 @@ func TestAccAWSRoute_IPv6_Update_Target(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "instance_id", ""), resource.TestCheckResourceAttr(resourceName, "instance_owner_id", ""), resource.TestCheckResourceAttr(resourceName, "nat_gateway_id", ""), - resource.TestCheckResourceAttr(resourceName, "network_interface_id", ""), + resource.TestCheckResourceAttrPair(resourceName, "network_interface_id", eniResourceName, "id"), resource.TestCheckResourceAttr(resourceName, "origin", ec2.RouteOriginCreateRoute), - resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateActive), + resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateBlackhole), resource.TestCheckResourceAttr(resourceName, "transit_gateway_id", ""), - resource.TestCheckResourceAttrPair(resourceName, "vpc_peering_connection_id", pcxResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "vpc_peering_connection_id", ""), ), }, { - Config: testAccAWSRouteConfigIpv6FlexiTarget(rName, destinationCidr, "gateway_id", vgwResourceName), + Config: testAccAWSRouteConfigIpv6FlexiTarget(rName, destinationCidr, "vpc_peering_connection_id", pcxResourceName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSRouteExists(resourceName, &route), resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", ""), resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", destinationCidr), resource.TestCheckResourceAttr(resourceName, "destination_prefix_list_id", ""), resource.TestCheckResourceAttr(resourceName, "egress_only_gateway_id", ""), - resource.TestCheckResourceAttrPair(resourceName, "gateway_id", vgwResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "gateway_id", ""), resource.TestCheckResourceAttr(resourceName, "instance_id", ""), resource.TestCheckResourceAttr(resourceName, "instance_owner_id", ""), resource.TestCheckResourceAttr(resourceName, "nat_gateway_id", ""), @@ -1071,7 +1071,7 @@ func TestAccAWSRoute_IPv6_Update_Target(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "origin", ec2.RouteOriginCreateRoute), resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateActive), resource.TestCheckResourceAttr(resourceName, "transit_gateway_id", ""), - resource.TestCheckResourceAttr(resourceName, "vpc_peering_connection_id", ""), + resource.TestCheckResourceAttrPair(resourceName, "vpc_peering_connection_id", pcxResourceName, "id"), ), }, { @@ -1096,22 +1096,24 @@ func testAccCheckAWSRouteExists(n string, res *ec2.Route) resource.TestCheckFunc } conn := testAccProvider.Meta().(*AWSClient).ec2conn - r, err := resourceAwsRouteFindRoute( - conn, - rs.Primary.Attributes["route_table_id"], - rs.Primary.Attributes["destination_cidr_block"], - rs.Primary.Attributes["destination_ipv6_cidr_block"], - ) + + var route *ec2.Route + var err error + if v := rs.Primary.Attributes["destination_cidr_block"]; v != "" { + route, err = readIpv4Route(conn, rs.Primary.Attributes["route_table_id"], v) + } else if v := rs.Primary.Attributes["destination_ipv6_cidr_block"]; v != "" { + route, err = readIpv6Route(conn, rs.Primary.Attributes["route_table_id"], v) + } if err != nil { return err } - if r == nil { + if route == nil { return fmt.Errorf("Route not found") } - *res = *r + *res = *route return nil } @@ -1124,12 +1126,14 @@ func testAccCheckAWSRouteDestroy(s *terraform.State) error { } conn := testAccProvider.Meta().(*AWSClient).ec2conn - route, err := resourceAwsRouteFindRoute( - conn, - rs.Primary.Attributes["route_table_id"], - rs.Primary.Attributes["destination_cidr_block"], - rs.Primary.Attributes["destination_ipv6_cidr_block"], - ) + + var route *ec2.Route + var err error + if v := rs.Primary.Attributes["destination_cidr_block"]; v != "" { + route, err = readIpv4Route(conn, rs.Primary.Attributes["route_table_id"], v) + } else if v := rs.Primary.Attributes["destination_ipv6_cidr_block"]; v != "" { + route, err = readIpv6Route(conn, rs.Primary.Attributes["route_table_id"], v) + } if route == nil && err == nil { return nil From 80d2c456c9a3965b71f8965545838326a122a48f Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Sat, 4 Jul 2020 17:45:02 -0400 Subject: [PATCH 32/40] r/aws_route: Uncommented 'TestAccAWSRoute_IPv4_To_NetworkInterface_TwoAttachments'. Acceptance test output: $ make testacc TEST=./aws/ TESTARGS='-run=TestAccAWSRoute_IPv4_To_NetworkInterface_TwoAttachments' ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws/ -v -count 1 -parallel 2 -run=TestAccAWSRoute_IPv4_To_NetworkInterface_TwoAttachments -timeout 120m === RUN TestAccAWSRoute_IPv4_To_NetworkInterface_TwoAttachments === PAUSE TestAccAWSRoute_IPv4_To_NetworkInterface_TwoAttachments === CONT TestAccAWSRoute_IPv4_To_NetworkInterface_TwoAttachments --- PASS: TestAccAWSRoute_IPv4_To_NetworkInterface_TwoAttachments (145.48s) PASS ok github.com/terraform-providers/terraform-provider-aws/aws 145.537s --- aws/resource_aws_route_test.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/aws/resource_aws_route_test.go b/aws/resource_aws_route_test.go index c07a919d7ee8..0aad53ab6ac6 100644 --- a/aws/resource_aws_route_test.go +++ b/aws/resource_aws_route_test.go @@ -525,7 +525,6 @@ func TestAccAWSRoute_IPv4_To_NetworkInterface_Attached(t *testing.T) { }) } -/* func TestAccAWSRoute_IPv4_To_NetworkInterface_TwoAttachments(t *testing.T) { var route ec2.Route resourceName := "aws_route.test" @@ -589,7 +588,6 @@ func TestAccAWSRoute_IPv4_To_NetworkInterface_TwoAttachments(t *testing.T) { }, }) } -*/ func TestAccAWSRoute_IPv4_To_VpcPeeringConnection(t *testing.T) { var route ec2.Route @@ -1722,7 +1720,6 @@ resource "aws_route" "test" { `, rName, destinationCidr)) } -/* func testAccAWSRouteConfigIpv4NetworkInterfaceTwoAttachments(rName, destinationCidr, targetResourceName string) string { return composeConfig( testAccLatestAmazonNatInstanceAmiConfig(), @@ -1800,7 +1797,6 @@ resource "aws_route" "test" { } `, rName, destinationCidr, targetResourceName)) } -*/ func testAccAWSRouteConfigIpv4VpcPeeringConnection(rName, destinationCidr string) string { return fmt.Sprintf(` From 35b11750d7cac7dc6d3dcfc5ec39a10610047a0e Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Sat, 4 Jul 2020 18:15:34 -0400 Subject: [PATCH 33/40] Acceptance test output: $ make testacc TEST=./aws/ TESTARGS='-run=TestAccAWSRoute_' ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws/ -v -count 1 -parallel 2 -run=TestAccAWSRoute_ -timeout 120m === RUN TestAccAWSRoute_basic === PAUSE TestAccAWSRoute_basic === RUN TestAccAWSRoute_disappears === PAUSE TestAccAWSRoute_disappears === RUN TestAccAWSRoute_routeTableDisappears === PAUSE TestAccAWSRoute_routeTableDisappears === RUN TestAccAWSRoute_IPv6_To_EgressOnlyInternetGateway === PAUSE TestAccAWSRoute_IPv6_To_EgressOnlyInternetGateway === RUN TestAccAWSRoute_IPv6_To_InternetGateway === PAUSE TestAccAWSRoute_IPv6_To_InternetGateway === RUN TestAccAWSRoute_IPv6_To_Instance === PAUSE TestAccAWSRoute_IPv6_To_Instance === RUN TestAccAWSRoute_IPv6_To_NetworkInterface_Unattached === PAUSE TestAccAWSRoute_IPv6_To_NetworkInterface_Unattached === RUN TestAccAWSRoute_IPv6_To_VpcPeeringConnection === PAUSE TestAccAWSRoute_IPv6_To_VpcPeeringConnection === RUN TestAccAWSRoute_IPv6_To_VpnGateway === PAUSE TestAccAWSRoute_IPv6_To_VpnGateway === RUN TestAccAWSRoute_IPv4_To_VpnGateway === PAUSE TestAccAWSRoute_IPv4_To_VpnGateway === RUN TestAccAWSRoute_IPv4_To_Instance === PAUSE TestAccAWSRoute_IPv4_To_Instance === RUN TestAccAWSRoute_IPv4_To_NetworkInterface_Unattached === PAUSE TestAccAWSRoute_IPv4_To_NetworkInterface_Unattached === RUN TestAccAWSRoute_IPv4_To_NetworkInterface_Attached === PAUSE TestAccAWSRoute_IPv4_To_NetworkInterface_Attached === RUN TestAccAWSRoute_IPv4_To_NetworkInterface_TwoAttachments === PAUSE TestAccAWSRoute_IPv4_To_NetworkInterface_TwoAttachments === RUN TestAccAWSRoute_IPv4_To_VpcPeeringConnection === PAUSE TestAccAWSRoute_IPv4_To_VpcPeeringConnection === RUN TestAccAWSRoute_IPv4_To_NatGateway === PAUSE TestAccAWSRoute_IPv4_To_NatGateway === RUN TestAccAWSRoute_DoesNotCrashWithVpcEndpoint === PAUSE TestAccAWSRoute_DoesNotCrashWithVpcEndpoint === RUN TestAccAWSRoute_IPv4_To_TransitGateway === PAUSE TestAccAWSRoute_IPv4_To_TransitGateway === RUN TestAccAWSRoute_ConditionalCidrBlock === PAUSE TestAccAWSRoute_ConditionalCidrBlock === RUN TestAccAWSRoute_IPv4_Update_Target === PAUSE TestAccAWSRoute_IPv4_Update_Target === RUN TestAccAWSRoute_IPv6_Update_Target === PAUSE TestAccAWSRoute_IPv6_Update_Target === CONT TestAccAWSRoute_disappears === CONT TestAccAWSRoute_IPv6_Update_Target --- PASS: TestAccAWSRoute_disappears (48.49s) === CONT TestAccAWSRoute_IPv4_Update_Target --- PASS: TestAccAWSRoute_IPv6_Update_Target (266.65s) === CONT TestAccAWSRoute_ConditionalCidrBlock --- PASS: TestAccAWSRoute_ConditionalCidrBlock (76.16s) === CONT TestAccAWSRoute_IPv4_To_TransitGateway --- PASS: TestAccAWSRoute_IPv4_Update_Target (502.14s) === CONT TestAccAWSRoute_DoesNotCrashWithVpcEndpoint --- PASS: TestAccAWSRoute_DoesNotCrashWithVpcEndpoint (63.18s) === CONT TestAccAWSRoute_IPv4_To_NatGateway --- PASS: TestAccAWSRoute_IPv4_To_TransitGateway (346.35s) === CONT TestAccAWSRoute_IPv4_To_VpcPeeringConnection --- PASS: TestAccAWSRoute_IPv4_To_VpcPeeringConnection (42.93s) === CONT TestAccAWSRoute_IPv4_To_NetworkInterface_TwoAttachments --- PASS: TestAccAWSRoute_IPv4_To_NatGateway (216.48s) === CONT TestAccAWSRoute_IPv4_To_NetworkInterface_Attached --- PASS: TestAccAWSRoute_IPv4_To_NetworkInterface_TwoAttachments (155.89s) === CONT TestAccAWSRoute_IPv4_To_NetworkInterface_Unattached --- PASS: TestAccAWSRoute_IPv4_To_NetworkInterface_Unattached (48.44s) === CONT TestAccAWSRoute_IPv4_To_Instance --- PASS: TestAccAWSRoute_IPv4_To_NetworkInterface_Attached (146.10s) === CONT TestAccAWSRoute_IPv4_To_VpnGateway --- PASS: TestAccAWSRoute_IPv4_To_VpnGateway (59.08s) === CONT TestAccAWSRoute_IPv6_To_VpnGateway --- PASS: TestAccAWSRoute_IPv4_To_Instance (139.67s) === CONT TestAccAWSRoute_IPv6_To_VpcPeeringConnection --- PASS: TestAccAWSRoute_IPv6_To_VpnGateway (56.31s) === CONT TestAccAWSRoute_IPv6_To_NetworkInterface_Unattached --- PASS: TestAccAWSRoute_IPv6_To_VpcPeeringConnection (43.67s) === CONT TestAccAWSRoute_IPv6_To_Instance --- PASS: TestAccAWSRoute_IPv6_To_NetworkInterface_Unattached (49.09s) === CONT TestAccAWSRoute_IPv6_To_InternetGateway --- PASS: TestAccAWSRoute_IPv6_To_InternetGateway (52.37s) === CONT TestAccAWSRoute_IPv6_To_EgressOnlyInternetGateway --- PASS: TestAccAWSRoute_IPv6_To_Instance (131.22s) === CONT TestAccAWSRoute_routeTableDisappears --- PASS: TestAccAWSRoute_IPv6_To_EgressOnlyInternetGateway (59.16s) === CONT TestAccAWSRoute_basic --- PASS: TestAccAWSRoute_routeTableDisappears (48.47s) --- PASS: TestAccAWSRoute_basic (50.81s) PASS ok github.com/terraform-providers/terraform-provider-aws/aws 1303.322s --- aws/resource_aws_route_test.go | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/aws/resource_aws_route_test.go b/aws/resource_aws_route_test.go index 0aad53ab6ac6..d31a69d947a8 100644 --- a/aws/resource_aws_route_test.go +++ b/aws/resource_aws_route_test.go @@ -883,12 +883,12 @@ func TestAccAWSRoute_IPv4_Update_Target(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "destination_prefix_list_id", ""), resource.TestCheckResourceAttr(resourceName, "egress_only_gateway_id", ""), resource.TestCheckResourceAttr(resourceName, "gateway_id", ""), - resource.TestCheckResourceAttr(resourceName, "instance_id", ""), - resource.TestCheckResourceAttr(resourceName, "instance_owner_id", ""), + resource.TestCheckResourceAttrPair(resourceName, "instance_id", instanceResourceName, "id"), + testAccCheckResourceAttrAccountID(resourceName, "instance_owner_id"), resource.TestCheckResourceAttr(resourceName, "nat_gateway_id", ""), resource.TestCheckResourceAttrPair(resourceName, "network_interface_id", eniResourceName, "id"), resource.TestCheckResourceAttr(resourceName, "origin", ec2.RouteOriginCreateRoute), - resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateBlackhole), + resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateActive), resource.TestCheckResourceAttr(resourceName, "transit_gateway_id", ""), resource.TestCheckResourceAttr(resourceName, "vpc_peering_connection_id", ""), ), @@ -2031,7 +2031,11 @@ resource "aws_subnet" "test" { resource "aws_instance" "test" { ami = data.aws_ami.amzn-ami-minimal-hvm-ebs.id instance_type = data.aws_ec2_instance_type_offering.available.instance_type - subnet_id = aws_subnet.test.id + + network_interface { + device_index = 0 + network_interface_id = aws_network_interface.test.id + } tags = { Name = %[1]q From 5df142947fd1aa44bcd2ae2ff0635d055eed41ab Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Mon, 6 Jul 2020 16:01:35 -0400 Subject: [PATCH 34/40] r/aws_route: Use 'available' as the name of the 'aws_availability_zones' data source. --- aws/resource_aws_route_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/aws/resource_aws_route_test.go b/aws/resource_aws_route_test.go index d31a69d947a8..098abe5c06a5 100644 --- a/aws/resource_aws_route_test.go +++ b/aws/resource_aws_route_test.go @@ -1980,7 +1980,7 @@ func testAccAWSRouteConfigIpv4FlexiTarget(rName, destinationCidr, targetAttribut testAccLatestAmazonLinuxHvmEbsAmiConfig(), testAccAvailableEc2InstanceTypeForRegion("t3.micro", "t2.micro"), fmt.Sprintf(` -data "aws_availability_zones" "current" { +data "aws_availability_zones" "available" { # Exclude usw2-az4 (us-west-2d) as it has limited instance types. # IncorrectState: Transit Gateway is not available in availability zone us-west-2d exclude_zone_ids = ["usw2-az4"] @@ -2019,7 +2019,7 @@ resource "aws_internet_gateway" "test" { resource "aws_subnet" "test" { cidr_block = "10.1.1.0/24" vpc_id = aws_vpc.test.id - availability_zone = data.aws_availability_zones.current.names[0] + availability_zone = data.aws_availability_zones.available.names[0] map_public_ip_on_launch = true @@ -2125,7 +2125,7 @@ func testAccAWSRouteConfigIpv6FlexiTarget(rName, destinationCidr, targetAttribut testAccLatestAmazonLinuxHvmEbsAmiConfig(), testAccAvailableEc2InstanceTypeForRegion("t3.micro", "t2.micro"), fmt.Sprintf(` -data "aws_availability_zones" "current" { +data "aws_availability_zones" "available" { # Exclude usw2-az4 (us-west-2d) as it has limited instance types. # IncorrectState: Transit Gateway is not available in availability zone us-west-2d exclude_zone_ids = ["usw2-az4"] @@ -2165,7 +2165,7 @@ resource "aws_internet_gateway" "test" { resource "aws_subnet" "test" { cidr_block = "10.1.1.0/24" vpc_id = aws_vpc.test.id - availability_zone = data.aws_availability_zones.current.names[0] + availability_zone = data.aws_availability_zones.available.names[0] ipv6_cidr_block = cidrsubnet(aws_vpc.test.ipv6_cidr_block, 8, 1) map_public_ip_on_launch = true From 6b27b98282fde680427718cf35910fc8e52803a7 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 8 Jul 2020 15:33:13 -0400 Subject: [PATCH 35/40] r/aws_route: Add 'TestAccAWSRoute_LocalRoute' to test ability to import a local route. Acceptance test output: $ make testacc TEST=./aws/ TESTARGS='-run=TestAccAWSRoute_LocalRoute' ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws/ -v -count 1 -parallel 20 -run=TestAccAWSRoute_LocalRoute -timeout 120m === RUN TestAccAWSRoute_LocalRoute === PAUSE TestAccAWSRoute_LocalRoute === CONT TestAccAWSRoute_LocalRoute --- PASS: TestAccAWSRoute_LocalRoute (38.20s) PASS ok github.com/terraform-providers/terraform-provider-aws/aws 38.270s --- aws/resource_aws_route.go | 5 +++ aws/resource_aws_route_test.go | 74 ++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+) diff --git a/aws/resource_aws_route.go b/aws/resource_aws_route.go index 748622b8bcfd..51266eef2ee1 100644 --- a/aws/resource_aws_route.go +++ b/aws/resource_aws_route.go @@ -380,6 +380,11 @@ func resourceAwsRouteDelete(d *schema.ResourceData, meta interface{}) error { return nil } + // Local routes (which may have been imported) cannot be deleted. Remove from state. + if isAWSErr(err, "InvalidParameterValue", "cannot remove local route") { + return nil + } + if isAWSErr(err, "InvalidParameterException", "") { return resource.RetryableError(err) } diff --git a/aws/resource_aws_route_test.go b/aws/resource_aws_route_test.go index 098abe5c06a5..4502c1983af3 100644 --- a/aws/resource_aws_route_test.go +++ b/aws/resource_aws_route_test.go @@ -4,6 +4,7 @@ import ( "fmt" "testing" + "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" "github.com/hashicorp/terraform-plugin-sdk/helper/acctest" "github.com/hashicorp/terraform-plugin-sdk/helper/resource" @@ -1082,6 +1083,45 @@ func TestAccAWSRoute_IPv6_Update_Target(t *testing.T) { }) } +// https://github.com/terraform-providers/terraform-provider-aws/issues/11455. +func TestAccAWSRoute_LocalRoute(t *testing.T) { + var routeTable ec2.RouteTable + var vpc ec2.Vpc + resourceName := "aws_route.test" + rtResourceName := "aws_route_table.test" + vpcResourceName := "aws_vpc.test" + rName := acctest.RandomWithPrefix("tf-acc-test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSRouteDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSRouteConfigIpv4NoRoute(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckVpcExists(vpcResourceName, &vpc), + testAccCheckRouteTableExists(rtResourceName, &routeTable), + testAccCheckAWSRouteTableNumberOfRoutes(&routeTable, 1), + ), + }, + { + Config: testAccAWSRouteConfigIpv4LocalRoute(rName), + ResourceName: resourceName, + ImportState: true, + ImportStateIdFunc: func(rt *ec2.RouteTable, v *ec2.Vpc) resource.ImportStateIdFunc { + return func(s *terraform.State) (string, error) { + return fmt.Sprintf("%s_%s", aws.StringValue(rt.RouteTableId), aws.StringValue(v.CidrBlock)), nil + } + }(&routeTable, &vpc), + // Don't verify the state as the local route isn't actually in the pre-import state. + // Just running ImportState verifies that we can import a local route. + ImportStateVerify: false, + }, + }, + }) +} + func testAccCheckAWSRouteExists(n string, res *ec2.Route) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] @@ -2238,3 +2278,37 @@ resource "aws_route" "test" { } `, rName, destinationCidr, targetAttribute, targetValue)) } + +// + +func testAccAWSRouteConfigIpv4NoRoute(rName string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { + cidr_block = "10.1.0.0/16" + + tags = { + Name = %[1]q + } +} + +resource "aws_route_table" "test" { + vpc_id = aws_vpc.test.id + + tags = { + Name = %[1]q + } +} +`, rName) +} + +func testAccAWSRouteConfigIpv4LocalRoute(rName string) string { + return composeConfig( + testAccAWSRouteConfigIpv4NoRoute(rName), + fmt.Sprintf(` +resource "aws_route" "test" { + route_table_id = aws_route_table.test.id + destination_cidr_block = aws_vpc.test.cidr_block + gateway_id = "local" +} +`)) +} From d780df4bb203d2b62a72d91efb9b9c3fef78d66a Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 10 Jul 2020 11:40:25 -0400 Subject: [PATCH 36/40] r/aws_route: Add error constants to 'aws/internal/service/ec2'. Tweak route read function names. Acceptance test output: $ make testacc TEST=./aws/ TESTARGS='-run=TestAccAWSRoute_basic' ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws/ -v -count 1 -parallel 20 -run=TestAccAWSRoute_basic -timeout 120m === RUN TestAccAWSRoute_basic === PAUSE TestAccAWSRoute_basic === CONT TestAccAWSRoute_basic --- PASS: TestAccAWSRoute_basic (51.24s) PASS ok github.com/terraform-providers/terraform-provider-aws/aws 51.288s make testacc TEST=./aws/ TESTARGS='-run=TestAccAWSRoute_disappears' ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws/ -v -count 1 -parallel 20 -run=TestAccAWSRoute_disappears -timeout 120m === RUN TestAccAWSRoute_disappears === PAUSE TestAccAWSRoute_disappears === CONT TestAccAWSRoute_disappears --- PASS: TestAccAWSRoute_disappears (47.70s) PASS ok github.com/terraform-providers/terraform-provider-aws/aws 47.760s $ make testacc TEST=./aws/ TESTARGS='-run=TestAccAWSRoute_disappears' ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws/ -v -count 1 -parallel 20 -run=TestAccAWSRoute_disappears -timeout 120m === RUN TestAccAWSRoute_disappears === PAUSE TestAccAWSRoute_disappears === CONT TestAccAWSRoute_disappears --- PASS: TestAccAWSRoute_disappears (47.70s) PASS ok github.com/terraform-providers/terraform-provider-aws/aws 47.760s --- aws/internal/service/ec2/errors.go | 10 +++++ aws/resource_aws_route.go | 64 +++++++++++------------------- aws/resource_aws_route_table.go | 23 +++++++++++ aws/resource_aws_route_test.go | 8 ++-- 4 files changed, 61 insertions(+), 44 deletions(-) diff --git a/aws/internal/service/ec2/errors.go b/aws/internal/service/ec2/errors.go index bde544dbbaae..7c339f0dabb9 100644 --- a/aws/internal/service/ec2/errors.go +++ b/aws/internal/service/ec2/errors.go @@ -24,3 +24,13 @@ const ErrCodeClientVpnAuthorizationRuleNotFound = "InvalidClientVpnEndpointAutho const ErrCodeClientVpnAssociationIdNotFound = "InvalidClientVpnAssociationId.NotFound" const ErrCodeClientVpnRouteNotFound = "InvalidClientVpnRouteNotFound" + +const ErrCodeInvalidParameterException = "InvalidParameterException" + +const ErrCodeInvalidParameterValue = "InvalidParameterValue" + +const ErrCodeRouteNotFound = "InvalidRoute.NotFound" + +const ErrCodeRouteTableNotFound = "InvalidRouteTableID.NotFound" + +const ErrCodeTransitGatewayNotFound = "InvalidTransitGatewayID.NotFound" diff --git a/aws/resource_aws_route.go b/aws/resource_aws_route.go index 51266eef2ee1..561f27590f56 100644 --- a/aws/resource_aws_route.go +++ b/aws/resource_aws_route.go @@ -12,6 +12,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/helper/validation" + tfec2 "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/ec2" ) func resourceAwsRoute() *schema.Resource { @@ -149,15 +150,15 @@ func resourceAwsRouteCreate(d *schema.ResourceData, meta interface{}) error { RouteTableId: aws.String(routeTableID), } - var routeReader func(*ec2.EC2, string, string) (*ec2.Route, error) + var routeFinder routeFinder switch destinationAttr { case "destination_cidr_block": input.DestinationCidrBlock = aws.String(destination) - routeReader = readIpv4Route + routeFinder = routeByIpv4Destination case "destination_ipv6_cidr_block": input.DestinationIpv6CidrBlock = aws.String(destination) - routeReader = readIpv6Route + routeFinder = routeByIpv6Destination default: return fmt.Errorf("unexpected destination attribute: `%s`", destinationAttr) } @@ -187,11 +188,11 @@ func resourceAwsRouteCreate(d *schema.ResourceData, meta interface{}) error { err = resource.Retry(d.Timeout(schema.TimeoutCreate), func() *resource.RetryError { _, err = conn.CreateRoute(input) - if isAWSErr(err, "InvalidParameterException", "") { + if isAWSErr(err, tfec2.ErrCodeInvalidParameterException, "") { return resource.RetryableError(err) } - if isAWSErr(err, "InvalidTransitGatewayID.NotFound", "") { + if isAWSErr(err, tfec2.ErrCodeTransitGatewayNotFound, "") { return resource.RetryableError(err) } @@ -212,7 +213,7 @@ func resourceAwsRouteCreate(d *schema.ResourceData, meta interface{}) error { var route *ec2.Route err = resource.Retry(d.Timeout(schema.TimeoutCreate), func() *resource.RetryError { - route, err = routeReader(conn, routeTableID, destination) + route, err = routeFinder(conn, routeTableID, destination) if err != nil { return resource.RetryableError(err) @@ -226,7 +227,7 @@ func resourceAwsRouteCreate(d *schema.ResourceData, meta interface{}) error { }) if isResourceTimeoutError(err) { - route, err = routeReader(conn, routeTableID, destination) + route, err = routeFinder(conn, routeTableID, destination) } if err != nil { @@ -250,20 +251,20 @@ func resourceAwsRouteRead(d *schema.ResourceData, meta interface{}) error { destination := d.Get(destinationAttr).(string) routeTableID := d.Get("route_table_id").(string) - var routeReader func(*ec2.EC2, string, string) (*ec2.Route, error) + var routeFinder routeFinder switch destinationAttr { case "destination_cidr_block": - routeReader = readIpv4Route + routeFinder = routeByIpv4Destination case "destination_ipv6_cidr_block": - routeReader = readIpv6Route + routeFinder = routeByIpv6Destination default: return fmt.Errorf("unexpected destination attribute: `%s`", destinationAttr) } - route, err := routeReader(conn, routeTableID, destination) + route, err := routeFinder(conn, routeTableID, destination) - if isAWSErr(err, "InvalidRouteTableID.NotFound", "") { + if isAWSErr(err, tfec2.ErrCodeRouteTableNotFound, "") { log.Printf("[WARN] Route Table (%s) not found, removing from state", routeTableID) d.SetId("") return nil @@ -376,16 +377,16 @@ func resourceAwsRouteDelete(d *schema.ResourceData, meta interface{}) error { return nil } - if isAWSErr(err, "InvalidRoute.NotFound", "") { + if isAWSErr(err, tfec2.ErrCodeRouteNotFound, "") { return nil } // Local routes (which may have been imported) cannot be deleted. Remove from state. - if isAWSErr(err, "InvalidParameterValue", "cannot remove local route") { + if isAWSErr(err, tfec2.ErrCodeInvalidParameterValue, "cannot remove local route") { return nil } - if isAWSErr(err, "InvalidParameterException", "") { + if isAWSErr(err, tfec2.ErrCodeInvalidParameterException, "") { return resource.RetryableError(err) } @@ -397,7 +398,7 @@ func resourceAwsRouteDelete(d *schema.ResourceData, meta interface{}) error { _, err = conn.DeleteRoute(input) } - if isAWSErr(err, "InvalidRoute.NotFound", "") { + if isAWSErr(err, tfec2.ErrCodeRouteNotFound, "") { return nil } @@ -501,29 +502,12 @@ func routeDestinationAndTargetAttributes(d *schema.ResourceData) (string, string // TODO Move these to a per-service internal package and auto-generate where possible. // TODO -// readRouteTable returns the route table corresponding to the specified identifier. -// Returns nil if no route table is found. -func readRouteTable(conn *ec2.EC2, identifier string) (*ec2.RouteTable, error) { - input := &ec2.DescribeRouteTablesInput{ - RouteTableIds: aws.StringSlice([]string{identifier}), - } - - output, err := conn.DescribeRouteTables(input) - if err != nil { - return nil, err - } - - if len(output.RouteTables) == 0 || output.RouteTables[0] == nil { - return nil, nil - } - - return output.RouteTables[0], nil -} +type routeFinder func(*ec2.EC2, string, string) (*ec2.Route, error) -// readIpv4Route returns the route corresponding to the specified destination. +// routeByIpv4Destination returns the route corresponding to the specified IPv4 destination. // Returns nil if no route is found. -func readIpv4Route(conn *ec2.EC2, routeTableID, destinationCidr string) (*ec2.Route, error) { - routeTable, err := readRouteTable(conn, routeTableID) +func routeByIpv4Destination(conn *ec2.EC2, routeTableID, destinationCidr string) (*ec2.Route, error) { + routeTable, err := routeTableByID(conn, routeTableID) if err != nil { return nil, err } @@ -537,10 +521,10 @@ func readIpv4Route(conn *ec2.EC2, routeTableID, destinationCidr string) (*ec2.Ro return nil, nil } -// readIpv6Route returns the route corresponding to the specified destination. +// routeByIpv6Destination returns the route corresponding to the specified IPv6 destination. // Returns nil if no route is found. -func readIpv6Route(conn *ec2.EC2, routeTableID, destinationIpv6Cidr string) (*ec2.Route, error) { - routeTable, err := readRouteTable(conn, routeTableID) +func routeByIpv6Destination(conn *ec2.EC2, routeTableID, destinationIpv6Cidr string) (*ec2.Route, error) { + routeTable, err := routeTableByID(conn, routeTableID) if err != nil { return nil, err } diff --git a/aws/resource_aws_route_table.go b/aws/resource_aws_route_table.go index 8ca8e9a51d29..7e6020851a88 100644 --- a/aws/resource_aws_route_table.go +++ b/aws/resource_aws_route_table.go @@ -573,3 +573,26 @@ func resourceAwsRouteTableStateRefreshFunc(conn *ec2.EC2, id string) resource.St return rt, "ready", nil } } + +// TODO +// TODO Move these to a per-service internal package and auto-generate where possible. +// TODO + +// routeTableByID returns the route table corresponding to the specified identifier. +// Returns nil if no route table is found. +func routeTableByID(conn *ec2.EC2, routeTableID string) (*ec2.RouteTable, error) { + input := &ec2.DescribeRouteTablesInput{ + RouteTableIds: aws.StringSlice([]string{routeTableID}), + } + + output, err := conn.DescribeRouteTables(input) + if err != nil { + return nil, err + } + + if len(output.RouteTables) == 0 || output.RouteTables[0] == nil { + return nil, nil + } + + return output.RouteTables[0], nil +} diff --git a/aws/resource_aws_route_test.go b/aws/resource_aws_route_test.go index 4502c1983af3..79894e5dee6a 100644 --- a/aws/resource_aws_route_test.go +++ b/aws/resource_aws_route_test.go @@ -1138,9 +1138,9 @@ func testAccCheckAWSRouteExists(n string, res *ec2.Route) resource.TestCheckFunc var route *ec2.Route var err error if v := rs.Primary.Attributes["destination_cidr_block"]; v != "" { - route, err = readIpv4Route(conn, rs.Primary.Attributes["route_table_id"], v) + route, err = routeByIpv4Destination(conn, rs.Primary.Attributes["route_table_id"], v) } else if v := rs.Primary.Attributes["destination_ipv6_cidr_block"]; v != "" { - route, err = readIpv6Route(conn, rs.Primary.Attributes["route_table_id"], v) + route, err = routeByIpv6Destination(conn, rs.Primary.Attributes["route_table_id"], v) } if err != nil { @@ -1168,9 +1168,9 @@ func testAccCheckAWSRouteDestroy(s *terraform.State) error { var route *ec2.Route var err error if v := rs.Primary.Attributes["destination_cidr_block"]; v != "" { - route, err = readIpv4Route(conn, rs.Primary.Attributes["route_table_id"], v) + route, err = routeByIpv4Destination(conn, rs.Primary.Attributes["route_table_id"], v) } else if v := rs.Primary.Attributes["destination_ipv6_cidr_block"]; v != "" { - route, err = readIpv6Route(conn, rs.Primary.Attributes["route_table_id"], v) + route, err = routeByIpv6Destination(conn, rs.Primary.Attributes["route_table_id"], v) } if route == nil && err == nil { From 96a8b5fddf0beb2d213e5fbfe0ee4135d8b50aee Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 10 Jul 2020 14:08:33 -0400 Subject: [PATCH 37/40] r/aw3s_route: Move route finders to 'aws/internal/service/ec2/finder'. Add 'aws/internal/net/cidr.go'. --- aws/internal/net/cidr.go | 23 ++++++++++ aws/internal/net/cidr_test.go | 26 +++++++++++ aws/internal/service/ec2/finder/finder.go | 56 +++++++++++++++++++++++ aws/resource_aws_route.go | 49 +++----------------- aws/resource_aws_route_table.go | 23 ---------- aws/resource_aws_route_test.go | 9 ++-- aws/validators.go | 1 + 7 files changed, 118 insertions(+), 69 deletions(-) create mode 100644 aws/internal/net/cidr.go create mode 100644 aws/internal/net/cidr_test.go diff --git a/aws/internal/net/cidr.go b/aws/internal/net/cidr.go new file mode 100644 index 000000000000..5d4e8db05259 --- /dev/null +++ b/aws/internal/net/cidr.go @@ -0,0 +1,23 @@ +package net + +import ( + "net" +) + +// CIDRBlocksEqual returns whether or not two CIDR blocks are equal: +// - Both CIDR blocks parse to an IP address and network +// - The string representation of the IP addresses are equal +// - The string representation of the networks are equal +// This function is especially useful for IPv6 CIDR blocks which have multiple valid representations. +func CIDRBlocksEqual(cidr1, cidr2 string) bool { + ip1, ipnet1, err := net.ParseCIDR(cidr1) + if err != nil { + return false + } + ip2, ipnet2, err := net.ParseCIDR(cidr2) + if err != nil { + return false + } + + return ip2.String() == ip1.String() && ipnet2.String() == ipnet1.String() +} diff --git a/aws/internal/net/cidr_test.go b/aws/internal/net/cidr_test.go new file mode 100644 index 000000000000..a557b64a5797 --- /dev/null +++ b/aws/internal/net/cidr_test.go @@ -0,0 +1,26 @@ +package net + +import ( + "testing" +) + +func Test_CIDRBlocksEqual(t *testing.T) { + for _, ts := range []struct { + cidr1 string + cidr2 string + equal bool + }{ + {"10.2.2.0/24", "10.2.2.0/24", true}, + {"10.2.2.0/1234", "10.2.2.0/24", false}, + {"10.2.2.0/24", "10.2.2.0/1234", false}, + {"2001::/15", "2001::/15", true}, + {"::/0", "2001::/15", false}, + {"::/0", "::0/0", true}, + {"", "", false}, + } { + equal := CIDRBlocksEqual(ts.cidr1, ts.cidr2) + if ts.equal != equal { + t.Fatalf("CIDRBlocksEqual(%q, %q) should be: %t", ts.cidr1, ts.cidr2, ts.equal) + } + } +} diff --git a/aws/internal/service/ec2/finder/finder.go b/aws/internal/service/ec2/finder/finder.go index 202a11611443..faae90cf0339 100644 --- a/aws/internal/service/ec2/finder/finder.go +++ b/aws/internal/service/ec2/finder/finder.go @@ -3,6 +3,7 @@ package finder import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" + tfnet "github.com/terraform-providers/terraform-provider-aws/aws/internal/net" tfec2 "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/ec2" ) @@ -54,3 +55,58 @@ func ClientVpnRouteByID(conn *ec2.EC2, routeID string) (*ec2.DescribeClientVpnRo return ClientVpnRoute(conn, endpointID, targetSubnetID, destinationCidr) } + +// RouteTableByID returns the route table corresponding to the specified identifier. +// Returns nil if no route table is found. +func RouteTableByID(conn *ec2.EC2, routeTableID string) (*ec2.RouteTable, error) { + input := &ec2.DescribeRouteTablesInput{ + RouteTableIds: aws.StringSlice([]string{routeTableID}), + } + + output, err := conn.DescribeRouteTables(input) + if err != nil { + return nil, err + } + + if output == nil || len(output.RouteTables) == 0 || output.RouteTables[0] == nil { + return nil, nil + } + + return output.RouteTables[0], nil +} + +type RouteFinder func(*ec2.EC2, string, string) (*ec2.Route, error) + +// RouteByIpv4Destination returns the route corresponding to the specified IPv4 destination. +// Returns nil if no route is found. +func RouteByIpv4Destination(conn *ec2.EC2, routeTableID, destinationCidr string) (*ec2.Route, error) { + routeTable, err := RouteTableByID(conn, routeTableID) + if err != nil { + return nil, err + } + + for _, route := range routeTable.Routes { + if aws.StringValue(route.DestinationCidrBlock) == destinationCidr { + return route, nil + } + } + + return nil, nil +} + +// RouteByIpv6Destination returns the route corresponding to the specified IPv6 destination. +// Returns nil if no route is found. +func RouteByIpv6Destination(conn *ec2.EC2, routeTableID, destinationIpv6Cidr string) (*ec2.Route, error) { + routeTable, err := RouteTableByID(conn, routeTableID) + if err != nil { + return nil, err + } + + for _, route := range routeTable.Routes { + if tfnet.CIDRBlocksEqual(aws.StringValue(route.DestinationIpv6CidrBlock), destinationIpv6Cidr) { + return route, nil + } + } + + return nil, nil +} diff --git a/aws/resource_aws_route.go b/aws/resource_aws_route.go index 561f27590f56..88aaa9dc91b1 100644 --- a/aws/resource_aws_route.go +++ b/aws/resource_aws_route.go @@ -13,6 +13,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/helper/validation" tfec2 "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/ec2" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/ec2/finder" ) func resourceAwsRoute() *schema.Resource { @@ -150,15 +151,15 @@ func resourceAwsRouteCreate(d *schema.ResourceData, meta interface{}) error { RouteTableId: aws.String(routeTableID), } - var routeFinder routeFinder + var routeFinder finder.RouteFinder switch destinationAttr { case "destination_cidr_block": input.DestinationCidrBlock = aws.String(destination) - routeFinder = routeByIpv4Destination + routeFinder = finder.RouteByIpv4Destination case "destination_ipv6_cidr_block": input.DestinationIpv6CidrBlock = aws.String(destination) - routeFinder = routeByIpv6Destination + routeFinder = finder.RouteByIpv6Destination default: return fmt.Errorf("unexpected destination attribute: `%s`", destinationAttr) } @@ -251,13 +252,13 @@ func resourceAwsRouteRead(d *schema.ResourceData, meta interface{}) error { destination := d.Get(destinationAttr).(string) routeTableID := d.Get("route_table_id").(string) - var routeFinder routeFinder + var routeFinder finder.RouteFinder switch destinationAttr { case "destination_cidr_block": - routeFinder = routeByIpv4Destination + routeFinder = finder.RouteByIpv4Destination case "destination_ipv6_cidr_block": - routeFinder = routeByIpv6Destination + routeFinder = finder.RouteByIpv6Destination default: return fmt.Errorf("unexpected destination attribute: `%s`", destinationAttr) } @@ -502,42 +503,6 @@ func routeDestinationAndTargetAttributes(d *schema.ResourceData) (string, string // TODO Move these to a per-service internal package and auto-generate where possible. // TODO -type routeFinder func(*ec2.EC2, string, string) (*ec2.Route, error) - -// routeByIpv4Destination returns the route corresponding to the specified IPv4 destination. -// Returns nil if no route is found. -func routeByIpv4Destination(conn *ec2.EC2, routeTableID, destinationCidr string) (*ec2.Route, error) { - routeTable, err := routeTableByID(conn, routeTableID) - if err != nil { - return nil, err - } - - for _, route := range routeTable.Routes { - if aws.StringValue(route.DestinationCidrBlock) == destinationCidr { - return route, nil - } - } - - return nil, nil -} - -// routeByIpv6Destination returns the route corresponding to the specified IPv6 destination. -// Returns nil if no route is found. -func routeByIpv6Destination(conn *ec2.EC2, routeTableID, destinationIpv6Cidr string) (*ec2.Route, error) { - routeTable, err := routeTableByID(conn, routeTableID) - if err != nil { - return nil, err - } - - for _, route := range routeTable.Routes { - if cidrBlocksEqual(aws.StringValue(route.DestinationIpv6CidrBlock), destinationIpv6Cidr) { - return route, nil - } - } - - return nil, nil -} - func routeCreateID(routeTableID, destination string) string { return fmt.Sprintf("r-%s%d", routeTableID, hashcode.String(destination)) } diff --git a/aws/resource_aws_route_table.go b/aws/resource_aws_route_table.go index 7e6020851a88..8ca8e9a51d29 100644 --- a/aws/resource_aws_route_table.go +++ b/aws/resource_aws_route_table.go @@ -573,26 +573,3 @@ func resourceAwsRouteTableStateRefreshFunc(conn *ec2.EC2, id string) resource.St return rt, "ready", nil } } - -// TODO -// TODO Move these to a per-service internal package and auto-generate where possible. -// TODO - -// routeTableByID returns the route table corresponding to the specified identifier. -// Returns nil if no route table is found. -func routeTableByID(conn *ec2.EC2, routeTableID string) (*ec2.RouteTable, error) { - input := &ec2.DescribeRouteTablesInput{ - RouteTableIds: aws.StringSlice([]string{routeTableID}), - } - - output, err := conn.DescribeRouteTables(input) - if err != nil { - return nil, err - } - - if len(output.RouteTables) == 0 || output.RouteTables[0] == nil { - return nil, nil - } - - return output.RouteTables[0], nil -} diff --git a/aws/resource_aws_route_test.go b/aws/resource_aws_route_test.go index 79894e5dee6a..58931e4d4079 100644 --- a/aws/resource_aws_route_test.go +++ b/aws/resource_aws_route_test.go @@ -9,6 +9,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/helper/acctest" "github.com/hashicorp/terraform-plugin-sdk/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/terraform" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/ec2/finder" ) // IPv4 to Internet Gateway. @@ -1138,9 +1139,9 @@ func testAccCheckAWSRouteExists(n string, res *ec2.Route) resource.TestCheckFunc var route *ec2.Route var err error if v := rs.Primary.Attributes["destination_cidr_block"]; v != "" { - route, err = routeByIpv4Destination(conn, rs.Primary.Attributes["route_table_id"], v) + route, err = finder.RouteByIpv4Destination(conn, rs.Primary.Attributes["route_table_id"], v) } else if v := rs.Primary.Attributes["destination_ipv6_cidr_block"]; v != "" { - route, err = routeByIpv6Destination(conn, rs.Primary.Attributes["route_table_id"], v) + route, err = finder.RouteByIpv6Destination(conn, rs.Primary.Attributes["route_table_id"], v) } if err != nil { @@ -1168,9 +1169,9 @@ func testAccCheckAWSRouteDestroy(s *terraform.State) error { var route *ec2.Route var err error if v := rs.Primary.Attributes["destination_cidr_block"]; v != "" { - route, err = routeByIpv4Destination(conn, rs.Primary.Attributes["route_table_id"], v) + route, err = finder.RouteByIpv4Destination(conn, rs.Primary.Attributes["route_table_id"], v) } else if v := rs.Primary.Attributes["destination_ipv6_cidr_block"]; v != "" { - route, err = routeByIpv6Destination(conn, rs.Primary.Attributes["route_table_id"], v) + route, err = finder.RouteByIpv6Destination(conn, rs.Primary.Attributes["route_table_id"], v) } if route == nil && err == nil { diff --git a/aws/validators.go b/aws/validators.go index 053a92bead94..f01709513448 100644 --- a/aws/validators.go +++ b/aws/validators.go @@ -815,6 +815,7 @@ func validateIpv6CIDRBlock(cidr string) error { return nil } +// TODO Replace with tfnet.CIDRBlocksEqual. // cidrBlocksEqual returns whether or not two CIDR blocks are equal: // - Both CIDR blocks parse to an IP address and network // - The string representation of the IP addresses are equal From ca1bec0db2cd3fefb15fa2b4568153668ce2f18c Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 10 Jul 2020 14:36:21 -0400 Subject: [PATCH 38/40] r/aws_route: Add 'createRoute' function. Acceptance test output: $ make testacc TEST=./aws/ TESTARGS='-run=TestAccAWSRoute_basic' ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws/ -v -count 1 -parallel 20 -run=TestAccAWSRoute_basic -timeout 120m === RUN TestAccAWSRoute_basic === PAUSE TestAccAWSRoute_basic === CONT TestAccAWSRoute_basic --- PASS: TestAccAWSRoute_basic (51.48s) PASS ok github.com/terraform-providers/terraform-provider-aws/aws 51.542s --- aws/resource_aws_route.go | 59 +++++++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 24 deletions(-) diff --git a/aws/resource_aws_route.go b/aws/resource_aws_route.go index 88aaa9dc91b1..c36e6d094f10 100644 --- a/aws/resource_aws_route.go +++ b/aws/resource_aws_route.go @@ -185,31 +185,9 @@ func resourceAwsRouteCreate(d *schema.ResourceData, meta interface{}) error { } log.Printf("[DEBUG] Creating Route: %s", input) - - err = resource.Retry(d.Timeout(schema.TimeoutCreate), func() *resource.RetryError { - _, err = conn.CreateRoute(input) - - if isAWSErr(err, tfec2.ErrCodeInvalidParameterException, "") { - return resource.RetryableError(err) - } - - if isAWSErr(err, tfec2.ErrCodeTransitGatewayNotFound, "") { - return resource.RetryableError(err) - } - - if err != nil { - return resource.NonRetryableError(err) - } - - return nil - }) - - if isResourceTimeoutError(err) { - _, err = conn.CreateRoute(input) - } - + err = createRoute(conn, input, d.Timeout(schema.TimeoutCreate)) if err != nil { - return fmt.Errorf("error creating Route: %s", err) + return err } var route *ec2.Route @@ -506,3 +484,36 @@ func routeDestinationAndTargetAttributes(d *schema.ResourceData) (string, string func routeCreateID(routeTableID, destination string) string { return fmt.Sprintf("r-%s%d", routeTableID, hashcode.String(destination)) } + +// createRoute attempts to create a route. +// The specified eventual consistency timeout is respected. +// Any error is returned. +func createRoute(conn *ec2.EC2, input *ec2.CreateRouteInput, timeout time.Duration) error { + err := resource.Retry(timeout, func() *resource.RetryError { + _, err := conn.CreateRoute(input) + + if isAWSErr(err, tfec2.ErrCodeInvalidParameterException, "") { + return resource.RetryableError(err) + } + + if isAWSErr(err, tfec2.ErrCodeTransitGatewayNotFound, "") { + return resource.RetryableError(err) + } + + if err != nil { + return resource.NonRetryableError(err) + } + + return nil + }) + + if isResourceTimeoutError(err) { + _, err = conn.CreateRoute(input) + } + + if err != nil { + return fmt.Errorf("error creating Route: %s", err) + } + + return nil +} From 20d086ac9a0263b7d1066dfdf9c457c191ab1bef Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Mon, 10 Aug 2020 09:45:23 -0400 Subject: [PATCH 39/40] Use 'testAccAvailableAZsNoOptInDefaultExcludeConfig'. --- aws/resource_aws_route_test.go | 28 ++-------------------------- 1 file changed, 2 insertions(+), 26 deletions(-) diff --git a/aws/resource_aws_route_test.go b/aws/resource_aws_route_test.go index 58931e4d4079..f240548d74f4 100644 --- a/aws/resource_aws_route_test.go +++ b/aws/resource_aws_route_test.go @@ -2019,20 +2019,9 @@ resource "aws_route" "test" { func testAccAWSRouteConfigIpv4FlexiTarget(rName, destinationCidr, targetAttribute, targetValue string) string { return composeConfig( testAccLatestAmazonLinuxHvmEbsAmiConfig(), + testAccAvailableAZsNoOptInDefaultExcludeConfig(), testAccAvailableEc2InstanceTypeForRegion("t3.micro", "t2.micro"), fmt.Sprintf(` -data "aws_availability_zones" "available" { - # Exclude usw2-az4 (us-west-2d) as it has limited instance types. - # IncorrectState: Transit Gateway is not available in availability zone us-west-2d - exclude_zone_ids = ["usw2-az4"] - state = "available" - - filter { - name = "opt-in-status" - values = ["opt-in-not-required"] - } -} - resource "aws_vpc" "test" { cidr_block = "10.1.0.0/16" @@ -2164,20 +2153,9 @@ resource "aws_route" "test" { func testAccAWSRouteConfigIpv6FlexiTarget(rName, destinationCidr, targetAttribute, targetValue string) string { return composeConfig( testAccLatestAmazonLinuxHvmEbsAmiConfig(), + testAccAvailableAZsNoOptInDefaultExcludeConfig(), testAccAvailableEc2InstanceTypeForRegion("t3.micro", "t2.micro"), fmt.Sprintf(` -data "aws_availability_zones" "available" { - # Exclude usw2-az4 (us-west-2d) as it has limited instance types. - # IncorrectState: Transit Gateway is not available in availability zone us-west-2d - exclude_zone_ids = ["usw2-az4"] - state = "available" - - filter { - name = "opt-in-status" - values = ["opt-in-not-required"] - } -} - resource "aws_vpc" "test" { cidr_block = "10.1.0.0/16" assign_generated_ipv6_cidr_block = true @@ -2280,8 +2258,6 @@ resource "aws_route" "test" { `, rName, destinationCidr, targetAttribute, targetValue)) } -// - func testAccAWSRouteConfigIpv4NoRoute(rName string) string { return fmt.Sprintf(` resource "aws_vpc" "test" { From 193e0473f766a97c465bc3fe7ef3eed72cde6da2 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Mon, 10 Aug 2020 18:02:17 -0400 Subject: [PATCH 40/40] Use 'RouteCreateID' in 'internal/service/ec2' package. Acceptance test output: $ make testacc TEST=./aws/ TESTARGS='-run=TestAccAWSRoute_basic' ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws -v -count 1 -parallel 20 -run=TestAccAWSRoute_basic -timeout 120m === RUN TestAccAWSRoute_basic === PAUSE TestAccAWSRoute_basic === CONT TestAccAWSRoute_basic --- PASS: TestAccAWSRoute_basic (40.57s) PASS ok github.com/terraform-providers/terraform-provider-aws/aws 40.615s $ AWS_DEFAULT_REGION=us-east-2 make testacc TEST=./aws/ TESTARGS='-run=TestAccAWSRouteDataSource_basic' ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws -v -count 1 -parallel 20 -run=TestAccAWSRouteDataSource_basic -timeout 120m === RUN TestAccAWSRouteDataSource_basic === PAUSE TestAccAWSRouteDataSource_basic === CONT TestAccAWSRouteDataSource_basic --- PASS: TestAccAWSRouteDataSource_basic (82.16s) PASS ok github.com/terraform-providers/terraform-provider-aws/aws 82.202s --- aws/data_source_aws_route.go | 12 ++++++++---- aws/internal/service/ec2/id.go | 7 +++++++ aws/resource_aws_route.go | 13 ++----------- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/aws/data_source_aws_route.go b/aws/data_source_aws_route.go index a67731fcbb3b..bbbe81aeaf61 100644 --- a/aws/data_source_aws_route.go +++ b/aws/data_source_aws_route.go @@ -4,9 +4,10 @@ import ( "fmt" "log" + "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" - "github.com/hashicorp/terraform-plugin-sdk/helper/hashcode" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + tfec2 "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/ec2" ) func dataSourceAwsRoute() *schema.Resource { @@ -194,10 +195,13 @@ func getRoutes(table *ec2.RouteTable, d *schema.ResourceData) []*ec2.Route { // Helper: Create an ID for a route func resourceAwsRouteID(d *schema.ResourceData, r *ec2.Route) string { + routeTableID := d.Get("route_table_id").(string) - if r.DestinationIpv6CidrBlock != nil && *r.DestinationIpv6CidrBlock != "" { - return fmt.Sprintf("r-%s%d", d.Get("route_table_id").(string), hashcode.String(*r.DestinationIpv6CidrBlock)) + if destination := aws.StringValue(r.DestinationCidrBlock); destination != "" { + return tfec2.RouteCreateID(routeTableID, destination) + } else if destination := aws.StringValue(r.DestinationIpv6CidrBlock); destination != "" { + return tfec2.RouteCreateID(routeTableID, destination) } - return fmt.Sprintf("r-%s%d", d.Get("route_table_id").(string), hashcode.String(*r.DestinationCidrBlock)) + return "" } diff --git a/aws/internal/service/ec2/id.go b/aws/internal/service/ec2/id.go index 824e23eaeade..ea82b270b9f0 100644 --- a/aws/internal/service/ec2/id.go +++ b/aws/internal/service/ec2/id.go @@ -3,6 +3,8 @@ package ec2 import ( "fmt" "strings" + + "github.com/hashicorp/terraform-plugin-sdk/helper/hashcode" ) const clientVpnAuthorizationRuleIDSeparator = "," @@ -49,3 +51,8 @@ func ClientVpnRouteParseID(id string) (string, string, string, error) { fmt.Errorf("unexpected format for ID (%q), expected endpoint-id"+clientVpnRouteIDSeparator+ "target-subnet-id"+clientVpnRouteIDSeparator+"destination-cidr-block", id) } + +// RouteCreateID returns a route resource ID. +func RouteCreateID(routeTableID, destination string) string { + return fmt.Sprintf("r-%s%d", routeTableID, hashcode.String(destination)) +} diff --git a/aws/resource_aws_route.go b/aws/resource_aws_route.go index c36e6d094f10..0559761f0484 100644 --- a/aws/resource_aws_route.go +++ b/aws/resource_aws_route.go @@ -8,7 +8,6 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" - "github.com/hashicorp/terraform-plugin-sdk/helper/hashcode" "github.com/hashicorp/terraform-plugin-sdk/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/helper/validation" @@ -36,7 +35,7 @@ func resourceAwsRoute() *schema.Resource { } else { d.Set("destination_cidr_block", destination) } - d.SetId(fmt.Sprintf("r-%s%d", routeTableID, hashcode.String(destination))) + d.SetId(tfec2.RouteCreateID(routeTableID, destination)) return []*schema.ResourceData{d}, nil }, }, @@ -217,7 +216,7 @@ func resourceAwsRouteCreate(d *schema.ResourceData, meta interface{}) error { return fmt.Errorf("Route in Route Table (%s) with destination (%s) not found", routeTableID, destination) } - d.SetId(routeCreateID(routeTableID, destination)) + d.SetId(tfec2.RouteCreateID(routeTableID, destination)) return resourceAwsRouteRead(d, meta) } @@ -477,14 +476,6 @@ func routeDestinationAndTargetAttributes(d *schema.ResourceData) (string, string return destinationAttr, targetAttr, nil } -// TODO -// TODO Move these to a per-service internal package and auto-generate where possible. -// TODO - -func routeCreateID(routeTableID, destination string) string { - return fmt.Sprintf("r-%s%d", routeTableID, hashcode.String(destination)) -} - // createRoute attempts to create a route. // The specified eventual consistency timeout is respected. // Any error is returned.