From 8638d272a742fc9c733c8b40acdd1c167c995999 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 6 Jan 2021 17:50:17 -0500 Subject: [PATCH 01/25] r/aws_default_route_table: AWS Wavelength support. --- aws/resource_aws_default_route_table.go | 19 ++++-- aws/resource_aws_default_route_table_test.go | 68 +++++++++++++++++++ .../docs/r/default_route_table.html.markdown | 1 + 3 files changed, 84 insertions(+), 4 deletions(-) diff --git a/aws/resource_aws_default_route_table.go b/aws/resource_aws_default_route_table.go index 3ee9440552f0..e4fb553a54d8 100644 --- a/aws/resource_aws_default_route_table.go +++ b/aws/resource_aws_default_route_table.go @@ -50,6 +50,9 @@ func resourceAwsDefaultRouteTable() *schema.Resource { Optional: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ + /// + // Destinations. + /// "cidr_block": { Type: schema.TypeString, Optional: true, @@ -68,6 +71,14 @@ func resourceAwsDefaultRouteTable() *schema.Resource { ), }, + // + // Targets. + // + "carrier_gateway_id": { + Type: schema.TypeString, + Optional: true, + }, + "egress_only_gateway_id": { Type: schema.TypeString, Optional: true, @@ -88,22 +99,22 @@ func resourceAwsDefaultRouteTable() *schema.Resource { Optional: true, }, - "transit_gateway_id": { + "network_interface_id": { Type: schema.TypeString, Optional: true, }, - "vpc_endpoint_id": { + "transit_gateway_id": { Type: schema.TypeString, Optional: true, }, - "vpc_peering_connection_id": { + "vpc_endpoint_id": { Type: schema.TypeString, Optional: true, }, - "network_interface_id": { + "vpc_peering_connection_id": { Type: schema.TypeString, Optional: true, }, diff --git a/aws/resource_aws_default_route_table_test.go b/aws/resource_aws_default_route_table_test.go index 054960468abe..a845e5bea8c2 100644 --- a/aws/resource_aws_default_route_table_test.go +++ b/aws/resource_aws_default_route_table_test.go @@ -404,6 +404,41 @@ func TestAccAWSDefaultRouteTable_ConditionalCidrBlock(t *testing.T) { }) } +func TestAccAWSDefaultRouteTable_IPv4_To_CarrierGateway(t *testing.T) { + var routeTable ec2.RouteTable + resourceName := "aws_default_route_table.test" + cgwResourceName := "aws_ec2_carrier_gateway.test" + rName := acctest.RandomWithPrefix("tf-acc-test") + destinationCidr := "0.0.0.0/0" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSWavelengthZoneAvailable(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckRouteTableDestroy, + Steps: []resource.TestStep{ + { + Config: testAccDefaultRouteTableConfigIpv4CarrierGateway(rName, destinationCidr), + Check: resource.ComposeTestCheckFunc( + testAccCheckRouteTableExists(resourceName, &routeTable), + testAccCheckAWSRouteTableNumberOfRoutes(&routeTable, 2), + testAccMatchResourceAttrRegionalARN(resourceName, "arn", "ec2", regexp.MustCompile(`route-table/.+$`)), + testAccCheckResourceAttrAccountID(resourceName, "owner_id"), + resource.TestCheckResourceAttr(resourceName, "propagating_vgws.#", "0"), + resource.TestCheckResourceAttr(resourceName, "route.#", "1"), + testAccCheckDefaultRouteTableRoute(resourceName, "cidr_block", destinationCidr, "carrier_gateway_id", cgwResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.Name", rName), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func testAccCheckDefaultRouteTableDestroy(s *terraform.State) error { conn := testAccProvider.Meta().(*AWSClient).ec2conn @@ -955,6 +990,39 @@ resource "aws_default_route_table" "test" { `, rName, destinationCidr, destinationIpv6Cidr, ipv6Route) } +func testAccDefaultRouteTableConfigIpv4CarrierGateway(rName, destinationCidr string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { + cidr_block = "10.1.0.0/16" + + tags = { + Name = %[1]q + } +} + +resource "aws_ec2_carrier_gateway" "test" { + vpc_id = aws_vpc.test.id + + tags = { + Name = %[1]q + } +} + +resource "aws_default_route_table" "test" { + default_route_table_id = aws_vpc.test.default_route_table_id + + route { + cidr_block = %[2]q + carrier_gateway_id = aws_ec2_carrier_gateway.test.id + } + + tags = { + Name = %[1]q + } +} +`, rName, destinationCidr) +} + func testAccAWSDefaultRouteTableImportStateIdFunc(resourceName string) resource.ImportStateIdFunc { return func(s *terraform.State) (string, error) { rs, ok := s.RootModule().Resources[resourceName] diff --git a/website/docs/r/default_route_table.html.markdown b/website/docs/r/default_route_table.html.markdown index 1a43ee8ff6db..27b1aa9b7c56 100644 --- a/website/docs/r/default_route_table.html.markdown +++ b/website/docs/r/default_route_table.html.markdown @@ -75,6 +75,7 @@ One of the following destination arguments must be supplied: One of the following target arguments must be supplied: +* `carrier_gateway_id` - (Optional) Identifier of a carrier gateway. This attribute can only be used when the VPC contains a subnet which is associated with a Wavelength Zone. * `egress_only_gateway_id` - (Optional) Identifier of a VPC Egress Only Internet Gateway. * `gateway_id` - (Optional) Identifier of a VPC internet gateway or a virtual private gateway. * `instance_id` - (Optional) Identifier of an EC2 instance. From 052f75d726b01602e9ca378572b1810531b83af6 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 6 Jan 2021 17:54:43 -0500 Subject: [PATCH 02/25] Revert "r/aws_default_route_table: AWS Wavelength support." This reverts commit a32cff5e705ae5c7f841c1743d8f7f84500d0294. --- aws/resource_aws_default_route_table.go | 24 +----- aws/resource_aws_default_route_table_test.go | 73 ------------------- .../docs/r/default_route_table.html.markdown | 1 - 3 files changed, 4 insertions(+), 94 deletions(-) diff --git a/aws/resource_aws_default_route_table.go b/aws/resource_aws_default_route_table.go index e4fb553a54d8..c27960876f05 100644 --- a/aws/resource_aws_default_route_table.go +++ b/aws/resource_aws_default_route_table.go @@ -50,9 +50,6 @@ func resourceAwsDefaultRouteTable() *schema.Resource { Optional: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - /// - // Destinations. - /// "cidr_block": { Type: schema.TypeString, Optional: true, @@ -71,14 +68,6 @@ func resourceAwsDefaultRouteTable() *schema.Resource { ), }, - // - // Targets. - // - "carrier_gateway_id": { - Type: schema.TypeString, - Optional: true, - }, - "egress_only_gateway_id": { Type: schema.TypeString, Optional: true, @@ -99,22 +88,22 @@ func resourceAwsDefaultRouteTable() *schema.Resource { Optional: true, }, - "network_interface_id": { + "transit_gateway_id": { Type: schema.TypeString, Optional: true, }, - "transit_gateway_id": { + "vpc_endpoint_id": { Type: schema.TypeString, Optional: true, }, - "vpc_endpoint_id": { + "vpc_peering_connection_id": { Type: schema.TypeString, Optional: true, }, - "vpc_peering_connection_id": { + "network_interface_id": { Type: schema.TypeString, Optional: true, }, @@ -125,11 +114,6 @@ func resourceAwsDefaultRouteTable() *schema.Resource { "tags": tagsSchema(), - "arn": { - Type: schema.TypeString, - Computed: true, - }, - "owner_id": { Type: schema.TypeString, Computed: true, diff --git a/aws/resource_aws_default_route_table_test.go b/aws/resource_aws_default_route_table_test.go index a845e5bea8c2..33acad385bc0 100644 --- a/aws/resource_aws_default_route_table_test.go +++ b/aws/resource_aws_default_route_table_test.go @@ -38,7 +38,6 @@ func TestAccAWSDefaultRouteTable_basic(t *testing.T) { Config: testAccDefaultRouteTableConfigBasic(rName), Check: resource.ComposeTestCheckFunc( testAccCheckRouteTableExists(resourceName, &routeTable), - testAccMatchResourceAttrRegionalARN(resourceName, "arn", "ec2", regexp.MustCompile(`route-table/.+$`)), testAccCheckResourceAttrAccountID(resourceName, "owner_id"), resource.TestCheckResourceAttr(resourceName, "propagating_vgws.#", "0"), resource.TestCheckResourceAttr(resourceName, "route.#", "0"), @@ -101,7 +100,6 @@ func TestAccAWSDefaultRouteTable_Route_ConfigMode(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckRouteTableExists(resourceName, &routeTable), testAccCheckAWSRouteTableNumberOfRoutes(&routeTable, 2), - testAccMatchResourceAttrRegionalARN(resourceName, "arn", "ec2", regexp.MustCompile(`route-table/.+$`)), testAccCheckResourceAttrAccountID(resourceName, "owner_id"), resource.TestCheckResourceAttr(resourceName, "propagating_vgws.#", "0"), resource.TestCheckResourceAttr(resourceName, "route.#", "1"), @@ -121,7 +119,6 @@ func TestAccAWSDefaultRouteTable_Route_ConfigMode(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckRouteTableExists(resourceName, &routeTable), testAccCheckAWSRouteTableNumberOfRoutes(&routeTable, 2), - testAccMatchResourceAttrRegionalARN(resourceName, "arn", "ec2", regexp.MustCompile(`route-table/.+$`)), testAccCheckResourceAttrAccountID(resourceName, "owner_id"), resource.TestCheckResourceAttr(resourceName, "propagating_vgws.#", "0"), // The route block from the previous step should still be @@ -137,7 +134,6 @@ func TestAccAWSDefaultRouteTable_Route_ConfigMode(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckRouteTableExists(resourceName, &routeTable), testAccCheckAWSRouteTableNumberOfRoutes(&routeTable, 1), - testAccMatchResourceAttrRegionalARN(resourceName, "arn", "ec2", regexp.MustCompile(`route-table/.+$`)), testAccCheckResourceAttrAccountID(resourceName, "owner_id"), resource.TestCheckResourceAttr(resourceName, "propagating_vgws.#", "0"), // This config uses attribute syntax to set zero routes @@ -172,7 +168,6 @@ func TestAccAWSDefaultRouteTable_swap(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckRouteTableExists(resourceName, &routeTable), testAccCheckAWSRouteTableNumberOfRoutes(&routeTable, 2), - testAccMatchResourceAttrRegionalARN(resourceName, "arn", "ec2", regexp.MustCompile(`route-table/.+$`)), testAccCheckResourceAttrAccountID(resourceName, "owner_id"), resource.TestCheckResourceAttr(resourceName, "propagating_vgws.#", "0"), resource.TestCheckResourceAttr(resourceName, "route.#", "1"), @@ -404,41 +399,6 @@ func TestAccAWSDefaultRouteTable_ConditionalCidrBlock(t *testing.T) { }) } -func TestAccAWSDefaultRouteTable_IPv4_To_CarrierGateway(t *testing.T) { - var routeTable ec2.RouteTable - resourceName := "aws_default_route_table.test" - cgwResourceName := "aws_ec2_carrier_gateway.test" - rName := acctest.RandomWithPrefix("tf-acc-test") - destinationCidr := "0.0.0.0/0" - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSWavelengthZoneAvailable(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckRouteTableDestroy, - Steps: []resource.TestStep{ - { - Config: testAccDefaultRouteTableConfigIpv4CarrierGateway(rName, destinationCidr), - Check: resource.ComposeTestCheckFunc( - testAccCheckRouteTableExists(resourceName, &routeTable), - testAccCheckAWSRouteTableNumberOfRoutes(&routeTable, 2), - testAccMatchResourceAttrRegionalARN(resourceName, "arn", "ec2", regexp.MustCompile(`route-table/.+$`)), - testAccCheckResourceAttrAccountID(resourceName, "owner_id"), - resource.TestCheckResourceAttr(resourceName, "propagating_vgws.#", "0"), - resource.TestCheckResourceAttr(resourceName, "route.#", "1"), - testAccCheckDefaultRouteTableRoute(resourceName, "cidr_block", destinationCidr, "carrier_gateway_id", cgwResourceName, "id"), - resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), - resource.TestCheckResourceAttr(resourceName, "tags.Name", rName), - ), - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - }, - }, - }) -} - func testAccCheckDefaultRouteTableDestroy(s *terraform.State) error { conn := testAccProvider.Meta().(*AWSClient).ec2conn @@ -990,39 +950,6 @@ resource "aws_default_route_table" "test" { `, rName, destinationCidr, destinationIpv6Cidr, ipv6Route) } -func testAccDefaultRouteTableConfigIpv4CarrierGateway(rName, destinationCidr string) string { - return fmt.Sprintf(` -resource "aws_vpc" "test" { - cidr_block = "10.1.0.0/16" - - tags = { - Name = %[1]q - } -} - -resource "aws_ec2_carrier_gateway" "test" { - vpc_id = aws_vpc.test.id - - tags = { - Name = %[1]q - } -} - -resource "aws_default_route_table" "test" { - default_route_table_id = aws_vpc.test.default_route_table_id - - route { - cidr_block = %[2]q - carrier_gateway_id = aws_ec2_carrier_gateway.test.id - } - - tags = { - Name = %[1]q - } -} -`, rName, destinationCidr) -} - func testAccAWSDefaultRouteTableImportStateIdFunc(resourceName string) resource.ImportStateIdFunc { return func(s *terraform.State) (string, error) { rs, ok := s.RootModule().Resources[resourceName] diff --git a/website/docs/r/default_route_table.html.markdown b/website/docs/r/default_route_table.html.markdown index 27b1aa9b7c56..1a43ee8ff6db 100644 --- a/website/docs/r/default_route_table.html.markdown +++ b/website/docs/r/default_route_table.html.markdown @@ -75,7 +75,6 @@ One of the following destination arguments must be supplied: One of the following target arguments must be supplied: -* `carrier_gateway_id` - (Optional) Identifier of a carrier gateway. This attribute can only be used when the VPC contains a subnet which is associated with a Wavelength Zone. * `egress_only_gateway_id` - (Optional) Identifier of a VPC Egress Only Internet Gateway. * `gateway_id` - (Optional) Identifier of a VPC internet gateway or a virtual private gateway. * `instance_id` - (Optional) Identifier of an EC2 instance. From 7df1469611cf0b70f94167b37a662837cd7b6f3c Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 6 Jan 2021 18:14:43 -0500 Subject: [PATCH 03/25] r/aws_default_route_table: Add 'arn' attribute. Acceptance test output: $ make testacc TEST=./aws/ TESTARGS='-run=TestAccAWSDefaultRouteTable_' ACCTEST_PARALLELISM=2 ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws -v -count 1 -parallel 2 -run=TestAccAWSDefaultRouteTable_ -timeout 120m === RUN TestAccAWSDefaultRouteTable_basic === PAUSE TestAccAWSDefaultRouteTable_basic === RUN TestAccAWSDefaultRouteTable_disappears_Vpc === PAUSE TestAccAWSDefaultRouteTable_disappears_Vpc === RUN TestAccAWSDefaultRouteTable_Route_ConfigMode === PAUSE TestAccAWSDefaultRouteTable_Route_ConfigMode === RUN TestAccAWSDefaultRouteTable_swap === PAUSE TestAccAWSDefaultRouteTable_swap === RUN TestAccAWSDefaultRouteTable_IPv4_To_TransitGateway === PAUSE TestAccAWSDefaultRouteTable_IPv4_To_TransitGateway === RUN TestAccAWSDefaultRouteTable_IPv4_To_VpcEndpoint === PAUSE TestAccAWSDefaultRouteTable_IPv4_To_VpcEndpoint === RUN TestAccAWSDefaultRouteTable_VpcEndpointAssociation === PAUSE TestAccAWSDefaultRouteTable_VpcEndpointAssociation === RUN TestAccAWSDefaultRouteTable_tags === PAUSE TestAccAWSDefaultRouteTable_tags === RUN TestAccAWSDefaultRouteTable_ConditionalCidrBlock === PAUSE TestAccAWSDefaultRouteTable_ConditionalCidrBlock === CONT TestAccAWSDefaultRouteTable_basic === CONT TestAccAWSDefaultRouteTable_IPv4_To_VpcEndpoint --- PASS: TestAccAWSDefaultRouteTable_basic (29.97s) === CONT TestAccAWSDefaultRouteTable_ConditionalCidrBlock --- PASS: TestAccAWSDefaultRouteTable_ConditionalCidrBlock (54.15s) === CONT TestAccAWSDefaultRouteTable_tags --- PASS: TestAccAWSDefaultRouteTable_tags (52.24s) === CONT TestAccAWSDefaultRouteTable_VpcEndpointAssociation --- PASS: TestAccAWSDefaultRouteTable_VpcEndpointAssociation (44.51s) === CONT TestAccAWSDefaultRouteTable_swap --- PASS: TestAccAWSDefaultRouteTable_swap (91.07s) === CONT TestAccAWSDefaultRouteTable_IPv4_To_TransitGateway === CONT TestAccAWSDefaultRouteTable_Route_ConfigMode --- PASS: TestAccAWSDefaultRouteTable_IPv4_To_VpcEndpoint (323.68s) --- PASS: TestAccAWSDefaultRouteTable_Route_ConfigMode (84.01s) === CONT TestAccAWSDefaultRouteTable_disappears_Vpc --- PASS: TestAccAWSDefaultRouteTable_disappears_Vpc (14.13s) --- PASS: TestAccAWSDefaultRouteTable_IPv4_To_TransitGateway (400.11s) PASS ok github.com/terraform-providers/terraform-provider-aws/aws 672.134s --- aws/resource_aws_default_route_table.go | 5 +++++ aws/resource_aws_default_route_table_test.go | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/aws/resource_aws_default_route_table.go b/aws/resource_aws_default_route_table.go index c27960876f05..3ee9440552f0 100644 --- a/aws/resource_aws_default_route_table.go +++ b/aws/resource_aws_default_route_table.go @@ -114,6 +114,11 @@ func resourceAwsDefaultRouteTable() *schema.Resource { "tags": tagsSchema(), + "arn": { + Type: schema.TypeString, + Computed: true, + }, + "owner_id": { Type: schema.TypeString, Computed: true, diff --git a/aws/resource_aws_default_route_table_test.go b/aws/resource_aws_default_route_table_test.go index 33acad385bc0..054960468abe 100644 --- a/aws/resource_aws_default_route_table_test.go +++ b/aws/resource_aws_default_route_table_test.go @@ -38,6 +38,7 @@ func TestAccAWSDefaultRouteTable_basic(t *testing.T) { Config: testAccDefaultRouteTableConfigBasic(rName), Check: resource.ComposeTestCheckFunc( testAccCheckRouteTableExists(resourceName, &routeTable), + testAccMatchResourceAttrRegionalARN(resourceName, "arn", "ec2", regexp.MustCompile(`route-table/.+$`)), testAccCheckResourceAttrAccountID(resourceName, "owner_id"), resource.TestCheckResourceAttr(resourceName, "propagating_vgws.#", "0"), resource.TestCheckResourceAttr(resourceName, "route.#", "0"), @@ -100,6 +101,7 @@ func TestAccAWSDefaultRouteTable_Route_ConfigMode(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckRouteTableExists(resourceName, &routeTable), testAccCheckAWSRouteTableNumberOfRoutes(&routeTable, 2), + testAccMatchResourceAttrRegionalARN(resourceName, "arn", "ec2", regexp.MustCompile(`route-table/.+$`)), testAccCheckResourceAttrAccountID(resourceName, "owner_id"), resource.TestCheckResourceAttr(resourceName, "propagating_vgws.#", "0"), resource.TestCheckResourceAttr(resourceName, "route.#", "1"), @@ -119,6 +121,7 @@ func TestAccAWSDefaultRouteTable_Route_ConfigMode(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckRouteTableExists(resourceName, &routeTable), testAccCheckAWSRouteTableNumberOfRoutes(&routeTable, 2), + testAccMatchResourceAttrRegionalARN(resourceName, "arn", "ec2", regexp.MustCompile(`route-table/.+$`)), testAccCheckResourceAttrAccountID(resourceName, "owner_id"), resource.TestCheckResourceAttr(resourceName, "propagating_vgws.#", "0"), // The route block from the previous step should still be @@ -134,6 +137,7 @@ func TestAccAWSDefaultRouteTable_Route_ConfigMode(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckRouteTableExists(resourceName, &routeTable), testAccCheckAWSRouteTableNumberOfRoutes(&routeTable, 1), + testAccMatchResourceAttrRegionalARN(resourceName, "arn", "ec2", regexp.MustCompile(`route-table/.+$`)), testAccCheckResourceAttrAccountID(resourceName, "owner_id"), resource.TestCheckResourceAttr(resourceName, "propagating_vgws.#", "0"), // This config uses attribute syntax to set zero routes @@ -168,6 +172,7 @@ func TestAccAWSDefaultRouteTable_swap(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckRouteTableExists(resourceName, &routeTable), testAccCheckAWSRouteTableNumberOfRoutes(&routeTable, 2), + testAccMatchResourceAttrRegionalARN(resourceName, "arn", "ec2", regexp.MustCompile(`route-table/.+$`)), testAccCheckResourceAttrAccountID(resourceName, "owner_id"), resource.TestCheckResourceAttr(resourceName, "propagating_vgws.#", "0"), resource.TestCheckResourceAttr(resourceName, "route.#", "1"), From 621c838acaf29ed29521926a38677842fcf5bd9e Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 27 Jan 2021 17:14:45 -0500 Subject: [PATCH 04/25] r/aws_route_table: 'destination_prefix_list_id' attribute can be specified for managed prefix list destinations. Acceptance test output: $ make testacc TEST=./aws/ TESTARGS='-run=TestAccAWSRouteTable_PrefixList_To_InternetGateway' ACCTEST_PARALLELISM=2 ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws -v -count 1 -parallel 2 -run=TestAccAWSRouteTable_PrefixList_To_InternetGateway -timeout 120m === RUN TestAccAWSRouteTable_PrefixList_To_InternetGateway === PAUSE TestAccAWSRouteTable_PrefixList_To_InternetGateway === CONT TestAccAWSRouteTable_PrefixList_To_InternetGateway --- PASS: TestAccAWSRouteTable_PrefixList_To_InternetGateway (41.36s) PASS ok github.com/terraform-providers/terraform-provider-aws/aws 41.448s --- .changelog/#####.txt | 3 + aws/resource_aws_route_table.go | 25 +++++- aws/resource_aws_route_table_test.go | 109 ++++++++++++++++++++++- website/docs/r/route_table.html.markdown | 1 + 4 files changed, 135 insertions(+), 3 deletions(-) create mode 100644 .changelog/#####.txt diff --git a/.changelog/#####.txt b/.changelog/#####.txt new file mode 100644 index 000000000000..3e10379ea263 --- /dev/null +++ b/.changelog/#####.txt @@ -0,0 +1,3 @@ +```release-notes:enhancement +resource/aws_route_table: Add `destination_prefix_list_id` attribute +``` diff --git a/aws/resource_aws_route_table.go b/aws/resource_aws_route_table.go index 625658fc9ddb..9eaafc7b5296 100644 --- a/aws/resource_aws_route_table.go +++ b/aws/resource_aws_route_table.go @@ -20,6 +20,7 @@ import ( var routeTableValidDestinations = []string{ "cidr_block", "ipv6_cidr_block", + "destination_prefix_list_id", } var routeTableValidTargets = []string{ @@ -90,6 +91,11 @@ func resourceAwsRouteTable() *schema.Resource { ), }, + "destination_prefix_list_id": { + Type: schema.TypeString, + Optional: true, + }, + // // Targets. // @@ -235,7 +241,7 @@ func resourceAwsRouteTableRead(d *schema.ResourceData, meta interface{}) error { continue } - if r.DestinationPrefixListId != nil { + if r.DestinationPrefixListId != nil && strings.HasPrefix(aws.StringValue(r.GatewayId), "vpce-") { // Skipping because VPC endpoint routes are handled separately // See aws_vpc_endpoint continue @@ -249,6 +255,9 @@ func resourceAwsRouteTableRead(d *schema.ResourceData, meta interface{}) error { if r.DestinationIpv6CidrBlock != nil { m["ipv6_cidr_block"] = aws.StringValue(r.DestinationIpv6CidrBlock) } + if r.DestinationPrefixListId != nil { + m["destination_prefix_list_id"] = aws.StringValue(r.DestinationPrefixListId) + } if r.CarrierGatewayId != nil { m["carrier_gateway_id"] = aws.StringValue(r.CarrierGatewayId) } @@ -395,6 +404,12 @@ func resourceAwsRouteTableUpdate(d *schema.ResourceData, meta interface{}) error log.Printf("[INFO] Deleting route from %s: %s", d.Id(), m["cidr_block"].(string)) } + if s, ok := m["destination_prefix_list_id"].(string); ok && s != "" { + deleteOpts.DestinationPrefixListId = aws.String(s) + + log.Printf("[INFO] Deleting route from %s: %s", d.Id(), m["destination_prefix_list_id"].(string)) + } + _, err := conn.DeleteRoute(deleteOpts) if err != nil { return err @@ -448,6 +463,10 @@ func resourceAwsRouteTableUpdate(d *schema.ResourceData, meta interface{}) error opts.DestinationCidrBlock = aws.String(s) } + if s, ok := m["destination_prefix_list_id"].(string); ok && s != "" { + opts.DestinationPrefixListId = aws.String(s) + } + if s, ok := m["gateway_id"].(string); ok && s != "" { opts.GatewayId = aws.String(s) } @@ -589,6 +608,10 @@ func resourceAwsRouteTableHash(v interface{}) int { buf.WriteString(fmt.Sprintf("%s-", v.(string))) } + if v, ok := m["destination_prefix_list_id"]; ok { + buf.WriteString(fmt.Sprintf("%s-", v.(string))) + } + if v, ok := m["gateway_id"]; ok { buf.WriteString(fmt.Sprintf("%s-", v.(string))) } diff --git a/aws/resource_aws_route_table_test.go b/aws/resource_aws_route_table_test.go index 00ea7daeaac1..fcc09e5c547f 100644 --- a/aws/resource_aws_route_table_test.go +++ b/aws/resource_aws_route_table_test.go @@ -1046,6 +1046,42 @@ func TestAccAWSRouteTable_MultipleRoutes(t *testing.T) { }) } +func TestAccAWSRouteTable_PrefixList_To_InternetGateway(t *testing.T) { + var routeTable ec2.RouteTable + resourceName := "aws_route_table.test" + igwResourceName := "aws_internet_gateway.test" + plResourceName := "aws_ec2_managed_prefix_list.test" + rName := acctest.RandomWithPrefix("tf-acc-test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + IDRefreshName: resourceName, + Providers: testAccProviders, + CheckDestroy: testAccCheckRouteTableDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSRouteTableConfigPrefixListInternetGateway(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckRouteTableExists(resourceName, &routeTable), + testAccCheckAWSRouteTableNumberOfRoutes(&routeTable, 2), + testAccMatchResourceAttrRegionalARN(resourceName, "arn", "ec2", regexp.MustCompile(`route-table/.+$`)), + testAccCheckResourceAttrAccountID(resourceName, "owner_id"), + resource.TestCheckResourceAttr(resourceName, "propagating_vgws.#", "0"), + resource.TestCheckResourceAttr(resourceName, "route.#", "1"), + testAccCheckAWSRouteTablePrefixListRoute(resourceName, plResourceName, "gateway_id", igwResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.Name", rName), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func testAccCheckRouteTableExists(n string, v *ec2.RouteTable) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] @@ -1132,6 +1168,35 @@ func testAccCheckAWSRouteTableRoute(resourceName, destinationAttr, destination, } } +func testAccCheckAWSRouteTablePrefixListRoute(resourceName, prefixListResourceName, targetAttr, targetResourceName, targetResourceAttr string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rsPrefixList, ok := s.RootModule().Resources[prefixListResourceName] + if !ok { + return fmt.Errorf("Not found: %s", prefixListResourceName) + } + + destination := rsPrefixList.Primary.Attributes["id"] + if destination == "" { + return fmt.Errorf("Not found: %s.id", prefixListResourceName) + } + + rsTarget, ok := s.RootModule().Resources[targetResourceName] + if !ok { + return fmt.Errorf("Not found: %s", targetResourceName) + } + + target := rsTarget.Primary.Attributes[targetResourceAttr] + if target == "" { + return fmt.Errorf("Not found: %s.%s", targetResourceName, targetResourceAttr) + } + + return resource.TestCheckTypeSetElemNestedAttrs(resourceName, "route.*", map[string]string{ + "destination_prefix_list_id": destination, + targetAttr: target, + })(s) + } +} + // testAccCheckAWSRouteTableWaitForVpcEndpointRoute returns a TestCheckFunc which waits for // a route to the specified VPC endpoint's prefix list to appear in the specified route table. func testAccCheckAWSRouteTableWaitForVpcEndpointRoute(routeTable *ec2.RouteTable, vpce *ec2.VpcEndpoint) resource.TestCheckFunc { @@ -2137,8 +2202,9 @@ resource "aws_route_table" "test" { for_each = local.routes content { # Destination. - cidr_block = (route.value["destination_attr"] == "cidr_block") ? route.value["destination_value"] : null - ipv6_cidr_block = (route.value["destination_attr"] == "ipv6_cidr_block") ? route.value["destination_value"] : null + cidr_block = (route.value["destination_attr"] == "cidr_block") ? route.value["destination_value"] : null + ipv6_cidr_block = (route.value["destination_attr"] == "ipv6_cidr_block") ? route.value["destination_value"] : null + destination_prefix_list_id = (route.value["destination_attr"] == "destination_prefix_list_id") ? route.value["destination_value"] : null # Target. carrier_gateway_id = (route.value["target_attr"] == "carrier_gateway_id") ? route.value["target_value"] : null @@ -2178,3 +2244,42 @@ data "aws_ami" "amzn-ami-nat-instance" { } ` } + +func testAccAWSRouteTableConfigPrefixListInternetGateway(rName string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { + cidr_block = "10.1.0.0/16" + + tags = { + Name = %[1]q + } +} + +resource "aws_internet_gateway" "test" { + vpc_id = aws_vpc.test.id + + tags = { + Name = %[1]q + } +} + +resource "aws_ec2_managed_prefix_list" "test" { + address_family = "IPv4" + max_entries = 1 + name = %[1]q +} + +resource "aws_route_table" "test" { + vpc_id = aws_vpc.test.id + + route { + destination_prefix_list_id = aws_ec2_managed_prefix_list.test.id + gateway_id = aws_internet_gateway.test.id + } + + tags = { + Name = %[1]q + } +} +`, rName) +} diff --git a/website/docs/r/route_table.html.markdown b/website/docs/r/route_table.html.markdown index db094952204c..c2a618642267 100644 --- a/website/docs/r/route_table.html.markdown +++ b/website/docs/r/route_table.html.markdown @@ -81,6 +81,7 @@ One of the following destination arguments must be supplied: * `cidr_block` - (Required) The CIDR block of the route. * `ipv6_cidr_block` - (Optional) The Ipv6 CIDR block of the route. +* `destination_prefix_list_id` - (Optional) The ID of a [managed prefix list](ec2_managed_prefix_list.html) destination of the route. One of the following target arguments must be supplied: From 985bb3c042d63a2ac850014a0c9bc47c5435cbbe Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 27 Jan 2021 17:18:36 -0500 Subject: [PATCH 05/25] Rename CHANGELOG entry file. --- .changelog/{#####.txt => 17319.txt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .changelog/{#####.txt => 17319.txt} (100%) diff --git a/.changelog/#####.txt b/.changelog/17319.txt similarity index 100% rename from .changelog/#####.txt rename to .changelog/17319.txt From ce09aed4b47da5c7004af8f03fb8004475e7ae71 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 27 Jan 2021 17:25:06 -0500 Subject: [PATCH 06/25] Add acceptance test pre-check. --- aws/resource_aws_route_table_test.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/aws/resource_aws_route_table_test.go b/aws/resource_aws_route_table_test.go index fcc09e5c547f..aebd12aee6a0 100644 --- a/aws/resource_aws_route_table_test.go +++ b/aws/resource_aws_route_table_test.go @@ -1054,7 +1054,7 @@ func TestAccAWSRouteTable_PrefixList_To_InternetGateway(t *testing.T) { rName := acctest.RandomWithPrefix("tf-acc-test") resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, + PreCheck: func() { testAccPreCheck(t); testAccPreCheckEc2ManagedPrefixList(t) }, IDRefreshName: resourceName, Providers: testAccProviders, CheckDestroy: testAccCheckRouteTableDestroy, @@ -2202,9 +2202,8 @@ resource "aws_route_table" "test" { for_each = local.routes content { # Destination. - cidr_block = (route.value["destination_attr"] == "cidr_block") ? route.value["destination_value"] : null - ipv6_cidr_block = (route.value["destination_attr"] == "ipv6_cidr_block") ? route.value["destination_value"] : null - destination_prefix_list_id = (route.value["destination_attr"] == "destination_prefix_list_id") ? route.value["destination_value"] : null + cidr_block = (route.value["destination_attr"] == "cidr_block") ? route.value["destination_value"] : null + ipv6_cidr_block = (route.value["destination_attr"] == "ipv6_cidr_block") ? route.value["destination_value"] : null # Target. carrier_gateway_id = (route.value["target_attr"] == "carrier_gateway_id") ? route.value["target_value"] : null From d30ceb5a9aa6dab66347811cace94865d5255fe6 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Thu, 28 Jan 2021 17:53:29 -0500 Subject: [PATCH 07/25] r/aws_default_route_table: 'destination_prefix_list_id' attribute can be specified for managed prefix list destinations. Acceptance test output: $ make testacc TEST=./aws/ TESTARGS='-run=TestAccAWSDefaultRouteTable_PrefixList_To_InternetGateway' ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws -v -count 1 -parallel 20 -run=TestAccAWSDefaultRouteTable_PrefixList_To_InternetGateway -timeout 120m === RUN TestAccAWSDefaultRouteTable_PrefixList_To_InternetGateway === PAUSE TestAccAWSDefaultRouteTable_PrefixList_To_InternetGateway === CONT TestAccAWSDefaultRouteTable_PrefixList_To_InternetGateway --- PASS: TestAccAWSDefaultRouteTable_PrefixList_To_InternetGateway (54.14s) PASS ok github.com/terraform-providers/terraform-provider-aws/aws 54.216s --- .changelog/17319.txt | 4 + aws/resource_aws_default_route_table.go | 35 +++- aws/resource_aws_default_route_table_test.go | 163 +++++++++++++++++- .../docs/r/default_route_table.html.markdown | 1 + 4 files changed, 190 insertions(+), 13 deletions(-) diff --git a/.changelog/17319.txt b/.changelog/17319.txt index 3e10379ea263..3d552e4ac78d 100644 --- a/.changelog/17319.txt +++ b/.changelog/17319.txt @@ -1,3 +1,7 @@ +```release-notes:enhancement +resource/aws_default_route_table: Add `destination_prefix_list_id` attribute +``` + ```release-notes:enhancement resource/aws_route_table: Add `destination_prefix_list_id` attribute ``` diff --git a/aws/resource_aws_default_route_table.go b/aws/resource_aws_default_route_table.go index 3ee9440552f0..9297e71ab633 100644 --- a/aws/resource_aws_default_route_table.go +++ b/aws/resource_aws_default_route_table.go @@ -3,6 +3,7 @@ package aws import ( "fmt" "log" + "strings" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" @@ -50,6 +51,9 @@ func resourceAwsDefaultRouteTable() *schema.Resource { Optional: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ + /// + // Destinations. + /// "cidr_block": { Type: schema.TypeString, Optional: true, @@ -68,6 +72,14 @@ func resourceAwsDefaultRouteTable() *schema.Resource { ), }, + "destination_prefix_list_id": { + Type: schema.TypeString, + Optional: true, + }, + + // + // Targets. + // "egress_only_gateway_id": { Type: schema.TypeString, Optional: true, @@ -88,22 +100,22 @@ func resourceAwsDefaultRouteTable() *schema.Resource { Optional: true, }, - "transit_gateway_id": { + "network_interface_id": { Type: schema.TypeString, Optional: true, }, - "vpc_endpoint_id": { + "transit_gateway_id": { Type: schema.TypeString, Optional: true, }, - "vpc_peering_connection_id": { + "vpc_endpoint_id": { Type: schema.TypeString, Optional: true, }, - "network_interface_id": { + "vpc_peering_connection_id": { Type: schema.TypeString, Optional: true, }, @@ -240,7 +252,8 @@ func revokeAllRouteTableRules(defaultRouteTableId string, meta interface{}) erro if r.GatewayId != nil && *r.GatewayId == "local" { continue } - if r.DestinationPrefixListId != nil { + + if r.DestinationPrefixListId != nil && strings.HasPrefix(aws.StringValue(r.GatewayId), "vpce-") { // Skipping because VPC endpoint routes are handled separately // See aws_vpc_endpoint continue @@ -272,6 +285,18 @@ func revokeAllRouteTableRules(defaultRouteTableId string, meta interface{}) erro } } + if r.DestinationPrefixListId != nil { + log.Printf( + "[INFO] Deleting route from %s: %s", + defaultRouteTableId, *r.DestinationPrefixListId) + _, err := conn.DeleteRoute(&ec2.DeleteRouteInput{ + RouteTableId: aws.String(defaultRouteTableId), + DestinationPrefixListId: r.DestinationPrefixListId, + }) + if err != nil { + return err + } + } } return nil diff --git a/aws/resource_aws_default_route_table_test.go b/aws/resource_aws_default_route_table_test.go index 054960468abe..2ec2e8d45951 100644 --- a/aws/resource_aws_default_route_table_test.go +++ b/aws/resource_aws_default_route_table_test.go @@ -404,6 +404,46 @@ func TestAccAWSDefaultRouteTable_ConditionalCidrBlock(t *testing.T) { }) } +func TestAccAWSDefaultRouteTable_PrefixList_To_InternetGateway(t *testing.T) { + var routeTable ec2.RouteTable + resourceName := "aws_default_route_table.test" + igwResourceName := "aws_internet_gateway.test" + plResourceName := "aws_ec2_managed_prefix_list.test" + rName := acctest.RandomWithPrefix("tf-acc-test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccPreCheckEc2ManagedPrefixList(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckRouteTableDestroy, + Steps: []resource.TestStep{ + { + Config: testAccDefaultRouteTableConfigPrefixListInternetGateway(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckRouteTableExists(resourceName, &routeTable), + testAccCheckAWSRouteTableNumberOfRoutes(&routeTable, 2), + resource.TestCheckResourceAttr(resourceName, "route.#", "1"), + testAccCheckDefaultRouteTablePrefixListRoute(resourceName, plResourceName, "gateway_id", igwResourceName, "id"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateIdFunc: testAccAWSDefaultRouteTableImportStateIdFunc(resourceName), + ImportStateVerify: true, + }, + // Default route tables do not currently have a method to remove routes during deletion. + // Managed prefix lists will not delete unless the route is removed prior, otherwise will error: + // "unexpected state 'delete-failed', wanted target 'delete-complete'" + { + Config: testAccDefaultRouteTableConfigPrefixListInternetGatewayNoRoute(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckRouteTableExists(resourceName, &routeTable), + ), + }, + }, + }) +} + func testAccCheckDefaultRouteTableDestroy(s *terraform.State) error { conn := testAccProvider.Meta().(*AWSClient).ec2conn @@ -452,6 +492,46 @@ func testAccCheckDefaultRouteTableRoute(resourceName, destinationAttr, destinati } } +func testAccCheckDefaultRouteTablePrefixListRoute(resourceName, prefixListResourceName, targetAttr, targetResourceName, targetResourceAttr string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rsPrefixList, ok := s.RootModule().Resources[prefixListResourceName] + if !ok { + return fmt.Errorf("Not found: %s", prefixListResourceName) + } + + destination := rsPrefixList.Primary.Attributes["id"] + if destination == "" { + return fmt.Errorf("Not found: %s.id", prefixListResourceName) + } + + rsTarget, ok := s.RootModule().Resources[targetResourceName] + if !ok { + return fmt.Errorf("Not found: %s", targetResourceName) + } + + target := rsTarget.Primary.Attributes[targetResourceAttr] + if target == "" { + return fmt.Errorf("Not found: %s.%s", targetResourceName, targetResourceAttr) + } + + return resource.TestCheckTypeSetElemNestedAttrs(resourceName, "route.*", map[string]string{ + "destination_prefix_list_id": destination, + targetAttr: target, + })(s) + } +} + +func testAccAWSDefaultRouteTableImportStateIdFunc(resourceName string) resource.ImportStateIdFunc { + return func(s *terraform.State) (string, error) { + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return "", fmt.Errorf("Not found: %s", resourceName) + } + + return rs.Primary.Attributes["vpc_id"], nil + } +} + func testAccDefaultRouteTableConfigDefaultRouteTableId(defaultRouteTableId string) string { return fmt.Sprintf(` resource "aws_default_route_table" "test" { @@ -955,13 +1035,80 @@ resource "aws_default_route_table" "test" { `, rName, destinationCidr, destinationIpv6Cidr, ipv6Route) } -func testAccAWSDefaultRouteTableImportStateIdFunc(resourceName string) resource.ImportStateIdFunc { - return func(s *terraform.State) (string, error) { - rs, ok := s.RootModule().Resources[resourceName] - if !ok { - return "", fmt.Errorf("Not found: %s", resourceName) - } +func testAccDefaultRouteTableConfigPrefixListInternetGateway(rName string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { + cidr_block = "10.1.0.0/16" - return rs.Primary.Attributes["vpc_id"], nil - } + tags = { + Name = %[1]q + } +} + +resource "aws_internet_gateway" "test" { + vpc_id = aws_vpc.test.id + + tags = { + Name = %[1]q + } +} + +resource "aws_ec2_managed_prefix_list" "test" { + address_family = "IPv4" + max_entries = 1 + name = %[1]q +} + +resource "aws_default_route_table" "test" { + default_route_table_id = aws_vpc.test.default_route_table_id + + route { + destination_prefix_list_id = aws_ec2_managed_prefix_list.test.id + gateway_id = aws_internet_gateway.test.id + } + + tags = { + Name = %[1]q + } +} +`, rName) +} + +func testAccDefaultRouteTableConfigPrefixListInternetGatewayNoRoute(rName string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { + cidr_block = "10.1.0.0/16" + + tags = { + Name = %[1]q + } +} + +resource "aws_internet_gateway" "test" { + vpc_id = aws_vpc.test.id + + tags = { + Name = %[1]q + } +} + +resource "aws_ec2_managed_prefix_list" "test" { + address_family = "IPv4" + max_entries = 1 + name = %[1]q +} + +resource "aws_default_route_table" "test" { + default_route_table_id = aws_vpc.test.default_route_table_id + + route { + cidr_block = "0.0.0.0/0" + gateway_id = aws_internet_gateway.test.id + } + + tags = { + Name = %[1]q + } +} +`, rName) } diff --git a/website/docs/r/default_route_table.html.markdown b/website/docs/r/default_route_table.html.markdown index 1a43ee8ff6db..23f5199cbe95 100644 --- a/website/docs/r/default_route_table.html.markdown +++ b/website/docs/r/default_route_table.html.markdown @@ -72,6 +72,7 @@ One of the following destination arguments must be supplied: * `cidr_block` - (Required) The CIDR block of the route. * `ipv6_cidr_block` - (Optional) The Ipv6 CIDR block of the route +* `destination_prefix_list_id` - (Optional) The ID of a [managed prefix list](ec2_managed_prefix_list.html) destination of the route. One of the following target arguments must be supplied: From d8d5437a1fd01f94504abaa60f5633f5bb2272d7 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 26 Mar 2021 15:02:29 -0400 Subject: [PATCH 08/25] r/aws_(default)_route_table: Add 'ErrorCheck' to new acceptance tests. Acceptance test output: $ make testacc TEST=./aws/ TESTARGS='-run=TestAccAWSRouteTable_\|TestAccAWSDefaultRouteTable_' ACCTEST_PARALLELISM=2 ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws -v -count 1 -parallel 2 -run=TestAccAWSRouteTable_\|TestAccAWSDefaultRouteTable_ -timeout 180m === RUN TestAccAWSDefaultRouteTable_basic === PAUSE TestAccAWSDefaultRouteTable_basic === RUN TestAccAWSDefaultRouteTable_disappears_Vpc === PAUSE TestAccAWSDefaultRouteTable_disappears_Vpc === RUN TestAccAWSDefaultRouteTable_Route_ConfigMode === PAUSE TestAccAWSDefaultRouteTable_Route_ConfigMode === RUN TestAccAWSDefaultRouteTable_swap === PAUSE TestAccAWSDefaultRouteTable_swap === RUN TestAccAWSDefaultRouteTable_IPv4_To_TransitGateway === PAUSE TestAccAWSDefaultRouteTable_IPv4_To_TransitGateway === RUN TestAccAWSDefaultRouteTable_IPv4_To_VpcEndpoint === PAUSE TestAccAWSDefaultRouteTable_IPv4_To_VpcEndpoint === RUN TestAccAWSDefaultRouteTable_VpcEndpointAssociation === PAUSE TestAccAWSDefaultRouteTable_VpcEndpointAssociation === RUN TestAccAWSDefaultRouteTable_tags === PAUSE TestAccAWSDefaultRouteTable_tags === RUN TestAccAWSDefaultRouteTable_ConditionalCidrBlock === PAUSE TestAccAWSDefaultRouteTable_ConditionalCidrBlock === RUN TestAccAWSDefaultRouteTable_PrefixList_To_InternetGateway === PAUSE TestAccAWSDefaultRouteTable_PrefixList_To_InternetGateway === RUN TestAccAWSRouteTable_basic === PAUSE TestAccAWSRouteTable_basic === RUN TestAccAWSRouteTable_disappears === PAUSE TestAccAWSRouteTable_disappears === RUN TestAccAWSRouteTable_disappears_SubnetAssociation === PAUSE TestAccAWSRouteTable_disappears_SubnetAssociation === RUN TestAccAWSRouteTable_IPv4_To_InternetGateway === PAUSE TestAccAWSRouteTable_IPv4_To_InternetGateway === RUN TestAccAWSRouteTable_IPv4_To_Instance === PAUSE TestAccAWSRouteTable_IPv4_To_Instance === RUN TestAccAWSRouteTable_IPv6_To_EgressOnlyInternetGateway === PAUSE TestAccAWSRouteTable_IPv6_To_EgressOnlyInternetGateway === RUN TestAccAWSRouteTable_tags === PAUSE TestAccAWSRouteTable_tags === RUN TestAccAWSRouteTable_RequireRouteDestination === PAUSE TestAccAWSRouteTable_RequireRouteDestination === RUN TestAccAWSRouteTable_RequireRouteTarget === PAUSE TestAccAWSRouteTable_RequireRouteTarget === RUN TestAccAWSRouteTable_Route_ConfigMode === PAUSE TestAccAWSRouteTable_Route_ConfigMode === RUN TestAccAWSRouteTable_IPv4_To_TransitGateway === PAUSE TestAccAWSRouteTable_IPv4_To_TransitGateway === RUN TestAccAWSRouteTable_IPv4_To_VpcEndpoint === PAUSE TestAccAWSRouteTable_IPv4_To_VpcEndpoint === RUN TestAccAWSRouteTable_IPv4_To_CarrierGateway === PAUSE TestAccAWSRouteTable_IPv4_To_CarrierGateway === RUN TestAccAWSRouteTable_IPv4_To_LocalGateway === PAUSE TestAccAWSRouteTable_IPv4_To_LocalGateway === RUN TestAccAWSRouteTable_IPv4_To_VpcPeeringConnection === PAUSE TestAccAWSRouteTable_IPv4_To_VpcPeeringConnection === RUN TestAccAWSRouteTable_vgwRoutePropagation === PAUSE TestAccAWSRouteTable_vgwRoutePropagation === RUN TestAccAWSRouteTable_ConditionalCidrBlock === PAUSE TestAccAWSRouteTable_ConditionalCidrBlock === RUN TestAccAWSRouteTable_IPv4_To_NatGateway === PAUSE TestAccAWSRouteTable_IPv4_To_NatGateway === RUN TestAccAWSRouteTable_IPv6_To_NetworkInterface_Unattached === PAUSE TestAccAWSRouteTable_IPv6_To_NetworkInterface_Unattached === RUN TestAccAWSRouteTable_VpcMultipleCidrs === PAUSE TestAccAWSRouteTable_VpcMultipleCidrs === RUN TestAccAWSRouteTable_VpcClassicLink === PAUSE TestAccAWSRouteTable_VpcClassicLink === RUN TestAccAWSRouteTable_GatewayVpcEndpoint === PAUSE TestAccAWSRouteTable_GatewayVpcEndpoint === RUN TestAccAWSRouteTable_MultipleRoutes === PAUSE TestAccAWSRouteTable_MultipleRoutes === RUN TestAccAWSRouteTable_PrefixList_To_InternetGateway === PAUSE TestAccAWSRouteTable_PrefixList_To_InternetGateway === CONT TestAccAWSDefaultRouteTable_basic === CONT TestAccAWSRouteTable_RequireRouteTarget --- PASS: TestAccAWSRouteTable_RequireRouteTarget (13.47s) === CONT TestAccAWSRouteTable_PrefixList_To_InternetGateway --- PASS: TestAccAWSDefaultRouteTable_basic (33.14s) === CONT TestAccAWSRouteTable_MultipleRoutes --- PASS: TestAccAWSRouteTable_PrefixList_To_InternetGateway (42.18s) === CONT TestAccAWSRouteTable_GatewayVpcEndpoint --- PASS: TestAccAWSRouteTable_GatewayVpcEndpoint (55.61s) === CONT TestAccAWSRouteTable_VpcClassicLink --- PASS: TestAccAWSRouteTable_VpcClassicLink (23.84s) === CONT TestAccAWSRouteTable_VpcMultipleCidrs --- PASS: TestAccAWSRouteTable_VpcMultipleCidrs (44.73s) === CONT TestAccAWSRouteTable_IPv6_To_NetworkInterface_Unattached --- PASS: TestAccAWSRouteTable_MultipleRoutes (153.22s) === CONT TestAccAWSRouteTable_IPv4_To_NatGateway --- PASS: TestAccAWSRouteTable_IPv6_To_NetworkInterface_Unattached (64.51s) === CONT TestAccAWSRouteTable_ConditionalCidrBlock --- PASS: TestAccAWSRouteTable_ConditionalCidrBlock (53.93s) === CONT TestAccAWSRouteTable_vgwRoutePropagation --- PASS: TestAccAWSRouteTable_vgwRoutePropagation (86.30s) === CONT TestAccAWSRouteTable_IPv4_To_VpcPeeringConnection --- PASS: TestAccAWSRouteTable_IPv4_To_VpcPeeringConnection (26.74s) === CONT TestAccAWSRouteTable_IPv4_To_LocalGateway data_source_aws_outposts_outposts_test.go:67: skipping since no Outposts found --- SKIP: TestAccAWSRouteTable_IPv4_To_LocalGateway (0.67s) === CONT TestAccAWSRouteTable_IPv4_To_CarrierGateway --- PASS: TestAccAWSRouteTable_IPv4_To_NatGateway (235.45s) === CONT TestAccAWSRouteTable_IPv4_To_VpcEndpoint --- PASS: TestAccAWSRouteTable_IPv4_To_CarrierGateway (26.19s) === CONT TestAccAWSRouteTable_IPv4_To_TransitGateway === CONT TestAccAWSRouteTable_Route_ConfigMode --- PASS: TestAccAWSRouteTable_IPv4_To_VpcEndpoint (261.01s) --- PASS: TestAccAWSRouteTable_Route_ConfigMode (71.61s) === CONT TestAccAWSDefaultRouteTable_PrefixList_To_InternetGateway --- PASS: TestAccAWSRouteTable_IPv4_To_TransitGateway (359.96s) === CONT TestAccAWSRouteTable_RequireRouteDestination --- PASS: TestAccAWSDefaultRouteTable_PrefixList_To_InternetGateway (54.98s) === CONT TestAccAWSRouteTable_tags --- PASS: TestAccAWSRouteTable_tags (68.33s) === CONT TestAccAWSRouteTable_IPv6_To_EgressOnlyInternetGateway --- PASS: TestAccAWSRouteTable_IPv6_To_EgressOnlyInternetGateway (48.66s) === CONT TestAccAWSRouteTable_IPv4_To_Instance --- PASS: TestAccAWSRouteTable_IPv4_To_Instance (81.54s) === CONT TestAccAWSRouteTable_IPv4_To_InternetGateway --- PASS: TestAccAWSRouteTable_IPv4_To_InternetGateway (63.41s) === CONT TestAccAWSRouteTable_disappears_SubnetAssociation --- PASS: TestAccAWSRouteTable_disappears_SubnetAssociation (24.67s) === CONT TestAccAWSRouteTable_disappears --- PASS: TestAccAWSRouteTable_RequireRouteDestination (304.50s) === CONT TestAccAWSRouteTable_basic === CONT TestAccAWSDefaultRouteTable_IPv4_To_VpcEndpoint --- PASS: TestAccAWSRouteTable_disappears (20.62s) --- PASS: TestAccAWSRouteTable_basic (22.67s) === CONT TestAccAWSDefaultRouteTable_ConditionalCidrBlock --- PASS: TestAccAWSDefaultRouteTable_ConditionalCidrBlock (55.10s) === CONT TestAccAWSDefaultRouteTable_tags --- PASS: TestAccAWSDefaultRouteTable_tags (53.67s) === CONT TestAccAWSDefaultRouteTable_VpcEndpointAssociation --- PASS: TestAccAWSDefaultRouteTable_VpcEndpointAssociation (44.59s) === CONT TestAccAWSDefaultRouteTable_swap --- PASS: TestAccAWSDefaultRouteTable_swap (102.85s) === CONT TestAccAWSDefaultRouteTable_IPv4_To_TransitGateway --- PASS: TestAccAWSDefaultRouteTable_IPv4_To_VpcEndpoint (278.89s) === CONT TestAccAWSDefaultRouteTable_Route_ConfigMode --- PASS: TestAccAWSDefaultRouteTable_Route_ConfigMode (94.74s) === CONT TestAccAWSDefaultRouteTable_disappears_Vpc --- PASS: TestAccAWSDefaultRouteTable_disappears_Vpc (15.28s) --- PASS: TestAccAWSDefaultRouteTable_IPv4_To_TransitGateway (369.81s) PASS ok github.com/terraform-providers/terraform-provider-aws/aws 1751.431s --- aws/resource_aws_default_route_table_test.go | 1 + aws/resource_aws_route_table_test.go | 1 + 2 files changed, 2 insertions(+) diff --git a/aws/resource_aws_default_route_table_test.go b/aws/resource_aws_default_route_table_test.go index 2ec2e8d45951..b838d893d8d3 100644 --- a/aws/resource_aws_default_route_table_test.go +++ b/aws/resource_aws_default_route_table_test.go @@ -413,6 +413,7 @@ func TestAccAWSDefaultRouteTable_PrefixList_To_InternetGateway(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t); testAccPreCheckEc2ManagedPrefixList(t) }, + ErrorCheck: testAccErrorCheck(t, ec2.EndpointsID), Providers: testAccProviders, CheckDestroy: testAccCheckRouteTableDestroy, Steps: []resource.TestStep{ diff --git a/aws/resource_aws_route_table_test.go b/aws/resource_aws_route_table_test.go index aebd12aee6a0..8839a03103c7 100644 --- a/aws/resource_aws_route_table_test.go +++ b/aws/resource_aws_route_table_test.go @@ -1055,6 +1055,7 @@ func TestAccAWSRouteTable_PrefixList_To_InternetGateway(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t); testAccPreCheckEc2ManagedPrefixList(t) }, + ErrorCheck: testAccErrorCheck(t, ec2.EndpointsID), IDRefreshName: resourceName, Providers: testAccProviders, CheckDestroy: testAccCheckRouteTableDestroy, From 5c59677f3cfb2c3ba94825f71ae60ee4945888be Mon Sep 17 00:00:00 2001 From: Greg Piper <7915411+gpiper14@users.noreply.github.com> Date: Fri, 8 Mar 2019 17:00:14 -0500 Subject: [PATCH 09/25] Fix issue when creating default route table that has a route propagation --- aws/resource_aws_default_route_table.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/aws/resource_aws_default_route_table.go b/aws/resource_aws_default_route_table.go index 9297e71ab633..5cb43bd921ef 100644 --- a/aws/resource_aws_default_route_table.go +++ b/aws/resource_aws_default_route_table.go @@ -258,6 +258,10 @@ func revokeAllRouteTableRules(defaultRouteTableId string, meta interface{}) erro // See aws_vpc_endpoint continue } + if *r.Origin == "EnableVgwRoutePropagation" { + // Skipping because its from a Gateway associations. Already removed above + continue + } if r.DestinationCidrBlock != nil { log.Printf( From 9be052296727845e8a94c9a0764a6eb53eda29a3 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Sun, 28 Mar 2021 19:06:51 -0400 Subject: [PATCH 10/25] r/aws_default_route_table: Add 'TestAccAWSDefaultRouteTable_RevokeExistingRules'. Acceptance test output: $ make testacc TEST=./aws/ TESTARGS='-run=TestAccAWSDefaultRouteTable_' ACCTEST_PARALLELISM=2 ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws -v -count 1 -parallel 2 -run=TestAccAWSDefaultRouteTable_ -timeout 180m === RUN TestAccAWSDefaultRouteTable_basic === PAUSE TestAccAWSDefaultRouteTable_basic === RUN TestAccAWSDefaultRouteTable_disappears_Vpc === PAUSE TestAccAWSDefaultRouteTable_disappears_Vpc === RUN TestAccAWSDefaultRouteTable_Route_ConfigMode === PAUSE TestAccAWSDefaultRouteTable_Route_ConfigMode === RUN TestAccAWSDefaultRouteTable_swap === PAUSE TestAccAWSDefaultRouteTable_swap === RUN TestAccAWSDefaultRouteTable_IPv4_To_TransitGateway === PAUSE TestAccAWSDefaultRouteTable_IPv4_To_TransitGateway === RUN TestAccAWSDefaultRouteTable_IPv4_To_VpcEndpoint === PAUSE TestAccAWSDefaultRouteTable_IPv4_To_VpcEndpoint === RUN TestAccAWSDefaultRouteTable_VpcEndpointAssociation === PAUSE TestAccAWSDefaultRouteTable_VpcEndpointAssociation === RUN TestAccAWSDefaultRouteTable_tags === PAUSE TestAccAWSDefaultRouteTable_tags === RUN TestAccAWSDefaultRouteTable_ConditionalCidrBlock === PAUSE TestAccAWSDefaultRouteTable_ConditionalCidrBlock === RUN TestAccAWSDefaultRouteTable_PrefixList_To_InternetGateway === PAUSE TestAccAWSDefaultRouteTable_PrefixList_To_InternetGateway === RUN TestAccAWSDefaultRouteTable_RevokeExistingRules === PAUSE TestAccAWSDefaultRouteTable_RevokeExistingRules === CONT TestAccAWSDefaultRouteTable_basic === CONT TestAccAWSDefaultRouteTable_VpcEndpointAssociation --- PASS: TestAccAWSDefaultRouteTable_basic (27.81s) === CONT TestAccAWSDefaultRouteTable_RevokeExistingRules --- PASS: TestAccAWSDefaultRouteTable_VpcEndpointAssociation (47.64s) === CONT TestAccAWSDefaultRouteTable_PrefixList_To_InternetGateway --- PASS: TestAccAWSDefaultRouteTable_PrefixList_To_InternetGateway (54.34s) === CONT TestAccAWSDefaultRouteTable_ConditionalCidrBlock --- PASS: TestAccAWSDefaultRouteTable_RevokeExistingRules (104.87s) === CONT TestAccAWSDefaultRouteTable_tags --- PASS: TestAccAWSDefaultRouteTable_ConditionalCidrBlock (55.49s) === CONT TestAccAWSDefaultRouteTable_swap --- PASS: TestAccAWSDefaultRouteTable_tags (55.05s) === CONT TestAccAWSDefaultRouteTable_IPv4_To_VpcEndpoint --- PASS: TestAccAWSDefaultRouteTable_swap (101.23s) === CONT TestAccAWSDefaultRouteTable_IPv4_To_TransitGateway --- PASS: TestAccAWSDefaultRouteTable_IPv4_To_VpcEndpoint (318.61s) === CONT TestAccAWSDefaultRouteTable_Route_ConfigMode --- PASS: TestAccAWSDefaultRouteTable_Route_ConfigMode (93.98s) === CONT TestAccAWSDefaultRouteTable_disappears_Vpc --- PASS: TestAccAWSDefaultRouteTable_disappears_Vpc (14.50s) --- PASS: TestAccAWSDefaultRouteTable_IPv4_To_TransitGateway (400.86s) PASS ok github.com/terraform-providers/terraform-provider-aws/aws 659.684s --- aws/resource_aws_default_route_table.go | 78 +++---- aws/resource_aws_default_route_table_test.go | 221 ++++++++++++++----- 2 files changed, 186 insertions(+), 113 deletions(-) diff --git a/aws/resource_aws_default_route_table.go b/aws/resource_aws_default_route_table.go index 5cb43bd921ef..fdf9f14d6862 100644 --- a/aws/resource_aws_default_route_table.go +++ b/aws/resource_aws_default_route_table.go @@ -10,6 +10,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/terraform-providers/terraform-provider-aws/aws/internal/keyvaluetags" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/ec2/finder" ) func resourceAwsDefaultRouteTable() *schema.Resource { @@ -140,31 +141,28 @@ func resourceAwsDefaultRouteTable() *schema.Resource { } func resourceAwsDefaultRouteTableCreate(d *schema.ResourceData, meta interface{}) error { - d.SetId(d.Get("default_route_table_id").(string)) - conn := meta.(*AWSClient).ec2conn - rtRaw, _, err := resourceAwsRouteTableStateRefreshFunc(conn, d.Id())() + routeTableID := d.Get("default_route_table_id").(string) + + routeTable, err := finder.RouteTableByID(conn, routeTableID) + if err != nil { - return fmt.Errorf("error reading EC2 Default Route Table (%s): %s", d.Id(), err) - } - if rtRaw == nil { - return fmt.Errorf("error reading EC2 Default Route Table (%s): not found", d.Id()) + return fmt.Errorf("error reading EC2 Default Route Table (%s): %w", routeTableID, err) } - rt := rtRaw.(*ec2.RouteTable) - - d.Set("vpc_id", rt.VpcId) + d.SetId(routeTableID) + d.Set("vpc_id", routeTable.VpcId) // revoke all default and pre-existing routes on the default route table. // In the UPDATE method, we'll apply only the rules in the configuration. log.Printf("[DEBUG] Revoking default routes for Default Route Table for %s", d.Id()) - if err := revokeAllRouteTableRules(d.Id(), meta); err != nil { + if err := revokeAllRouteTableRules(conn, routeTable); err != nil { return err } if v := d.Get("tags").(map[string]interface{}); len(v) > 0 { if err := keyvaluetags.Ec2CreateTags(conn, d.Id(), v); err != nil { - return fmt.Errorf("error adding tags: %s", err) + return fmt.Errorf("error adding tags: %w", err) } } @@ -215,41 +213,27 @@ func resourceAwsDefaultRouteTableDelete(d *schema.ResourceData, meta interface{} // revokeAllRouteTableRules revoke all routes on the Default Route Table // This should only be ran once at creation time of this resource -func revokeAllRouteTableRules(defaultRouteTableId string, meta interface{}) error { - conn := meta.(*AWSClient).ec2conn - log.Printf("\n***\nrevokeAllRouteTableRules\n***\n") - - resp, err := conn.DescribeRouteTables(&ec2.DescribeRouteTablesInput{ - RouteTableIds: []*string{aws.String(defaultRouteTableId)}, - }) - if err != nil { - return err - } - - if len(resp.RouteTables) < 1 || resp.RouteTables[0] == nil { - return fmt.Errorf("Default Route table not found") - } - - rt := resp.RouteTables[0] - +func revokeAllRouteTableRules(conn *ec2.EC2, routeTable *ec2.RouteTable) error { // Remove all Gateway association - for _, r := range rt.PropagatingVgws { - log.Printf( - "[INFO] Deleting VGW propagation from %s: %s", - defaultRouteTableId, *r.GatewayId) + for _, r := range routeTable.PropagatingVgws { _, err := conn.DisableVgwRoutePropagation(&ec2.DisableVgwRoutePropagationInput{ - RouteTableId: aws.String(defaultRouteTableId), + RouteTableId: routeTable.RouteTableId, GatewayId: r.GatewayId, }) + if err != nil { return err } } // Delete all routes - for _, r := range rt.Routes { + for _, r := range routeTable.Routes { // you cannot delete the local route - if r.GatewayId != nil && *r.GatewayId == "local" { + if aws.StringValue(r.GatewayId) == "local" { + continue + } + + if aws.StringValue(r.Origin) == ec2.RouteOriginEnableVgwRoutePropagation { continue } @@ -258,45 +242,35 @@ func revokeAllRouteTableRules(defaultRouteTableId string, meta interface{}) erro // See aws_vpc_endpoint continue } - if *r.Origin == "EnableVgwRoutePropagation" { - // Skipping because its from a Gateway associations. Already removed above - continue - } if r.DestinationCidrBlock != nil { - log.Printf( - "[INFO] Deleting route from %s: %s", - defaultRouteTableId, *r.DestinationCidrBlock) _, err := conn.DeleteRoute(&ec2.DeleteRouteInput{ - RouteTableId: aws.String(defaultRouteTableId), + RouteTableId: routeTable.RouteTableId, DestinationCidrBlock: r.DestinationCidrBlock, }) + if err != nil { return err } } if r.DestinationIpv6CidrBlock != nil { - log.Printf( - "[INFO] Deleting route from %s: %s", - defaultRouteTableId, *r.DestinationIpv6CidrBlock) _, err := conn.DeleteRoute(&ec2.DeleteRouteInput{ - RouteTableId: aws.String(defaultRouteTableId), + RouteTableId: routeTable.RouteTableId, DestinationIpv6CidrBlock: r.DestinationIpv6CidrBlock, }) + if err != nil { return err } } if r.DestinationPrefixListId != nil { - log.Printf( - "[INFO] Deleting route from %s: %s", - defaultRouteTableId, *r.DestinationPrefixListId) _, err := conn.DeleteRoute(&ec2.DeleteRouteInput{ - RouteTableId: aws.String(defaultRouteTableId), + RouteTableId: routeTable.RouteTableId, DestinationPrefixListId: r.DestinationPrefixListId, }) + if err != nil { return err } diff --git a/aws/resource_aws_default_route_table_test.go b/aws/resource_aws_default_route_table_test.go index b838d893d8d3..911020440224 100644 --- a/aws/resource_aws_default_route_table_test.go +++ b/aws/resource_aws_default_route_table_test.go @@ -27,12 +27,12 @@ func TestAccAWSDefaultRouteTable_basic(t *testing.T) { // Verify non-existent Route Table ID behavior { Config: testAccDefaultRouteTableConfigDefaultRouteTableId("rtb-00000000"), - ExpectError: regexp.MustCompile(`EC2 Default Route Table \(rtb-00000000\): not found`), + ExpectError: regexp.MustCompile(`EC2 Default Route Table \(rtb-00000000\): couldn't find resource`), }, // Verify invalid Route Table ID behavior { Config: testAccDefaultRouteTableConfigDefaultRouteTableId("vpc-00000000"), - ExpectError: regexp.MustCompile(`EC2 Default Route Table \(vpc-00000000\): not found`), + ExpectError: regexp.MustCompile(`EC2 Default Route Table \(vpc-00000000\): couldn't find resource`), }, { Config: testAccDefaultRouteTableConfigBasic(rName), @@ -105,7 +105,7 @@ func TestAccAWSDefaultRouteTable_Route_ConfigMode(t *testing.T) { testAccCheckResourceAttrAccountID(resourceName, "owner_id"), resource.TestCheckResourceAttr(resourceName, "propagating_vgws.#", "0"), resource.TestCheckResourceAttr(resourceName, "route.#", "1"), - testAccCheckDefaultRouteTableRoute(resourceName, "cidr_block", destinationCidr, "gateway_id", igwResourceName, "id"), + testAccCheckAWSRouteTableRoute(resourceName, "cidr_block", destinationCidr, "gateway_id", igwResourceName, "id"), resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), resource.TestCheckResourceAttr(resourceName, "tags.Name", rName), ), @@ -127,7 +127,7 @@ func TestAccAWSDefaultRouteTable_Route_ConfigMode(t *testing.T) { // The route block from the previous step should still be // present, because no blocks means "ignore existing blocks". resource.TestCheckResourceAttr(resourceName, "route.#", "1"), - testAccCheckDefaultRouteTableRoute(resourceName, "cidr_block", destinationCidr, "gateway_id", igwResourceName, "id"), + testAccCheckAWSRouteTableRoute(resourceName, "cidr_block", destinationCidr, "gateway_id", igwResourceName, "id"), resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), resource.TestCheckResourceAttr(resourceName, "tags.Name", rName), ), @@ -176,7 +176,7 @@ func TestAccAWSDefaultRouteTable_swap(t *testing.T) { testAccCheckResourceAttrAccountID(resourceName, "owner_id"), resource.TestCheckResourceAttr(resourceName, "propagating_vgws.#", "0"), resource.TestCheckResourceAttr(resourceName, "route.#", "1"), - testAccCheckDefaultRouteTableRoute(resourceName, "cidr_block", destinationCidr1, "gateway_id", igwResourceName, "id"), + testAccCheckAWSRouteTableRoute(resourceName, "cidr_block", destinationCidr1, "gateway_id", igwResourceName, "id"), resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), resource.TestCheckResourceAttr(resourceName, "tags.Name", rName), ), @@ -199,7 +199,7 @@ func TestAccAWSDefaultRouteTable_swap(t *testing.T) { testAccCheckRouteTableExists(resourceName, &routeTable), testAccCheckAWSRouteTableNumberOfRoutes(&routeTable, 2), resource.TestCheckResourceAttr(resourceName, "route.#", "1"), - testAccCheckDefaultRouteTableRoute(resourceName, "cidr_block", destinationCidr1, "gateway_id", igwResourceName, "id"), + testAccCheckAWSRouteTableRoute(resourceName, "cidr_block", destinationCidr1, "gateway_id", igwResourceName, "id"), ), ExpectNonEmptyPlan: true, }, @@ -209,7 +209,7 @@ func TestAccAWSDefaultRouteTable_swap(t *testing.T) { testAccCheckRouteTableExists(resourceName, &routeTable), testAccCheckAWSRouteTableNumberOfRoutes(&routeTable, 2), resource.TestCheckResourceAttr(resourceName, "route.#", "1"), - testAccCheckDefaultRouteTableRoute(resourceName, "cidr_block", destinationCidr1, "gateway_id", igwResourceName, "id"), + testAccCheckAWSRouteTableRoute(resourceName, "cidr_block", destinationCidr1, "gateway_id", igwResourceName, "id"), resource.TestCheckResourceAttrPair(resourceName, "id", rtResourceName, "id"), ), // Follow up plan will now show a diff as the destination CIDR on the aws_route_table @@ -239,7 +239,7 @@ func TestAccAWSDefaultRouteTable_IPv4_To_TransitGateway(t *testing.T) { testAccCheckRouteTableExists(resourceName, &routeTable), testAccCheckAWSRouteTableNumberOfRoutes(&routeTable, 2), resource.TestCheckResourceAttr(resourceName, "route.#", "1"), - testAccCheckDefaultRouteTableRoute(resourceName, "cidr_block", destinationCidr, "transit_gateway_id", tgwResourceName, "id"), + testAccCheckAWSRouteTableRoute(resourceName, "cidr_block", destinationCidr, "transit_gateway_id", tgwResourceName, "id"), ), }, { @@ -271,7 +271,7 @@ func TestAccAWSDefaultRouteTable_IPv4_To_VpcEndpoint(t *testing.T) { testAccCheckRouteTableExists(resourceName, &routeTable), testAccCheckAWSRouteTableNumberOfRoutes(&routeTable, 2), resource.TestCheckResourceAttr(resourceName, "route.#", "1"), - testAccCheckDefaultRouteTableRoute(resourceName, "cidr_block", destinationCidr, "vpc_endpoint_id", vpceResourceName, "id"), + testAccCheckAWSRouteTableRoute(resourceName, "cidr_block", destinationCidr, "vpc_endpoint_id", vpceResourceName, "id"), ), }, { @@ -313,7 +313,7 @@ func TestAccAWSDefaultRouteTable_VpcEndpointAssociation(t *testing.T) { testAccCheckRouteTableExists(resourceName, &routeTable), testAccCheckAWSRouteTableNumberOfRoutes(&routeTable, 3), resource.TestCheckResourceAttr(resourceName, "route.#", "1"), - testAccCheckDefaultRouteTableRoute(resourceName, "cidr_block", destinationCidr, "gateway_id", igwResourceName, "id"), + testAccCheckAWSRouteTableRoute(resourceName, "cidr_block", destinationCidr, "gateway_id", igwResourceName, "id"), ), }, { @@ -384,14 +384,14 @@ func TestAccAWSDefaultRouteTable_ConditionalCidrBlock(t *testing.T) { Config: testAccDefaultRouteTableConfigConditionalIpv4Ipv6(rName, destinationCidr, destinationIpv6Cidr, false), Check: resource.ComposeTestCheckFunc( testAccCheckRouteTableExists(resourceName, &routeTable), - testAccCheckDefaultRouteTableRoute(resourceName, "cidr_block", destinationCidr, "gateway_id", igwResourceName, "id"), + testAccCheckAWSRouteTableRoute(resourceName, "cidr_block", destinationCidr, "gateway_id", igwResourceName, "id"), ), }, { Config: testAccDefaultRouteTableConfigConditionalIpv4Ipv6(rName, destinationCidr, destinationIpv6Cidr, true), Check: resource.ComposeTestCheckFunc( testAccCheckRouteTableExists(resourceName, &routeTable), - testAccCheckDefaultRouteTableRoute(resourceName, "ipv6_cidr_block", destinationIpv6Cidr, "gateway_id", igwResourceName, "id"), + testAccCheckAWSRouteTableRoute(resourceName, "ipv6_cidr_block", destinationIpv6Cidr, "gateway_id", igwResourceName, "id"), ), }, { @@ -423,7 +423,7 @@ func TestAccAWSDefaultRouteTable_PrefixList_To_InternetGateway(t *testing.T) { testAccCheckRouteTableExists(resourceName, &routeTable), testAccCheckAWSRouteTableNumberOfRoutes(&routeTable, 2), resource.TestCheckResourceAttr(resourceName, "route.#", "1"), - testAccCheckDefaultRouteTablePrefixListRoute(resourceName, plResourceName, "gateway_id", igwResourceName, "id"), + testAccCheckAWSRouteTablePrefixListRoute(resourceName, plResourceName, "gateway_id", igwResourceName, "id"), ), }, { @@ -445,6 +445,67 @@ func TestAccAWSDefaultRouteTable_PrefixList_To_InternetGateway(t *testing.T) { }) } +func TestAccAWSDefaultRouteTable_RevokeExistingRules(t *testing.T) { + var routeTable ec2.RouteTable + resourceName := "aws_default_route_table.test" + rtResourceName := "aws_route_table.test" + eoigwResourceName := "aws_egress_only_internet_gateway.test" + igwResourceName := "aws_internet_gateway.test" + vgwResourceName := "aws_vpn_gateway.test" + + rName := acctest.RandomWithPrefix("tf-acc-test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ErrorCheck: testAccErrorCheck(t, ec2.EndpointsID), + Providers: testAccProviders, + CheckDestroy: testAccCheckRouteTableDestroy, + Steps: []resource.TestStep{ + { + Config: testAccDefaultRouteTableConfigRevokeExistingRulesCustomRouteTable(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckRouteTableExists(rtResourceName, &routeTable), + testAccCheckAWSRouteTableNumberOfRoutes(&routeTable, 3), + resource.TestCheckResourceAttr(rtResourceName, "propagating_vgws.#", "1"), + resource.TestCheckTypeSetElemAttrPair(rtResourceName, "propagating_vgws.*", vgwResourceName, "id"), + resource.TestCheckResourceAttr(rtResourceName, "route.#", "1"), + testAccCheckAWSRouteTableRoute(rtResourceName, "ipv6_cidr_block", "::/0", "egress_only_gateway_id", eoigwResourceName, "id"), + resource.TestCheckResourceAttr(rtResourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(rtResourceName, "tags.Name", rName), + ), + }, + { + Config: testAccDefaultRouteTableConfigRevokeExistingRulesCustomRouteTableToMain(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckRouteTableExists(rtResourceName, &routeTable), + testAccCheckAWSRouteTableNumberOfRoutes(&routeTable, 3), + resource.TestCheckResourceAttr(rtResourceName, "propagating_vgws.#", "1"), + resource.TestCheckTypeSetElemAttrPair(rtResourceName, "propagating_vgws.*", vgwResourceName, "id"), + resource.TestCheckResourceAttr(rtResourceName, "route.#", "1"), + testAccCheckAWSRouteTableRoute(rtResourceName, "ipv6_cidr_block", "::/0", "egress_only_gateway_id", eoigwResourceName, "id"), + resource.TestCheckResourceAttr(rtResourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(rtResourceName, "tags.Name", rName), + ), + }, + { + Config: testAccDefaultRouteTableConfigRevokeExistingRulesDefaultRouteTableOverlaysCustomRouteTable(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckRouteTableExists(resourceName, &routeTable), + testAccCheckAWSRouteTableNumberOfRoutes(&routeTable, 3), + resource.TestCheckResourceAttr(resourceName, "propagating_vgws.#", "0"), + resource.TestCheckResourceAttr(resourceName, "route.#", "1"), + testAccCheckAWSRouteTableRoute(resourceName, "cidr_block", "0.0.0.0/0", "gateway_id", igwResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.Name", rName), + ), + // The plan on refresh will not be empty as the custom route table resource's routes and propagating VGWs have + // been modified since the default route table's routes and propagating VGWs now overlay the custom route table. + ExpectNonEmptyPlan: true, + }, + }, + }) +} + func testAccCheckDefaultRouteTableDestroy(s *terraform.State) error { conn := testAccProvider.Meta().(*AWSClient).ec2conn @@ -474,54 +535,6 @@ func testAccCheckDefaultRouteTableDestroy(s *terraform.State) error { return nil } -func testAccCheckDefaultRouteTableRoute(resourceName, destinationAttr, destination, targetAttr, targetResourceName, targetResourceAttr string) resource.TestCheckFunc { - return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[targetResourceName] - if !ok { - return fmt.Errorf("Not found: %s", targetResourceName) - } - - target := rs.Primary.Attributes[targetResourceAttr] - if target == "" { - return fmt.Errorf("Not found: %s.%s", targetResourceName, targetResourceAttr) - } - - return resource.TestCheckTypeSetElemNestedAttrs(resourceName, "route.*", map[string]string{ - destinationAttr: destination, - targetAttr: target, - })(s) - } -} - -func testAccCheckDefaultRouteTablePrefixListRoute(resourceName, prefixListResourceName, targetAttr, targetResourceName, targetResourceAttr string) resource.TestCheckFunc { - return func(s *terraform.State) error { - rsPrefixList, ok := s.RootModule().Resources[prefixListResourceName] - if !ok { - return fmt.Errorf("Not found: %s", prefixListResourceName) - } - - destination := rsPrefixList.Primary.Attributes["id"] - if destination == "" { - return fmt.Errorf("Not found: %s.id", prefixListResourceName) - } - - rsTarget, ok := s.RootModule().Resources[targetResourceName] - if !ok { - return fmt.Errorf("Not found: %s", targetResourceName) - } - - target := rsTarget.Primary.Attributes[targetResourceAttr] - if target == "" { - return fmt.Errorf("Not found: %s.%s", targetResourceName, targetResourceAttr) - } - - return resource.TestCheckTypeSetElemNestedAttrs(resourceName, "route.*", map[string]string{ - "destination_prefix_list_id": destination, - targetAttr: target, - })(s) - } -} - func testAccAWSDefaultRouteTableImportStateIdFunc(resourceName string) resource.ImportStateIdFunc { return func(s *terraform.State) (string, error) { rs, ok := s.RootModule().Resources[resourceName] @@ -1113,3 +1126,89 @@ resource "aws_default_route_table" "test" { } `, rName) } + +func testAccDefaultRouteTableConfigRevokeExistingRulesCustomRouteTable(rName 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" { + tags = { + Name = %[1]q + } +} + +resource "aws_vpn_gateway_attachment" "test" { + vpc_id = aws_vpc.test.id + vpn_gateway_id = aws_vpn_gateway.test.id +} + +resource "aws_egress_only_internet_gateway" "test" { + vpc_id = aws_vpc.test.id + + tags = { + Name = %[1]q + } +} + +resource "aws_route_table" "test" { + vpc_id = aws_vpc.test.id + + propagating_vgws = [aws_vpn_gateway_attachment.test.vpn_gateway_id] + + route { + ipv6_cidr_block = "::/0" + egress_only_gateway_id = aws_egress_only_internet_gateway.test.id + } + + tags = { + Name = %[1]q + } +} +`, rName) +} + +func testAccDefaultRouteTableConfigRevokeExistingRulesCustomRouteTableToMain(rName string) string { + return composeConfig( + testAccDefaultRouteTableConfigRevokeExistingRulesCustomRouteTable(rName), + ` +resource "aws_main_route_table_association" "test" { + vpc_id = aws_vpc.test.id + route_table_id = aws_route_table.test.id +} +`) +} + +func testAccDefaultRouteTableConfigRevokeExistingRulesDefaultRouteTableOverlaysCustomRouteTable(rName string) string { + return composeConfig( + testAccDefaultRouteTableConfigRevokeExistingRulesCustomRouteTableToMain(rName), + fmt.Sprintf(` +resource "aws_internet_gateway" "test" { + vpc_id = aws_vpc.test.id + + tags = { + Name = %[1]q + } +} + +resource "aws_default_route_table" "test" { + default_route_table_id = aws_route_table.test.id + + route { + cidr_block = "0.0.0.0/0" + gateway_id = aws_internet_gateway.test.id + } + + tags = { + Name = %[1]q + } +} +`, rName)) +} From 6c2cc1f964187b11fac52c27eb345f792d9ad2b7 Mon Sep 17 00:00:00 2001 From: staebler Date: Fri, 1 Mar 2019 14:00:12 -0500 Subject: [PATCH 11/25] route_table: fail creation if later read does not find resource The typical route table creation steps involve making an ec2/CreateRouteTable request, an ec2/DescribeRouteTables request, some other requests to update the route table, followed by a final ec2.DescribeRouteTables request. If the response to the final ec2/DescribeRouteTables request is InvalidRouteTableID.NotFound, then the ID of the route table resource is cleared so that the route table resource is not retained. However, the creation is still considered a success. This results in either (1) failures from other resources that depend upon the route table resource or (2) a report of a successful apply even though one of the resources needed does not actually exist. These changes adjust the result of the creation in the case where the route table cannot be found on the final ec2/DescribeRouteTables request. Instead of reporting success for the creation, report failure. Fixes #7644 --- aws/resource_aws_route_table.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/aws/resource_aws_route_table.go b/aws/resource_aws_route_table.go index 9eaafc7b5296..c67e75e0aeac 100644 --- a/aws/resource_aws_route_table.go +++ b/aws/resource_aws_route_table.go @@ -203,7 +203,15 @@ func resourceAwsRouteTableCreate(d *schema.ResourceData, meta interface{}) error d.Id(), err) } - return resourceAwsRouteTableUpdate(d, meta) + if err := resourceAwsRouteTableUpdate(d, meta); err != nil { + return fmt.Errorf("Error updating route table after creating it: %s", err) + } + + if d.Id() == "" { + return fmt.Errorf("Route table not found after creating it: %s", err) + } + + return nil } func resourceAwsRouteTableRead(d *schema.ResourceData, meta interface{}) error { From 2fef042622b1dfe95ad34ac58105aa12d4733113 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Mon, 29 Mar 2021 10:29:27 -0400 Subject: [PATCH 12/25] r/aws_route_table: Add 'd.IsNewResource()' check to resource read (#16796). Acceptance test output: $ make testacc TEST=./aws/ TESTARGS='-run=TestAccAWSRouteTable_' ACCTEST_PARALLELISM=2 ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws -v -count 1 -parallel 2 -run=TestAccAWSRouteTable_ -timeout 180m === RUN TestAccAWSRouteTable_basic === PAUSE TestAccAWSRouteTable_basic === RUN TestAccAWSRouteTable_disappears === PAUSE TestAccAWSRouteTable_disappears === RUN TestAccAWSRouteTable_disappears_SubnetAssociation === PAUSE TestAccAWSRouteTable_disappears_SubnetAssociation === RUN TestAccAWSRouteTable_IPv4_To_InternetGateway === PAUSE TestAccAWSRouteTable_IPv4_To_InternetGateway === RUN TestAccAWSRouteTable_IPv4_To_Instance === PAUSE TestAccAWSRouteTable_IPv4_To_Instance === RUN TestAccAWSRouteTable_IPv6_To_EgressOnlyInternetGateway === PAUSE TestAccAWSRouteTable_IPv6_To_EgressOnlyInternetGateway === RUN TestAccAWSRouteTable_tags === PAUSE TestAccAWSRouteTable_tags === RUN TestAccAWSRouteTable_RequireRouteDestination === PAUSE TestAccAWSRouteTable_RequireRouteDestination === RUN TestAccAWSRouteTable_RequireRouteTarget === PAUSE TestAccAWSRouteTable_RequireRouteTarget === RUN TestAccAWSRouteTable_Route_ConfigMode === PAUSE TestAccAWSRouteTable_Route_ConfigMode === RUN TestAccAWSRouteTable_IPv4_To_TransitGateway === PAUSE TestAccAWSRouteTable_IPv4_To_TransitGateway === RUN TestAccAWSRouteTable_IPv4_To_VpcEndpoint === PAUSE TestAccAWSRouteTable_IPv4_To_VpcEndpoint === RUN TestAccAWSRouteTable_IPv4_To_CarrierGateway === PAUSE TestAccAWSRouteTable_IPv4_To_CarrierGateway === RUN TestAccAWSRouteTable_IPv4_To_LocalGateway === PAUSE TestAccAWSRouteTable_IPv4_To_LocalGateway === RUN TestAccAWSRouteTable_IPv4_To_VpcPeeringConnection === PAUSE TestAccAWSRouteTable_IPv4_To_VpcPeeringConnection === RUN TestAccAWSRouteTable_vgwRoutePropagation === PAUSE TestAccAWSRouteTable_vgwRoutePropagation === RUN TestAccAWSRouteTable_ConditionalCidrBlock === PAUSE TestAccAWSRouteTable_ConditionalCidrBlock === RUN TestAccAWSRouteTable_IPv4_To_NatGateway === PAUSE TestAccAWSRouteTable_IPv4_To_NatGateway === RUN TestAccAWSRouteTable_IPv6_To_NetworkInterface_Unattached === PAUSE TestAccAWSRouteTable_IPv6_To_NetworkInterface_Unattached === RUN TestAccAWSRouteTable_VpcMultipleCidrs === PAUSE TestAccAWSRouteTable_VpcMultipleCidrs === RUN TestAccAWSRouteTable_VpcClassicLink === PAUSE TestAccAWSRouteTable_VpcClassicLink === RUN TestAccAWSRouteTable_GatewayVpcEndpoint === PAUSE TestAccAWSRouteTable_GatewayVpcEndpoint === RUN TestAccAWSRouteTable_MultipleRoutes === PAUSE TestAccAWSRouteTable_MultipleRoutes === RUN TestAccAWSRouteTable_PrefixList_To_InternetGateway === PAUSE TestAccAWSRouteTable_PrefixList_To_InternetGateway === CONT TestAccAWSRouteTable_basic === CONT TestAccAWSRouteTable_IPv4_To_LocalGateway data_source_aws_outposts_outposts_test.go:67: skipping since no Outposts found --- SKIP: TestAccAWSRouteTable_IPv4_To_LocalGateway (1.40s) === CONT TestAccAWSRouteTable_PrefixList_To_InternetGateway --- PASS: TestAccAWSRouteTable_basic (22.84s) === CONT TestAccAWSRouteTable_MultipleRoutes --- PASS: TestAccAWSRouteTable_PrefixList_To_InternetGateway (42.61s) === CONT TestAccAWSRouteTable_GatewayVpcEndpoint --- PASS: TestAccAWSRouteTable_GatewayVpcEndpoint (65.20s) === CONT TestAccAWSRouteTable_VpcClassicLink --- PASS: TestAccAWSRouteTable_VpcClassicLink (23.99s) === CONT TestAccAWSRouteTable_VpcMultipleCidrs --- PASS: TestAccAWSRouteTable_VpcMultipleCidrs (44.49s) === CONT TestAccAWSRouteTable_IPv6_To_NetworkInterface_Unattached --- PASS: TestAccAWSRouteTable_MultipleRoutes (174.34s) === CONT TestAccAWSRouteTable_IPv4_To_NatGateway --- PASS: TestAccAWSRouteTable_IPv6_To_NetworkInterface_Unattached (64.12s) === CONT TestAccAWSRouteTable_ConditionalCidrBlock --- PASS: TestAccAWSRouteTable_ConditionalCidrBlock (54.20s) === CONT TestAccAWSRouteTable_vgwRoutePropagation --- PASS: TestAccAWSRouteTable_vgwRoutePropagation (86.26s) === CONT TestAccAWSRouteTable_IPv4_To_VpcPeeringConnection --- PASS: TestAccAWSRouteTable_IPv4_To_VpcPeeringConnection (26.81s) === CONT TestAccAWSRouteTable_RequireRouteDestination --- PASS: TestAccAWSRouteTable_IPv4_To_NatGateway (246.64s) === CONT TestAccAWSRouteTable_IPv4_To_CarrierGateway --- PASS: TestAccAWSRouteTable_IPv4_To_CarrierGateway (26.55s) === CONT TestAccAWSRouteTable_IPv4_To_VpcEndpoint --- PASS: TestAccAWSRouteTable_RequireRouteDestination (324.00s) === CONT TestAccAWSRouteTable_IPv4_To_TransitGateway --- PASS: TestAccAWSRouteTable_IPv4_To_VpcEndpoint (263.18s) === CONT TestAccAWSRouteTable_Route_ConfigMode --- PASS: TestAccAWSRouteTable_Route_ConfigMode (70.84s) === CONT TestAccAWSRouteTable_RequireRouteTarget --- PASS: TestAccAWSRouteTable_RequireRouteTarget (11.86s) === CONT TestAccAWSRouteTable_IPv4_To_Instance --- PASS: TestAccAWSRouteTable_IPv4_To_Instance (113.23s) === CONT TestAccAWSRouteTable_tags --- PASS: TestAccAWSRouteTable_tags (68.59s) === CONT TestAccAWSRouteTable_IPv6_To_EgressOnlyInternetGateway --- PASS: TestAccAWSRouteTable_IPv6_To_EgressOnlyInternetGateway (47.38s) === CONT TestAccAWSRouteTable_disappears_SubnetAssociation --- PASS: TestAccAWSRouteTable_disappears_SubnetAssociation (24.28s) === CONT TestAccAWSRouteTable_IPv4_To_InternetGateway --- PASS: TestAccAWSRouteTable_IPv4_To_TransitGateway (339.66s) === CONT TestAccAWSRouteTable_disappears --- PASS: TestAccAWSRouteTable_disappears (20.05s) --- PASS: TestAccAWSRouteTable_IPv4_To_InternetGateway (64.71s) PASS ok github.com/terraform-providers/terraform-provider-aws/aws 1134.554s --- aws/resource_aws_route_table.go | 38 +++++++++++++++------------------ 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/aws/resource_aws_route_table.go b/aws/resource_aws_route_table.go index c67e75e0aeac..4e2f77b52c01 100644 --- a/aws/resource_aws_route_table.go +++ b/aws/resource_aws_route_table.go @@ -15,6 +15,8 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/terraform-providers/terraform-provider-aws/aws/internal/hashcode" "github.com/terraform-providers/terraform-provider-aws/aws/internal/keyvaluetags" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/ec2/finder" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/tfresource" ) var routeTableValidDestinations = []string{ @@ -203,35 +205,29 @@ func resourceAwsRouteTableCreate(d *schema.ResourceData, meta interface{}) error d.Id(), err) } - if err := resourceAwsRouteTableUpdate(d, meta); err != nil { - return fmt.Errorf("Error updating route table after creating it: %s", err) - } - - if d.Id() == "" { - return fmt.Errorf("Route table not found after creating it: %s", err) - } - - return nil + return resourceAwsRouteTableUpdate(d, meta) } func resourceAwsRouteTableRead(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).ec2conn ignoreTagsConfig := meta.(*AWSClient).IgnoreTagsConfig - rtRaw, _, err := resourceAwsRouteTableStateRefreshFunc(conn, d.Id())() - if err != nil { - return err - } - if rtRaw == nil { + routeTable, err := finder.RouteTableByID(conn, d.Id()) + + if !d.IsNewResource() && tfresource.NotFound(err) { + log.Printf("[WARN] Route table (%s) not found, removing from state", d.Id()) d.SetId("") return nil } - rt := rtRaw.(*ec2.RouteTable) - d.Set("vpc_id", rt.VpcId) + if err != nil { + return fmt.Errorf("error reading route table (%s): %w", d.Id(), err) + } + + d.Set("vpc_id", routeTable.VpcId) - propagatingVGWs := make([]string, 0, len(rt.PropagatingVgws)) - for _, vgw := range rt.PropagatingVgws { + propagatingVGWs := make([]string, 0, len(routeTable.PropagatingVgws)) + for _, vgw := range routeTable.PropagatingVgws { propagatingVGWs = append(propagatingVGWs, aws.StringValue(vgw.GatewayId)) } d.Set("propagating_vgws", propagatingVGWs) @@ -240,7 +236,7 @@ func resourceAwsRouteTableRead(d *schema.ResourceData, meta interface{}) error { route := &schema.Set{F: resourceAwsRouteTableHash} // Loop through the routes and add them to the set - for _, r := range rt.Routes { + for _, r := range routeTable.Routes { if aws.StringValue(r.GatewayId) == "local" { continue } @@ -303,11 +299,11 @@ func resourceAwsRouteTableRead(d *schema.ResourceData, meta interface{}) error { d.Set("route", route) // Tags - if err := d.Set("tags", keyvaluetags.Ec2KeyValueTags(rt.Tags).IgnoreAws().IgnoreConfig(ignoreTagsConfig).Map()); err != nil { + if err := d.Set("tags", keyvaluetags.Ec2KeyValueTags(routeTable.Tags).IgnoreAws().IgnoreConfig(ignoreTagsConfig).Map()); err != nil { return fmt.Errorf("error setting tags: %w", err) } - ownerID := aws.StringValue(rt.OwnerId) + ownerID := aws.StringValue(routeTable.OwnerId) arn := arn.ARN{ Partition: meta.(*AWSClient).partition, Service: ec2.ServiceName, From 65d1d7a3cdf93960ca98f566e8da577094073673 Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Mon, 29 Mar 2021 12:30:14 -0400 Subject: [PATCH 13/25] r/route_table: Code consistency --- aws/resource_aws_route_table.go | 54 +++++++++------------------------ 1 file changed, 15 insertions(+), 39 deletions(-) diff --git a/aws/resource_aws_route_table.go b/aws/resource_aws_route_table.go index 4e2f77b52c01..c5e56cae162f 100644 --- a/aws/resource_aws_route_table.go +++ b/aws/resource_aws_route_table.go @@ -49,14 +49,14 @@ func resourceAwsRouteTable() *schema.Resource { }, Schema: map[string]*schema.Schema{ - "vpc_id": { + "arn": { Type: schema.TypeString, - Required: true, - ForceNew: true, + Computed: true, + }, + "owner_id": { + Type: schema.TypeString, + Computed: true, }, - - "tags": tagsSchema(), - "propagating_vgws": { Type: schema.TypeSet, Optional: true, @@ -64,7 +64,6 @@ func resourceAwsRouteTable() *schema.Resource { Elem: &schema.Schema{Type: schema.TypeString}, Set: schema.HashString, }, - "route": { Type: schema.TypeSet, Computed: true, @@ -83,7 +82,6 @@ func resourceAwsRouteTable() *schema.Resource { validateIpv4CIDRNetworkAddress, ), }, - "ipv6_cidr_block": { Type: schema.TypeString, Optional: true, @@ -92,7 +90,6 @@ func resourceAwsRouteTable() *schema.Resource { validateIpv6CIDRNetworkAddress, ), }, - "destination_prefix_list_id": { Type: schema.TypeString, Optional: true, @@ -105,47 +102,38 @@ func resourceAwsRouteTable() *schema.Resource { Type: schema.TypeString, Optional: true, }, - "egress_only_gateway_id": { Type: schema.TypeString, Optional: true, }, - "gateway_id": { Type: schema.TypeString, Optional: true, }, - "instance_id": { Type: schema.TypeString, Optional: true, }, - "local_gateway_id": { Type: schema.TypeString, Optional: true, }, - "nat_gateway_id": { Type: schema.TypeString, Optional: true, }, - "network_interface_id": { Type: schema.TypeString, Optional: true, }, - "transit_gateway_id": { Type: schema.TypeString, Optional: true, }, - "vpc_endpoint_id": { Type: schema.TypeString, Optional: true, }, - "vpc_peering_connection_id": { Type: schema.TypeString, Optional: true, @@ -154,15 +142,11 @@ func resourceAwsRouteTable() *schema.Resource { }, Set: resourceAwsRouteTableHash, }, - - "arn": { - Type: schema.TypeString, - Computed: true, - }, - - "owner_id": { + "tags": tagsSchema(), + "vpc_id": { Type: schema.TypeString, - Computed: true, + Required: true, + ForceNew: true, }, }, } @@ -189,9 +173,7 @@ func resourceAwsRouteTableCreate(d *schema.ResourceData, meta interface{}) error log.Printf("[INFO] Route Table ID: %s", d.Id()) // Wait for the route table to become available - log.Printf( - "[DEBUG] Waiting for route table (%s) to become available", - d.Id()) + log.Printf("[DEBUG] Waiting for route table (%s) to become available", d.Id()) stateConf := &resource.StateChangeConf{ Pending: []string{"pending"}, Target: []string{"ready"}, @@ -200,9 +182,7 @@ func resourceAwsRouteTableCreate(d *schema.ResourceData, meta interface{}) error NotFoundChecks: 40, } if _, err := stateConf.WaitForState(); err != nil { - return fmt.Errorf( - "Error waiting for route table (%s) to become available: %s", - d.Id(), err) + return fmt.Errorf("error waiting for route table (%s) to become available: %w", d.Id(), err) } return resourceAwsRouteTableUpdate(d, meta) @@ -332,9 +312,7 @@ func resourceAwsRouteTableUpdate(d *schema.ResourceData, meta interface{}) error id := vgw.(string) // Disable the propagation as it no longer exists in the config - log.Printf( - "[INFO] Deleting VGW propagation from %s: %s", - d.Id(), id) + log.Printf("[INFO] Deleting VGW propagation from %s: %s", d.Id(), id) _, err := conn.DisableVgwRoutePropagation(&ec2.DisableVgwRoutePropagationInput{ RouteTableId: aws.String(d.Id()), GatewayId: aws.String(id), @@ -397,9 +375,7 @@ func resourceAwsRouteTableUpdate(d *schema.ResourceData, meta interface{}) error if s, ok := m["ipv6_cidr_block"].(string); ok && s != "" { deleteOpts.DestinationIpv6CidrBlock = aws.String(s) - log.Printf( - "[INFO] Deleting route from %s: %s", - d.Id(), m["ipv6_cidr_block"].(string)) + log.Printf("[INFO] Deleting route from %s: %s", d.Id(), m["ipv6_cidr_block"].(string)) } if s, ok := m["cidr_block"].(string); ok && s != "" { @@ -668,7 +644,7 @@ func resourceAwsRouteTableHash(v interface{}) int { func resourceAwsRouteTableStateRefreshFunc(conn *ec2.EC2, id string) resource.StateRefreshFunc { return func() (interface{}, string, error) { resp, err := conn.DescribeRouteTables(&ec2.DescribeRouteTablesInput{ - RouteTableIds: []*string{aws.String(id)}, + RouteTableIds: aws.StringSlice([]string{id}), }) if err != nil { if isAWSErr(err, "InvalidRouteTableID.NotFound", "") { From 1961ca17f4395772a99ae8fd0624f53af4410231 Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Mon, 29 Mar 2021 12:33:32 -0400 Subject: [PATCH 14/25] r/route_table: Code consistency --- aws/resource_aws_route_table.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/aws/resource_aws_route_table.go b/aws/resource_aws_route_table.go index c5e56cae162f..54d4730a15d1 100644 --- a/aws/resource_aws_route_table.go +++ b/aws/resource_aws_route_table.go @@ -82,6 +82,10 @@ func resourceAwsRouteTable() *schema.Resource { validateIpv4CIDRNetworkAddress, ), }, + "destination_prefix_list_id": { + Type: schema.TypeString, + Optional: true, + }, "ipv6_cidr_block": { Type: schema.TypeString, Optional: true, @@ -90,10 +94,6 @@ func resourceAwsRouteTable() *schema.Resource { validateIpv6CIDRNetworkAddress, ), }, - "destination_prefix_list_id": { - Type: schema.TypeString, - Optional: true, - }, // // Targets. From 3407ddf74d6934449a7365d69752518ecd488945 Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Mon, 29 Mar 2021 14:05:47 -0400 Subject: [PATCH 15/25] r/route_table: Add waiter and status for route table --- aws/internal/service/ec2/waiter/status.go | 26 ++++++++++++++ aws/internal/service/ec2/waiter/waiter.go | 43 +++++++++++++++++++++++ 2 files changed, 69 insertions(+) diff --git a/aws/internal/service/ec2/waiter/status.go b/aws/internal/service/ec2/waiter/status.go index 9e1e7e54fcd9..56b7e5e6a522 100644 --- a/aws/internal/service/ec2/waiter/status.go +++ b/aws/internal/service/ec2/waiter/status.go @@ -245,6 +245,32 @@ func InstanceIamInstanceProfile(conn *ec2.EC2, id string) resource.StateRefreshF } } +const ( + ErrCodeInvalidRouteTableIDNotFound = "InvalidRouteTableID.NotFound" + + RouteTableStatusReady = "ready" +) + +func RouteTableStatus(conn *ec2.EC2, id string) resource.StateRefreshFunc { + return func() (interface{}, string, error) { + output, err := finder.RouteTableByID(conn, id) + + if tfawserr.ErrCodeEquals(err, ErrCodeInvalidRouteTableIDNotFound) { + return nil, "", nil + } + + if err != nil { + return nil, "", err + } + + if output == nil { + return nil, "", nil + } + + return output, RouteTableStatusReady, nil + } +} + const ( SecurityGroupStatusCreated = "Created" diff --git a/aws/internal/service/ec2/waiter/waiter.go b/aws/internal/service/ec2/waiter/waiter.go index a7385d40cef7..625bf972bf14 100644 --- a/aws/internal/service/ec2/waiter/waiter.go +++ b/aws/internal/service/ec2/waiter/waiter.go @@ -257,6 +257,49 @@ const ( NetworkAclEntryPropagationTimeout = 5 * time.Minute ) +const ( + RouteTableReadyTimeout = 10 * time.Minute + RouteTableDeletedTimeout = 5 * time.Minute + RouteTableUpdateTimeout = 5 * time.Minute + + RouteTableNotFoundChecks = 40 +) + +func RouteTableReady(conn *ec2.EC2, id string) (*ec2.RouteTable, error) { + stateConf := &resource.StateChangeConf{ + Pending: []string{"pending"}, + Target: []string{"ready"}, + Refresh: RouteTableStatus(conn, id), + Timeout: RouteTableReadyTimeout, + NotFoundChecks: RouteTableNotFoundChecks, + } + + outputRaw, err := stateConf.WaitForState() + + if output, ok := outputRaw.(*ec2.RouteTable); ok { + return output, err + } + + return nil, err +} + +func RouteTableDeleted(conn *ec2.EC2, id string) (*ec2.RouteTable, error) { + stateConf := &resource.StateChangeConf{ + Pending: []string{"ready"}, + Target: []string{}, + Refresh: RouteTableStatus(conn, id), + Timeout: RouteTableDeletedTimeout, + } + + outputRaw, err := stateConf.WaitForState() + + if output, ok := outputRaw.(*ec2.RouteTable); ok { + return output, err + } + + return nil, err +} + func SecurityGroupCreated(conn *ec2.EC2, id string, timeout time.Duration) (*ec2.SecurityGroup, error) { stateConf := &resource.StateChangeConf{ Pending: []string{SecurityGroupStatusNotFound}, From 90b0c9708247f156a66bd97f1dbfa8db978a8070 Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Mon, 29 Mar 2021 14:12:43 -0400 Subject: [PATCH 16/25] r/route_table_association: Use waiter for route table status --- aws/resource_aws_route_table_association.go | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/aws/resource_aws_route_table_association.go b/aws/resource_aws_route_table_association.go index 2dd3602b7a2f..445a45501901 100644 --- a/aws/resource_aws_route_table_association.go +++ b/aws/resource_aws_route_table_association.go @@ -11,6 +11,7 @@ import ( "github.com/aws/aws-sdk-go/service/ec2" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/ec2/waiter" ) func resourceAwsRouteTableAssociation() *schema.Resource { @@ -99,15 +100,12 @@ func resourceAwsRouteTableAssociationRead(d *schema.ResourceData, meta interface conn := meta.(*AWSClient).ec2conn // Get the routing table that this association belongs to - rtRaw, _, err := resourceAwsRouteTableStateRefreshFunc( - conn, d.Get("route_table_id").(string))() + rtID := d.Get("route_table_id").(string) + rt, err := waiter.RouteTableReady(conn, rtID) + if err != nil { - return err - } - if rtRaw == nil { - return nil + return fmt.Errorf("error getting route table (%s) status: %w", rtID, err) } - rt := rtRaw.(*ec2.RouteTable) // Inspect that the association exists found := false From 6c7be9dffdaaa5b7167ffa2a32b4c4ef89397132 Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Mon, 29 Mar 2021 14:14:37 -0400 Subject: [PATCH 17/25] r/route_table: Switch to waiter --- aws/resource_aws_route_table.go | 65 +++++---------------------------- 1 file changed, 9 insertions(+), 56 deletions(-) diff --git a/aws/resource_aws_route_table.go b/aws/resource_aws_route_table.go index 54d4730a15d1..ef8e13c307b7 100644 --- a/aws/resource_aws_route_table.go +++ b/aws/resource_aws_route_table.go @@ -16,6 +16,7 @@ import ( "github.com/terraform-providers/terraform-provider-aws/aws/internal/hashcode" "github.com/terraform-providers/terraform-provider-aws/aws/internal/keyvaluetags" "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/ec2/finder" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/ec2/waiter" "github.com/terraform-providers/terraform-provider-aws/aws/internal/tfresource" ) @@ -174,14 +175,7 @@ func resourceAwsRouteTableCreate(d *schema.ResourceData, meta interface{}) error // Wait for the route table to become available log.Printf("[DEBUG] Waiting for route table (%s) to become available", d.Id()) - stateConf := &resource.StateChangeConf{ - Pending: []string{"pending"}, - Target: []string{"ready"}, - Refresh: resourceAwsRouteTableStateRefreshFunc(conn, d.Id()), - Timeout: 10 * time.Minute, - NotFoundChecks: 40, - } - if _, err := stateConf.WaitForState(); err != nil { + if _, err := waiter.RouteTableReady(conn, d.Id()); err != nil { return fmt.Errorf("error waiting for route table (%s) to become available: %w", d.Id(), err) } @@ -468,7 +462,7 @@ func resourceAwsRouteTableUpdate(d *schema.ResourceData, meta interface{}) error } log.Printf("[INFO] Creating route for %s: %#v", d.Id(), opts) - err := resource.Retry(5*time.Minute, func() *resource.RetryError { + err := resource.Retry(waiter.RouteTableUpdateTimeout, func() *resource.RetryError { _, err := conn.CreateRoute(&opts) if isAWSErr(err, "InvalidRouteTableID.NotFound", "") { @@ -512,14 +506,11 @@ func resourceAwsRouteTableDelete(d *schema.ResourceData, meta interface{}) error // First request the routing table since we'll have to disassociate // all the subnets first. - rtRaw, _, err := resourceAwsRouteTableStateRefreshFunc(conn, d.Id())() + rt, err := waiter.RouteTableReady(conn, d.Id()) + if err != nil { - return err - } - if rtRaw == nil { - return nil + return fmt.Errorf("error getting route table (%s) status: %w", d.Id(), err) } - rt := rtRaw.(*ec2.RouteTable) // Do all the disassociations for _, a := range rt.Associations { @@ -554,20 +545,9 @@ func resourceAwsRouteTableDelete(d *schema.ResourceData, meta interface{}) error } // Wait for the route table to really destroy - log.Printf( - "[DEBUG] Waiting for route table (%s) to become destroyed", - d.Id()) - - stateConf := &resource.StateChangeConf{ - Pending: []string{"ready"}, - Target: []string{}, - Refresh: resourceAwsRouteTableStateRefreshFunc(conn, d.Id()), - Timeout: 5 * time.Minute, - } - if _, err := stateConf.WaitForState(); err != nil { - return fmt.Errorf( - "Error waiting for route table (%s) to become destroyed: %s", - d.Id(), err) + log.Printf("[DEBUG] Waiting for route table (%s) deletion", d.Id()) + if _, err := waiter.RouteTableDeleted(conn, d.Id()); err != nil { + return fmt.Errorf("error waiting for route table (%s) deletion: %w", d.Id(), err) } return nil @@ -638,30 +618,3 @@ func resourceAwsRouteTableHash(v interface{}) int { return hashcode.String(buf.String()) } - -// resourceAwsRouteTableStateRefreshFunc returns a resource.StateRefreshFunc that is used to watch -// a RouteTable. -func resourceAwsRouteTableStateRefreshFunc(conn *ec2.EC2, id string) resource.StateRefreshFunc { - return func() (interface{}, string, error) { - resp, err := conn.DescribeRouteTables(&ec2.DescribeRouteTablesInput{ - RouteTableIds: aws.StringSlice([]string{id}), - }) - if err != nil { - if isAWSErr(err, "InvalidRouteTableID.NotFound", "") { - resp = nil - } else { - log.Printf("Error on RouteTableStateRefresh: %s", err) - return nil, "", err - } - } - - if resp == nil { - // Sometimes AWS just has consistency issues and doesn't see - // our instance yet. Return an empty state. - return nil, "", nil - } - - rt := resp.RouteTables[0] - return rt, "ready", nil - } -} From 491cbfd2a1389b968339c62b9a693e0a1f44b7b3 Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Mon, 29 Mar 2021 14:15:33 -0400 Subject: [PATCH 18/25] r/vpn_gateway_route_propagation: Use waiter for route table status --- ...source_aws_vpn_gateway_route_propagation.go | 10 ++++++---- ...e_aws_vpn_gateway_route_propagation_test.go | 18 +++++++++++------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/aws/resource_aws_vpn_gateway_route_propagation.go b/aws/resource_aws_vpn_gateway_route_propagation.go index 93d3031e78d3..5efcff2bd6f0 100644 --- a/aws/resource_aws_vpn_gateway_route_propagation.go +++ b/aws/resource_aws_vpn_gateway_route_propagation.go @@ -7,6 +7,7 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/ec2/waiter" ) func resourceAwsVpnGatewayRoutePropagation() *schema.Resource { @@ -74,17 +75,18 @@ func resourceAwsVpnGatewayRoutePropagationRead(d *schema.ResourceData, meta inte rtID := d.Get("route_table_id").(string) log.Printf("[INFO] Reading route table %s to check for VPN gateway %s", rtID, gwID) - rtRaw, _, err := resourceAwsRouteTableStateRefreshFunc(conn, rtID)() + rt, err := waiter.RouteTableReady(conn, d.Id()) + if err != nil { - return err + return fmt.Errorf("error getting route table (%s) status: %w", d.Id(), err) } - if rtRaw == nil { + + if rt == nil { log.Printf("[INFO] Route table %q doesn't exist, so dropping %q route propagation from state", rtID, gwID) d.SetId("") return nil } - rt := rtRaw.(*ec2.RouteTable) exists := false for _, vgw := range rt.PropagatingVgws { if aws.StringValue(vgw.GatewayId) == gwID { diff --git a/aws/resource_aws_vpn_gateway_route_propagation_test.go b/aws/resource_aws_vpn_gateway_route_propagation_test.go index ff9f4087edb9..5116925fbcd8 100644 --- a/aws/resource_aws_vpn_gateway_route_propagation_test.go +++ b/aws/resource_aws_vpn_gateway_route_propagation_test.go @@ -8,6 +8,7 @@ import ( "github.com/aws/aws-sdk-go/service/ec2" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/ec2/waiter" ) func TestAccAWSVPNGatewayRoutePropagation_basic(t *testing.T) { @@ -32,15 +33,16 @@ func TestAccAWSVPNGatewayRoutePropagation_basic(t *testing.T) { rtID = rs.Primary.Attributes["route_table_id"] gwID = rs.Primary.Attributes["vpn_gateway_id"] - rtRaw, _, err := resourceAwsRouteTableStateRefreshFunc(conn, rtID)() + rt, err := waiter.RouteTableReady(conn, rtID) + if err != nil { - return fmt.Errorf("failed to read route table: %s", err) + return fmt.Errorf("error getting route table (%s) status: %w", rtID, err) } - if rtRaw == nil { + + if rt == nil { return errors.New("route table doesn't exist") } - rt := rtRaw.(*ec2.RouteTable) exists := false for _, vgw := range rt.PropagatingVgws { if *vgw.GatewayId == gwID { @@ -58,11 +60,13 @@ func TestAccAWSVPNGatewayRoutePropagation_basic(t *testing.T) { CheckDestroy: func(state *terraform.State) error { conn := testAccProvider.Meta().(*AWSClient).ec2conn - rtRaw, _, err := resourceAwsRouteTableStateRefreshFunc(conn, rtID)() + rt, err := waiter.RouteTableReady(conn, rtID) + if err != nil { - return fmt.Errorf("failed to read route table: %s", err) + return fmt.Errorf("error getting route table (%s) status: %w", rtID, err) } - if rtRaw != nil { + + if rt != nil { return errors.New("route table still exists") } return nil From 56c538da124009267b4ae793aa45c23466edd104 Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Mon, 29 Mar 2021 14:18:02 -0400 Subject: [PATCH 19/25] r/vpn_gateway_route_propagation: Use correct ID for waiter --- aws/resource_aws_vpn_gateway_route_propagation.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aws/resource_aws_vpn_gateway_route_propagation.go b/aws/resource_aws_vpn_gateway_route_propagation.go index 5efcff2bd6f0..025c15b7ffc4 100644 --- a/aws/resource_aws_vpn_gateway_route_propagation.go +++ b/aws/resource_aws_vpn_gateway_route_propagation.go @@ -75,10 +75,10 @@ func resourceAwsVpnGatewayRoutePropagationRead(d *schema.ResourceData, meta inte rtID := d.Get("route_table_id").(string) log.Printf("[INFO] Reading route table %s to check for VPN gateway %s", rtID, gwID) - rt, err := waiter.RouteTableReady(conn, d.Id()) + rt, err := waiter.RouteTableReady(conn, rtID) if err != nil { - return fmt.Errorf("error getting route table (%s) status: %w", d.Id(), err) + return fmt.Errorf("error getting route table (%s) status: %w", rtID, err) } if rt == nil { From 43181cdef2a397c79bb47355313b7712470c3f0f Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Mon, 29 Mar 2021 14:55:05 -0400 Subject: [PATCH 20/25] r/route_table: Avoid changing API errors --- aws/internal/service/ec2/finder/finder.go | 13 +------------ aws/internal/service/ec2/waiter/waiter.go | 4 ++-- aws/resource_aws_route_table.go | 4 ++-- 3 files changed, 5 insertions(+), 16 deletions(-) diff --git a/aws/internal/service/ec2/finder/finder.go b/aws/internal/service/ec2/finder/finder.go index cad843458937..db14310c4acc 100644 --- a/aws/internal/service/ec2/finder/finder.go +++ b/aws/internal/service/ec2/finder/finder.go @@ -5,7 +5,6 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" - "github.com/hashicorp/aws-sdk-go-base/tfawserr" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" tfnet "github.com/terraform-providers/terraform-provider-aws/aws/internal/net" tfec2 "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/ec2" @@ -193,22 +192,12 @@ func RouteTableByID(conn *ec2.EC2, routeTableID string) (*ec2.RouteTable, error) func RouteTable(conn *ec2.EC2, input *ec2.DescribeRouteTablesInput) (*ec2.RouteTable, error) { output, err := conn.DescribeRouteTables(input) - if tfawserr.ErrCodeEquals(err, tfec2.ErrCodeInvalidRouteTableIDNotFound) { - return nil, &resource.NotFoundError{ - LastError: err, - LastRequest: input, - } - } - if err != nil { return nil, err } if output == nil || len(output.RouteTables) == 0 || output.RouteTables[0] == nil { - return nil, &resource.NotFoundError{ - Message: "Empty result", - LastRequest: input, - } + return nil, fmt.Errorf(tfec2.ErrCodeInvalidRouteTableIDNotFound) } return output.RouteTables[0], nil diff --git a/aws/internal/service/ec2/waiter/waiter.go b/aws/internal/service/ec2/waiter/waiter.go index 625bf972bf14..fec24c91da0d 100644 --- a/aws/internal/service/ec2/waiter/waiter.go +++ b/aws/internal/service/ec2/waiter/waiter.go @@ -267,8 +267,8 @@ const ( func RouteTableReady(conn *ec2.EC2, id string) (*ec2.RouteTable, error) { stateConf := &resource.StateChangeConf{ - Pending: []string{"pending"}, - Target: []string{"ready"}, + Pending: []string{}, + Target: []string{RouteTableStatusReady}, Refresh: RouteTableStatus(conn, id), Timeout: RouteTableReadyTimeout, NotFoundChecks: RouteTableNotFoundChecks, diff --git a/aws/resource_aws_route_table.go b/aws/resource_aws_route_table.go index ef8e13c307b7..2090651384a4 100644 --- a/aws/resource_aws_route_table.go +++ b/aws/resource_aws_route_table.go @@ -10,6 +10,7 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/arn" "github.com/aws/aws-sdk-go/service/ec2" + "github.com/hashicorp/aws-sdk-go-base/tfawserr" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" @@ -17,7 +18,6 @@ import ( "github.com/terraform-providers/terraform-provider-aws/aws/internal/keyvaluetags" "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/ec2/finder" "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/ec2/waiter" - "github.com/terraform-providers/terraform-provider-aws/aws/internal/tfresource" ) var routeTableValidDestinations = []string{ @@ -188,7 +188,7 @@ func resourceAwsRouteTableRead(d *schema.ResourceData, meta interface{}) error { routeTable, err := finder.RouteTableByID(conn, d.Id()) - if !d.IsNewResource() && tfresource.NotFound(err) { + if !d.IsNewResource() && tfawserr.ErrCodeEquals(err, waiter.ErrCodeInvalidRouteTableIDNotFound) { log.Printf("[WARN] Route table (%s) not found, removing from state", d.Id()) d.SetId("") return nil From 960b0d73ec3ade7477d8b8bd97a21869c3f1e284 Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Mon, 29 Mar 2021 15:25:46 -0400 Subject: [PATCH 21/25] r/route_table: Rework waiters and VPN gateway route test --- aws/internal/service/ec2/waiter/waiter.go | 2 +- aws/resource_aws_route_table.go | 2 +- aws/resource_aws_route_table_association.go | 2 +- aws/resource_aws_vpn_gateway_route_propagation.go | 2 +- aws/resource_aws_vpn_gateway_route_propagation_test.go | 6 +++--- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/aws/internal/service/ec2/waiter/waiter.go b/aws/internal/service/ec2/waiter/waiter.go index fec24c91da0d..21a74f381a99 100644 --- a/aws/internal/service/ec2/waiter/waiter.go +++ b/aws/internal/service/ec2/waiter/waiter.go @@ -285,7 +285,7 @@ func RouteTableReady(conn *ec2.EC2, id string) (*ec2.RouteTable, error) { func RouteTableDeleted(conn *ec2.EC2, id string) (*ec2.RouteTable, error) { stateConf := &resource.StateChangeConf{ - Pending: []string{"ready"}, + Pending: []string{RouteTableStatusReady}, Target: []string{}, Refresh: RouteTableStatus(conn, id), Timeout: RouteTableDeletedTimeout, diff --git a/aws/resource_aws_route_table.go b/aws/resource_aws_route_table.go index 2090651384a4..f387a4a31836 100644 --- a/aws/resource_aws_route_table.go +++ b/aws/resource_aws_route_table.go @@ -509,7 +509,7 @@ func resourceAwsRouteTableDelete(d *schema.ResourceData, meta interface{}) error rt, err := waiter.RouteTableReady(conn, d.Id()) if err != nil { - return fmt.Errorf("error getting route table (%s) status: %w", d.Id(), err) + return fmt.Errorf("error getting route table (%s) prior to disassociating associations: %w", d.Id(), err) } // Do all the disassociations diff --git a/aws/resource_aws_route_table_association.go b/aws/resource_aws_route_table_association.go index 445a45501901..c8d601ac089a 100644 --- a/aws/resource_aws_route_table_association.go +++ b/aws/resource_aws_route_table_association.go @@ -104,7 +104,7 @@ func resourceAwsRouteTableAssociationRead(d *schema.ResourceData, meta interface rt, err := waiter.RouteTableReady(conn, rtID) if err != nil { - return fmt.Errorf("error getting route table (%s) status: %w", rtID, err) + return fmt.Errorf("error getting route table (%s) status while reading route table association: %w", rtID, err) } // Inspect that the association exists diff --git a/aws/resource_aws_vpn_gateway_route_propagation.go b/aws/resource_aws_vpn_gateway_route_propagation.go index 025c15b7ffc4..3c8bef6aff8f 100644 --- a/aws/resource_aws_vpn_gateway_route_propagation.go +++ b/aws/resource_aws_vpn_gateway_route_propagation.go @@ -78,7 +78,7 @@ func resourceAwsVpnGatewayRoutePropagationRead(d *schema.ResourceData, meta inte rt, err := waiter.RouteTableReady(conn, rtID) if err != nil { - return fmt.Errorf("error getting route table (%s) status: %w", rtID, err) + return fmt.Errorf("error getting route table (%s) status while reading VPN gateway route propagation: %w", rtID, err) } if rt == nil { diff --git a/aws/resource_aws_vpn_gateway_route_propagation_test.go b/aws/resource_aws_vpn_gateway_route_propagation_test.go index 5116925fbcd8..cbde36a71855 100644 --- a/aws/resource_aws_vpn_gateway_route_propagation_test.go +++ b/aws/resource_aws_vpn_gateway_route_propagation_test.go @@ -36,7 +36,7 @@ func TestAccAWSVPNGatewayRoutePropagation_basic(t *testing.T) { rt, err := waiter.RouteTableReady(conn, rtID) if err != nil { - return fmt.Errorf("error getting route table (%s) status: %w", rtID, err) + return fmt.Errorf("error getting route table (%s) while checking VPN gateway route propagation: %w", rtID, err) } if rt == nil { @@ -60,10 +60,10 @@ func TestAccAWSVPNGatewayRoutePropagation_basic(t *testing.T) { CheckDestroy: func(state *terraform.State) error { conn := testAccProvider.Meta().(*AWSClient).ec2conn - rt, err := waiter.RouteTableReady(conn, rtID) + rt, err := waiter.RouteTableDeleted(conn, rtID) if err != nil { - return fmt.Errorf("error getting route table (%s) status: %w", rtID, err) + return fmt.Errorf("error getting route table (%s) status while checking destroy: %w", rtID, err) } if rt != nil { From 7665057cd79bc0f2ad80d8b7141ac777386ee673 Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Mon, 29 Mar 2021 15:31:19 -0400 Subject: [PATCH 22/25] r/route_table_associations: Check that route table exists --- aws/resource_aws_route_table_association.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/aws/resource_aws_route_table_association.go b/aws/resource_aws_route_table_association.go index c8d601ac089a..235160aa6c7d 100644 --- a/aws/resource_aws_route_table_association.go +++ b/aws/resource_aws_route_table_association.go @@ -9,6 +9,7 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/service/ec2" + "github.com/hashicorp/aws-sdk-go-base/tfawserr" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/ec2/waiter" @@ -103,6 +104,12 @@ func resourceAwsRouteTableAssociationRead(d *schema.ResourceData, meta interface rtID := d.Get("route_table_id").(string) rt, err := waiter.RouteTableReady(conn, rtID) + if !d.IsNewResource() && tfawserr.ErrCodeEquals(err, waiter.ErrCodeInvalidRouteTableIDNotFound) { + log.Printf("[WARN] Route table (%s) not found, removing route table association (%s) from state", rtID, d.Id()) + d.SetId("") + return nil + } + if err != nil { return fmt.Errorf("error getting route table (%s) status while reading route table association: %w", rtID, err) } From ac11d7652205abcc48ee3e6b726b74e920cbd5da Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Mon, 29 Mar 2021 16:07:55 -0400 Subject: [PATCH 23/25] r/route_table: Switch to using tfresource Not Found --- aws/internal/service/ec2/finder/finder.go | 13 ++++++++++++- aws/internal/service/ec2/waiter/status.go | 3 ++- aws/internal/service/ec2/waiter/waiter.go | 5 +++++ aws/resource_aws_route_table.go | 4 ++-- aws/resource_aws_route_table_association.go | 4 ++-- aws/resource_aws_vpn_gateway_route_propagation.go | 7 +++++++ 6 files changed, 30 insertions(+), 6 deletions(-) diff --git a/aws/internal/service/ec2/finder/finder.go b/aws/internal/service/ec2/finder/finder.go index db14310c4acc..cad843458937 100644 --- a/aws/internal/service/ec2/finder/finder.go +++ b/aws/internal/service/ec2/finder/finder.go @@ -5,6 +5,7 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" + "github.com/hashicorp/aws-sdk-go-base/tfawserr" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" tfnet "github.com/terraform-providers/terraform-provider-aws/aws/internal/net" tfec2 "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/ec2" @@ -192,12 +193,22 @@ func RouteTableByID(conn *ec2.EC2, routeTableID string) (*ec2.RouteTable, error) func RouteTable(conn *ec2.EC2, input *ec2.DescribeRouteTablesInput) (*ec2.RouteTable, error) { output, err := conn.DescribeRouteTables(input) + if tfawserr.ErrCodeEquals(err, tfec2.ErrCodeInvalidRouteTableIDNotFound) { + return nil, &resource.NotFoundError{ + LastError: err, + LastRequest: input, + } + } + if err != nil { return nil, err } if output == nil || len(output.RouteTables) == 0 || output.RouteTables[0] == nil { - return nil, fmt.Errorf(tfec2.ErrCodeInvalidRouteTableIDNotFound) + return nil, &resource.NotFoundError{ + Message: "Empty result", + LastRequest: input, + } } return output.RouteTables[0], nil diff --git a/aws/internal/service/ec2/waiter/status.go b/aws/internal/service/ec2/waiter/status.go index 56b7e5e6a522..dc7c7b6114a4 100644 --- a/aws/internal/service/ec2/waiter/status.go +++ b/aws/internal/service/ec2/waiter/status.go @@ -12,6 +12,7 @@ import ( tfec2 "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/ec2" "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/ec2/finder" tfiam "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/iam" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/tfresource" ) const ( @@ -255,7 +256,7 @@ func RouteTableStatus(conn *ec2.EC2, id string) resource.StateRefreshFunc { return func() (interface{}, string, error) { output, err := finder.RouteTableByID(conn, id) - if tfawserr.ErrCodeEquals(err, ErrCodeInvalidRouteTableIDNotFound) { + if tfresource.NotFound(err) { return nil, "", nil } diff --git a/aws/internal/service/ec2/waiter/waiter.go b/aws/internal/service/ec2/waiter/waiter.go index 21a74f381a99..0ed7934363e9 100644 --- a/aws/internal/service/ec2/waiter/waiter.go +++ b/aws/internal/service/ec2/waiter/waiter.go @@ -8,6 +8,7 @@ import ( "github.com/hashicorp/aws-sdk-go-base/tfawserr" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" tfec2 "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/ec2" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/tfresource" ) const ( @@ -293,6 +294,10 @@ func RouteTableDeleted(conn *ec2.EC2, id string) (*ec2.RouteTable, error) { outputRaw, err := stateConf.WaitForState() + if tfresource.NotFound(err) { + return nil, nil + } + if output, ok := outputRaw.(*ec2.RouteTable); ok { return output, err } diff --git a/aws/resource_aws_route_table.go b/aws/resource_aws_route_table.go index f387a4a31836..a4a3941b6612 100644 --- a/aws/resource_aws_route_table.go +++ b/aws/resource_aws_route_table.go @@ -10,7 +10,6 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/arn" "github.com/aws/aws-sdk-go/service/ec2" - "github.com/hashicorp/aws-sdk-go-base/tfawserr" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" @@ -18,6 +17,7 @@ import ( "github.com/terraform-providers/terraform-provider-aws/aws/internal/keyvaluetags" "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/ec2/finder" "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/ec2/waiter" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/tfresource" ) var routeTableValidDestinations = []string{ @@ -188,7 +188,7 @@ func resourceAwsRouteTableRead(d *schema.ResourceData, meta interface{}) error { routeTable, err := finder.RouteTableByID(conn, d.Id()) - if !d.IsNewResource() && tfawserr.ErrCodeEquals(err, waiter.ErrCodeInvalidRouteTableIDNotFound) { + if !d.IsNewResource() && tfresource.NotFound(err) { log.Printf("[WARN] Route table (%s) not found, removing from state", d.Id()) d.SetId("") return nil diff --git a/aws/resource_aws_route_table_association.go b/aws/resource_aws_route_table_association.go index 235160aa6c7d..3b970da09dd6 100644 --- a/aws/resource_aws_route_table_association.go +++ b/aws/resource_aws_route_table_association.go @@ -9,10 +9,10 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/service/ec2" - "github.com/hashicorp/aws-sdk-go-base/tfawserr" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/ec2/waiter" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/tfresource" ) func resourceAwsRouteTableAssociation() *schema.Resource { @@ -104,7 +104,7 @@ func resourceAwsRouteTableAssociationRead(d *schema.ResourceData, meta interface rtID := d.Get("route_table_id").(string) rt, err := waiter.RouteTableReady(conn, rtID) - if !d.IsNewResource() && tfawserr.ErrCodeEquals(err, waiter.ErrCodeInvalidRouteTableIDNotFound) { + if !d.IsNewResource() && tfresource.NotFound(err) { log.Printf("[WARN] Route table (%s) not found, removing route table association (%s) from state", rtID, d.Id()) d.SetId("") return nil diff --git a/aws/resource_aws_vpn_gateway_route_propagation.go b/aws/resource_aws_vpn_gateway_route_propagation.go index 3c8bef6aff8f..5bdc6988ded9 100644 --- a/aws/resource_aws_vpn_gateway_route_propagation.go +++ b/aws/resource_aws_vpn_gateway_route_propagation.go @@ -8,6 +8,7 @@ import ( "github.com/aws/aws-sdk-go/service/ec2" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/ec2/waiter" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/tfresource" ) func resourceAwsVpnGatewayRoutePropagation() *schema.Resource { @@ -77,6 +78,12 @@ func resourceAwsVpnGatewayRoutePropagationRead(d *schema.ResourceData, meta inte log.Printf("[INFO] Reading route table %s to check for VPN gateway %s", rtID, gwID) rt, err := waiter.RouteTableReady(conn, rtID) + if !d.IsNewResource() && tfresource.NotFound(err) { + log.Printf("[WARN] Route table (%s) not found, removing VPN gateway route propagation (%s) from state", rtID, d.Id()) + d.SetId("") + return nil + } + if err != nil { return fmt.Errorf("error getting route table (%s) status while reading VPN gateway route propagation: %w", rtID, err) } From 87fa5bf58f4ab4b0d3162101741e74e86acf6ef8 Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Mon, 29 Mar 2021 17:27:52 -0400 Subject: [PATCH 24/25] r/route_table: Remove unnecessary check --- aws/internal/service/ec2/waiter/waiter.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/aws/internal/service/ec2/waiter/waiter.go b/aws/internal/service/ec2/waiter/waiter.go index 0ed7934363e9..21a74f381a99 100644 --- a/aws/internal/service/ec2/waiter/waiter.go +++ b/aws/internal/service/ec2/waiter/waiter.go @@ -8,7 +8,6 @@ import ( "github.com/hashicorp/aws-sdk-go-base/tfawserr" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" tfec2 "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/ec2" - "github.com/terraform-providers/terraform-provider-aws/aws/internal/tfresource" ) const ( @@ -294,10 +293,6 @@ func RouteTableDeleted(conn *ec2.EC2, id string) (*ec2.RouteTable, error) { outputRaw, err := stateConf.WaitForState() - if tfresource.NotFound(err) { - return nil, nil - } - if output, ok := outputRaw.(*ec2.RouteTable); ok { return output, err } From f36fc0ac4528e6055d5ef6ae723a6d757293e97c Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Mon, 29 Mar 2021 17:47:10 -0400 Subject: [PATCH 25/25] route_table: Add changelog items --- .changelog/17319.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.changelog/17319.txt b/.changelog/17319.txt index 3d552e4ac78d..01a6b8f59b9c 100644 --- a/.changelog/17319.txt +++ b/.changelog/17319.txt @@ -5,3 +5,15 @@ resource/aws_default_route_table: Add `destination_prefix_list_id` attribute ```release-notes:enhancement resource/aws_route_table: Add `destination_prefix_list_id` attribute ``` + +```release-note:bug +resource/aws_vpn_gateway_route_propagation: Improve eventual consistency handling and handling of out-of-band resource removal +``` + +```release-note:bug +resource/aws_route_table: Improve eventual consistency handling and handling of out-of-band resource removal +``` + +```release-note:bug +resource/aws_route_table_association: Improve eventual consistency handling and handling of out-of-band resource removal +``` \ No newline at end of file