From 7fafa81c663eb4830526418c5dbe2813639d77a2 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Sun, 24 Jan 2021 17:39:36 -0500 Subject: [PATCH 1/9] r/aws_route: 'destination_prefix_list_id' attribute can be specified for managed prefix list destinations. Acceptance test output: $ make testacc TEST=./aws TESTARGS='-run=TestAccAWSRoute_basic' ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws -v -count 1 -parallel 20 -run=TestAccAWSRoute_basic -timeout 120m === RUN TestAccAWSRoute_basic === PAUSE TestAccAWSRoute_basic === CONT TestAccAWSRoute_basic --- PASS: TestAccAWSRoute_basic (35.53s) PASS ok github.com/terraform-providers/terraform-provider-aws/aws 35.619s --- aws/internal/service/ec2/finder/finder.go | 17 +++++++++++++ aws/internal/service/ec2/id.go | 4 ++++ aws/resource_aws_route.go | 29 ++++++++++++++++++++--- aws/resource_aws_route_test.go | 4 ++++ website/docs/r/route.html.markdown | 12 +++++++++- 5 files changed, 62 insertions(+), 4 deletions(-) diff --git a/aws/internal/service/ec2/finder/finder.go b/aws/internal/service/ec2/finder/finder.go index cad84345893..cbc272faeb1 100644 --- a/aws/internal/service/ec2/finder/finder.go +++ b/aws/internal/service/ec2/finder/finder.go @@ -254,6 +254,23 @@ func RouteByIPv6Destination(conn *ec2.EC2, routeTableID, destinationIpv6Cidr str return nil, &resource.NotFoundError{} } +// RouteByPrefixListIDDestination returns the route corresponding to the specified prefix list destination. +// Returns NotFoundError if no route is found. +func RouteByPrefixListIDDestination(conn *ec2.EC2, routeTableID, prefixListID string) (*ec2.Route, error) { + routeTable, err := RouteTableByID(conn, routeTableID) + if err != nil { + return nil, err + } + + for _, route := range routeTable.Routes { + if aws.StringValue(route.DestinationPrefixListId) == prefixListID { + return route, nil + } + } + + return nil, &resource.NotFoundError{} +} + // SecurityGroupByID looks up a security group by ID. When not found, returns nil and potentially an API error. func SecurityGroupByID(conn *ec2.EC2, id string) (*ec2.SecurityGroup, error) { req := &ec2.DescribeSecurityGroupsInput{ diff --git a/aws/internal/service/ec2/id.go b/aws/internal/service/ec2/id.go index c7fa5040e0f..dc0207beca2 100644 --- a/aws/internal/service/ec2/id.go +++ b/aws/internal/service/ec2/id.go @@ -7,6 +7,10 @@ import ( "github.com/terraform-providers/terraform-provider-aws/aws/internal/hashcode" ) +const ( + ManagedPrefixListOwnerIdAWS = "AWS" +) + const clientVpnAuthorizationRuleIDSeparator = "," func ClientVpnAuthorizationRuleCreateID(endpointID, targetNetworkCidr, accessGroupID string) string { diff --git a/aws/resource_aws_route.go b/aws/resource_aws_route.go index b5eaaecde79..7feb89b98c0 100644 --- a/aws/resource_aws_route.go +++ b/aws/resource_aws_route.go @@ -20,6 +20,7 @@ import ( var routeValidDestinations = []string{ "destination_cidr_block", "destination_ipv6_cidr_block", + "destination_prefix_list_id", } var routeValidTargets = []string{ @@ -81,10 +82,10 @@ func resourceAwsRoute() *schema.Resource { DiffSuppressFunc: suppressEqualCIDRBlockDiffs, }, - // TODO This is a target once we have Managed Prefix List support. "destination_prefix_list_id": { Type: schema.TypeString, - Computed: true, + Optional: true, + ForceNew: true, }, // @@ -206,6 +207,9 @@ func resourceAwsRouteCreate(d *schema.ResourceData, meta interface{}) error { case "destination_ipv6_cidr_block": input.DestinationIpv6CidrBlock = destination routeFinder = finder.RouteByIPv6Destination + case "destination_prefix_list_id": + input.DestinationPrefixListId = destination + routeFinder = finder.RouteByPrefixListIDDestination default: return fmt.Errorf("error creating Route: unexpected route destination attribute: %q", destinationAttributeKey) } @@ -309,6 +313,8 @@ func resourceAwsRouteRead(d *schema.ResourceData, meta interface{}) error { routeFinder = finder.RouteByIPv4Destination case "destination_ipv6_cidr_block": routeFinder = finder.RouteByIPv6Destination + case "destination_prefix_list_id": + routeFinder = finder.RouteByPrefixListIDDestination default: return fmt.Errorf("error reading Route: unexpected route destination attribute: %q", destinationAttributeKey) } @@ -378,6 +384,8 @@ func resourceAwsRouteUpdate(d *schema.ResourceData, meta interface{}) error { input.DestinationCidrBlock = destination case "destination_ipv6_cidr_block": input.DestinationIpv6CidrBlock = destination + case "destination_prefix_list_id": + input.DestinationPrefixListId = destination default: return fmt.Errorf("error updating Route: unexpected route destination attribute: %q", destinationAttributeKey) } @@ -436,6 +444,8 @@ func resourceAwsRouteDelete(d *schema.ResourceData, meta interface{}) error { input.DestinationCidrBlock = destination case "destination_ipv6_cidr_block": input.DestinationIpv6CidrBlock = destination + case "destination_prefix_list_id": + input.DestinationPrefixListId = destination default: return fmt.Errorf("error deleting Route: unexpected route destination attribute: %q", destinationAttributeKey) } @@ -490,9 +500,22 @@ func resourceAwsRouteImport(d *schema.ResourceData, meta interface{}) ([]*schema d.Set("route_table_id", routeTableID) if strings.Contains(destination, ":") { d.Set("destination_ipv6_cidr_block", destination) - } else { + } else if strings.Contains(destination, ".") { d.Set("destination_cidr_block", destination) + } else { + managedPrefixList, err := finder.ManagedPrefixListByID(meta.(*AWSClient).ec2conn, destination) + + if err != nil { + return nil, err + } + + if managedPrefixList != nil && aws.StringValue(managedPrefixList.OwnerId) == tfec2.ManagedPrefixListOwnerIdAWS { + return nil, fmt.Errorf("Managed prefix list (%s) is owned by AWS", destination) + } + + d.Set("destination_prefix_list_id", destination) } + d.SetId(tfec2.RouteCreateID(routeTableID, destination)) return []*schema.ResourceData{d}, nil diff --git a/aws/resource_aws_route_test.go b/aws/resource_aws_route_test.go index ae7025293bb..842d2bfc4d6 100644 --- a/aws/resource_aws_route_test.go +++ b/aws/resource_aws_route_test.go @@ -1492,6 +1492,8 @@ func testAccCheckAWSRouteExists(n string, v *ec2.Route) resource.TestCheckFunc { route, err = finder.RouteByIPv4Destination(conn, rs.Primary.Attributes["route_table_id"], v) } else if v := rs.Primary.Attributes["destination_ipv6_cidr_block"]; v != "" { route, err = finder.RouteByIPv6Destination(conn, rs.Primary.Attributes["route_table_id"], v) + } else if v := rs.Primary.Attributes["destination_prefix_list_id"]; v != "" { + route, err = finder.RouteByPrefixListIDDestination(conn, rs.Primary.Attributes["route_table_id"], v) } if err != nil { @@ -1517,6 +1519,8 @@ func testAccCheckAWSRouteDestroy(s *terraform.State) error { _, err = finder.RouteByIPv4Destination(conn, rs.Primary.Attributes["route_table_id"], v) } else if v := rs.Primary.Attributes["destination_ipv6_cidr_block"]; v != "" { _, err = finder.RouteByIPv6Destination(conn, rs.Primary.Attributes["route_table_id"], v) + } else if v := rs.Primary.Attributes["destination_prefix_list_id"]; v != "" { + _, err = finder.RouteByPrefixListIDDestination(conn, rs.Primary.Attributes["route_table_id"], v) } if tfresource.NotFound(err) { diff --git a/website/docs/r/route.html.markdown b/website/docs/r/route.html.markdown index a3fab4fd1a9..58d93da6fa9 100644 --- a/website/docs/r/route.html.markdown +++ b/website/docs/r/route.html.markdown @@ -58,6 +58,7 @@ One of the following destination arguments must be supplied: * `destination_cidr_block` - (Optional) The destination CIDR block. * `destination_ipv6_cidr_block` - (Optional) The destination IPv6 CIDR block. +* `destination_prefix_list_id` - (Optional) The ID of a [managed prefix list](ec2_managed_prefix_list.html) destination. One of the following target arguments must be supplied: @@ -82,7 +83,10 @@ In addition to all arguments above, the following attributes are exported: ~> **NOTE:** Only the arguments that are configured (one of the above) will be exported as an attribute once the resource is created. -* `id` - Route Table identifier and destination +* `id` - Route identifier computed from the routing table identifier and route destination. +* `instance_owner_id` - The AWS account ID of the owner of the EC2 instance. +* `origin` - How the route was created - `CreateRouteTable`, `CreateRoute` or `EnableVgwRoutePropagation`. +* `state` - The state of the route - `active` or `blackhole`. ## Timeouts @@ -107,3 +111,9 @@ Import a route in route table `rtb-656C65616E6F72` with an IPv6 destination CIDR ```console $ terraform import aws_route.my_route rtb-656C65616E6F72_2620:0:2d0:200::8/125 ``` + +Import a route in route table `rtb-656C65616E6F72` with a managed prefix list destination of `pl-0570a1d2d725c16be` similarly: + +```console +$ terraform import aws_route.my_route rtb-656C65616E6F72_pl-0570a1d2d725c16be +``` From 45292409cbd72269e5374b7346e1c32cd6296cd3 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Mon, 25 Jan 2021 16:04:47 -0500 Subject: [PATCH 2/9] r/aws_route: Add 'TestAccAWSRoute_PrefixList_To_InternetGateway'. Acceptance test output: $ make testacc TEST=./aws TESTARGS='-run=TestAccAWSRoute_PrefixList_To_InternetGateway' ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws -v -count 1 -parallel 20 -run=TestAccAWSRoute_PrefixList_To_InternetGateway -timeout 120m === RUN TestAccAWSRoute_PrefixList_To_InternetGateway === PAUSE TestAccAWSRoute_PrefixList_To_InternetGateway === CONT TestAccAWSRoute_PrefixList_To_InternetGateway --- PASS: TestAccAWSRoute_PrefixList_To_InternetGateway (36.06s) PASS ok github.com/terraform-providers/terraform-provider-aws/aws 36.149s --- aws/resource_aws_route_test.go | 86 ++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/aws/resource_aws_route_test.go b/aws/resource_aws_route_test.go index 842d2bfc4d6..29ce858fce7 100644 --- a/aws/resource_aws_route_test.go +++ b/aws/resource_aws_route_test.go @@ -1473,6 +1473,49 @@ func TestAccAWSRoute_LocalRoute(t *testing.T) { }) } +func TestAccAWSRoute_PrefixList_To_InternetGateway(t *testing.T) { + var route ec2.Route + resourceName := "aws_route.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) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSRouteDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSRouteConfigPrefixListInternetGateway(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSRouteExists(resourceName, &route), + resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", ""), + resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), + resource.TestCheckResourceAttrPair(resourceName, "destination_prefix_list_id", plResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "egress_only_gateway_id", ""), + resource.TestCheckResourceAttrPair(resourceName, "gateway_id", igwResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "instance_id", ""), + resource.TestCheckResourceAttr(resourceName, "instance_owner_id", ""), + resource.TestCheckResourceAttr(resourceName, "local_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "nat_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "network_interface_id", ""), + resource.TestCheckResourceAttr(resourceName, "origin", ec2.RouteOriginCreateRoute), + resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateActive), + resource.TestCheckResourceAttr(resourceName, "transit_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "vpc_endpoint_id", ""), + resource.TestCheckResourceAttr(resourceName, "vpc_peering_connection_id", ""), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateIdFunc: testAccAWSRouteImportStateIdFunc(resourceName), + ImportStateVerify: true, + }, + }, + }) +} + func testAccCheckAWSRouteExists(n string, v *ec2.Route) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] @@ -1548,6 +1591,9 @@ func testAccAWSRouteImportStateIdFunc(resourceName string) resource.ImportStateI if v, ok := rs.Primary.Attributes["destination_ipv6_cidr_block"]; ok && v != "" { destination = v } + if v, ok := rs.Primary.Attributes["destination_prefix_list_id"]; ok && v != "" { + destination = v + } return fmt.Sprintf("%s_%s", rs.Primary.Attributes["route_table_id"], destination), nil } @@ -1630,6 +1676,46 @@ resource "aws_route" "test" { `, rName, destinationCidr) } +func testAccAWSRouteConfigPrefixListInternetGateway(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 + + tags = { + Name = %[1]q + } +} + +resource "aws_route" "test" { + route_table_id = aws_route_table.test.id + destination_prefix_list_id = aws_ec2_managed_prefix_list.test.id + gateway_id = aws_internet_gateway.test.id +} +`, rName) +} + func testAccAWSRouteConfigIpv6NetworkInterfaceUnattached(rName, destinationCidr string) string { return composeConfig( testAccAvailableAZsNoOptInConfig(), From 9bc9f57c0c9b0dd2481629d4850b483b351db4f4 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Mon, 25 Jan 2021 18:31:32 -0500 Subject: [PATCH 3/9] r/aws_route: Add prefix list destination tests. Acceptance test output: $ make testacc TEST=./aws/ TESTARGS='-run=TestAccAWSRoute_PrefixList_To_' ACCTEST_PARALLELISM=2 ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws -v -count 1 -parallel 2 -run=TestAccAWSRoute_PrefixList_To_ -timeout 120m === RUN TestAccAWSRoute_PrefixList_To_InternetGateway === PAUSE TestAccAWSRoute_PrefixList_To_InternetGateway === RUN TestAccAWSRoute_PrefixList_To_VpnGateway === PAUSE TestAccAWSRoute_PrefixList_To_VpnGateway === RUN TestAccAWSRoute_PrefixList_To_Instance === PAUSE TestAccAWSRoute_PrefixList_To_Instance === RUN TestAccAWSRoute_PrefixList_To_NetworkInterface_Unattached === PAUSE TestAccAWSRoute_PrefixList_To_NetworkInterface_Unattached === RUN TestAccAWSRoute_PrefixList_To_NetworkInterface_Attached === PAUSE TestAccAWSRoute_PrefixList_To_NetworkInterface_Attached === RUN TestAccAWSRoute_PrefixList_To_VpcPeeringConnection === PAUSE TestAccAWSRoute_PrefixList_To_VpcPeeringConnection === RUN TestAccAWSRoute_PrefixList_To_NatGateway === PAUSE TestAccAWSRoute_PrefixList_To_NatGateway === RUN TestAccAWSRoute_PrefixList_To_TransitGateway === PAUSE TestAccAWSRoute_PrefixList_To_TransitGateway === RUN TestAccAWSRoute_PrefixList_To_LocalGateway === PAUSE TestAccAWSRoute_PrefixList_To_LocalGateway === RUN TestAccAWSRoute_PrefixList_To_EgressOnlyInternetGateway === PAUSE TestAccAWSRoute_PrefixList_To_EgressOnlyInternetGateway === CONT TestAccAWSRoute_PrefixList_To_InternetGateway === CONT TestAccAWSRoute_PrefixList_To_NatGateway --- PASS: TestAccAWSRoute_PrefixList_To_InternetGateway (35.99s) === CONT TestAccAWSRoute_PrefixList_To_EgressOnlyInternetGateway --- PASS: TestAccAWSRoute_PrefixList_To_EgressOnlyInternetGateway (32.09s) === CONT TestAccAWSRoute_PrefixList_To_LocalGateway data_source_aws_outposts_outposts_test.go:66: skipping since no Outposts found --- SKIP: TestAccAWSRoute_PrefixList_To_LocalGateway (1.13s) === CONT TestAccAWSRoute_PrefixList_To_TransitGateway --- PASS: TestAccAWSRoute_PrefixList_To_NatGateway (200.00s) === CONT TestAccAWSRoute_PrefixList_To_NetworkInterface_Unattached --- PASS: TestAccAWSRoute_PrefixList_To_NetworkInterface_Unattached (65.18s) === CONT TestAccAWSRoute_PrefixList_To_VpcPeeringConnection --- PASS: TestAccAWSRoute_PrefixList_To_VpcPeeringConnection (33.28s) === CONT TestAccAWSRoute_PrefixList_To_NetworkInterface_Attached --- PASS: TestAccAWSRoute_PrefixList_To_TransitGateway (368.99s) === CONT TestAccAWSRoute_PrefixList_To_Instance --- PASS: TestAccAWSRoute_PrefixList_To_NetworkInterface_Attached (350.96s) === CONT TestAccAWSRoute_PrefixList_To_VpnGateway --- PASS: TestAccAWSRoute_PrefixList_To_VpnGateway (47.82s) --- PASS: TestAccAWSRoute_PrefixList_To_Instance (327.05s) PASS ok github.com/terraform-providers/terraform-provider-aws/aws 765.354s --- aws/resource_aws_route.go | 11 +- aws/resource_aws_route_test.go | 2145 +++++++++++++++++++++++--------- 2 files changed, 1567 insertions(+), 589 deletions(-) diff --git a/aws/resource_aws_route.go b/aws/resource_aws_route.go index 7feb89b98c0..c036fe20163 100644 --- a/aws/resource_aws_route.go +++ b/aws/resource_aws_route.go @@ -145,10 +145,13 @@ func resourceAwsRoute() *schema.Resource { }, "vpc_endpoint_id": { - Type: schema.TypeString, - Optional: true, - ExactlyOneOf: routeValidTargets, - ConflictsWith: []string{"destination_ipv6_cidr_block"}, // IPv4 destinations only. + Type: schema.TypeString, + Optional: true, + ExactlyOneOf: routeValidTargets, + ConflictsWith: []string{ + "destination_ipv6_cidr_block", // IPv4 destinations only. + "destination_prefix_list_id", // "Cannot create or replace a prefix list route targeting a VPC Endpoint." + }, }, "vpc_peering_connection_id": { diff --git a/aws/resource_aws_route_test.go b/aws/resource_aws_route_test.go index 29ce858fce7..21964132822 100644 --- a/aws/resource_aws_route_test.go +++ b/aws/resource_aws_route_test.go @@ -1489,6 +1489,7 @@ func TestAccAWSRoute_PrefixList_To_InternetGateway(t *testing.T) { Config: testAccAWSRouteConfigPrefixListInternetGateway(rName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSRouteExists(resourceName, &route), + resource.TestCheckResourceAttr(resourceName, "carrier_gateway_id", ""), resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", ""), resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), resource.TestCheckResourceAttrPair(resourceName, "destination_prefix_list_id", plResourceName, "id"), @@ -1516,91 +1517,839 @@ func TestAccAWSRoute_PrefixList_To_InternetGateway(t *testing.T) { }) } -func testAccCheckAWSRouteExists(n string, v *ec2.Route) resource.TestCheckFunc { - return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[n] - if !ok { - return fmt.Errorf("Not found: %s", n) - } - - if rs.Primary.ID == "" { - return fmt.Errorf("No ID is set") - } +func TestAccAWSRoute_PrefixList_To_VpnGateway(t *testing.T) { + var route ec2.Route + resourceName := "aws_route.test" + vgwResourceName := "aws_vpn_gateway.test" + plResourceName := "aws_ec2_managed_prefix_list.test" + rName := acctest.RandomWithPrefix("tf-acc-test") - conn := testAccProvider.Meta().(*AWSClient).ec2conn + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSRouteDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSRouteConfigPrefixListVpnGateway(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSRouteExists(resourceName, &route), + resource.TestCheckResourceAttr(resourceName, "carrier_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", ""), + resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), + resource.TestCheckResourceAttrPair(resourceName, "destination_prefix_list_id", plResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "egress_only_gateway_id", ""), + resource.TestCheckResourceAttrPair(resourceName, "gateway_id", vgwResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "instance_id", ""), + resource.TestCheckResourceAttr(resourceName, "instance_owner_id", ""), + resource.TestCheckResourceAttr(resourceName, "local_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "nat_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "network_interface_id", ""), + resource.TestCheckResourceAttr(resourceName, "origin", ec2.RouteOriginCreateRoute), + resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateActive), + resource.TestCheckResourceAttr(resourceName, "transit_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "vpc_endpoint_id", ""), + resource.TestCheckResourceAttr(resourceName, "vpc_peering_connection_id", ""), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateIdFunc: testAccAWSRouteImportStateIdFunc(resourceName), + ImportStateVerify: true, + }, + }, + }) +} - var route *ec2.Route - var err error - if v := rs.Primary.Attributes["destination_cidr_block"]; v != "" { - route, err = finder.RouteByIPv4Destination(conn, rs.Primary.Attributes["route_table_id"], v) - } else if v := rs.Primary.Attributes["destination_ipv6_cidr_block"]; v != "" { - route, err = finder.RouteByIPv6Destination(conn, rs.Primary.Attributes["route_table_id"], v) - } else if v := rs.Primary.Attributes["destination_prefix_list_id"]; v != "" { - route, err = finder.RouteByPrefixListIDDestination(conn, rs.Primary.Attributes["route_table_id"], v) - } +func TestAccAWSRoute_PrefixList_To_Instance(t *testing.T) { + var route ec2.Route + resourceName := "aws_route.test" + instanceResourceName := "aws_instance.test" + plResourceName := "aws_ec2_managed_prefix_list.test" + rName := acctest.RandomWithPrefix("tf-acc-test") - if err != nil { - return err - } + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSRouteDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSRouteConfigPrefixListInstance(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSRouteExists(resourceName, &route), + resource.TestCheckResourceAttr(resourceName, "carrier_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", ""), + resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), + resource.TestCheckResourceAttrPair(resourceName, "destination_prefix_list_id", plResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "egress_only_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "gateway_id", ""), + resource.TestCheckResourceAttrPair(resourceName, "instance_id", instanceResourceName, "id"), + testAccCheckResourceAttrAccountID(resourceName, "instance_owner_id"), + resource.TestCheckResourceAttr(resourceName, "local_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "nat_gateway_id", ""), + resource.TestCheckResourceAttrPair(resourceName, "network_interface_id", instanceResourceName, "primary_network_interface_id"), + resource.TestCheckResourceAttr(resourceName, "origin", ec2.RouteOriginCreateRoute), + resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateActive), + resource.TestCheckResourceAttr(resourceName, "transit_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "vpc_endpoint_id", ""), + resource.TestCheckResourceAttr(resourceName, "vpc_peering_connection_id", ""), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateIdFunc: testAccAWSRouteImportStateIdFunc(resourceName), + ImportStateVerify: true, + }, + }, + }) +} - *v = *route +func TestAccAWSRoute_PrefixList_To_NetworkInterface_Unattached(t *testing.T) { + var route ec2.Route + resourceName := "aws_route.test" + eniResourceName := "aws_network_interface.test" + plResourceName := "aws_ec2_managed_prefix_list.test" + rName := acctest.RandomWithPrefix("tf-acc-test") - return nil - } + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSRouteDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSRouteConfigPrefixListNetworkInterfaceUnattached(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSRouteExists(resourceName, &route), + resource.TestCheckResourceAttr(resourceName, "carrier_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", ""), + resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), + resource.TestCheckResourceAttrPair(resourceName, "destination_prefix_list_id", plResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "egress_only_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "instance_id", ""), + resource.TestCheckResourceAttr(resourceName, "instance_owner_id", ""), + resource.TestCheckResourceAttr(resourceName, "local_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "nat_gateway_id", ""), + resource.TestCheckResourceAttrPair(resourceName, "network_interface_id", eniResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "origin", ec2.RouteOriginCreateRoute), + resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateBlackhole), + resource.TestCheckResourceAttr(resourceName, "transit_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "vpc_endpoint_id", ""), + resource.TestCheckResourceAttr(resourceName, "vpc_peering_connection_id", ""), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateIdFunc: testAccAWSRouteImportStateIdFunc(resourceName), + ImportStateVerify: true, + }, + }, + }) } -func testAccCheckAWSRouteDestroy(s *terraform.State) error { - for _, rs := range s.RootModule().Resources { - if rs.Type != "aws_route" { - continue - } +func TestAccAWSRoute_PrefixList_To_NetworkInterface_Attached(t *testing.T) { + var route ec2.Route + resourceName := "aws_route.test" + eniResourceName := "aws_network_interface.test" + instanceResourceName := "aws_instance.test" + plResourceName := "aws_ec2_managed_prefix_list.test" + rName := acctest.RandomWithPrefix("tf-acc-test") - conn := testAccProvider.Meta().(*AWSClient).ec2conn + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSRouteDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSRouteConfigPrefixListNetworkInterfaceAttached(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSRouteExists(resourceName, &route), + resource.TestCheckResourceAttr(resourceName, "carrier_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", ""), + resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), + resource.TestCheckResourceAttrPair(resourceName, "destination_prefix_list_id", plResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "egress_only_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "gateway_id", ""), + resource.TestCheckResourceAttrPair(resourceName, "instance_id", instanceResourceName, "id"), + testAccCheckResourceAttrAccountID(resourceName, "instance_owner_id"), + resource.TestCheckResourceAttr(resourceName, "local_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "nat_gateway_id", ""), + resource.TestCheckResourceAttrPair(resourceName, "network_interface_id", eniResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "origin", ec2.RouteOriginCreateRoute), + resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateActive), + resource.TestCheckResourceAttr(resourceName, "transit_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "vpc_endpoint_id", ""), + resource.TestCheckResourceAttr(resourceName, "vpc_peering_connection_id", ""), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateIdFunc: testAccAWSRouteImportStateIdFunc(resourceName), + ImportStateVerify: true, + }, + }, + }) +} - var err error - if v := rs.Primary.Attributes["destination_cidr_block"]; v != "" { - _, err = finder.RouteByIPv4Destination(conn, rs.Primary.Attributes["route_table_id"], v) - } else if v := rs.Primary.Attributes["destination_ipv6_cidr_block"]; v != "" { - _, err = finder.RouteByIPv6Destination(conn, rs.Primary.Attributes["route_table_id"], v) - } else if v := rs.Primary.Attributes["destination_prefix_list_id"]; v != "" { - _, err = finder.RouteByPrefixListIDDestination(conn, rs.Primary.Attributes["route_table_id"], v) - } +func TestAccAWSRoute_PrefixList_To_VpcPeeringConnection(t *testing.T) { + var route ec2.Route + resourceName := "aws_route.test" + pcxResourceName := "aws_vpc_peering_connection.test" + plResourceName := "aws_ec2_managed_prefix_list.test" + rName := acctest.RandomWithPrefix("tf-acc-test") - if tfresource.NotFound(err) { - continue - } + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSRouteDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSRouteConfigPrefixListVpcPeeringConnection(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSRouteExists(resourceName, &route), + resource.TestCheckResourceAttr(resourceName, "carrier_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", ""), + resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), + resource.TestCheckResourceAttrPair(resourceName, "destination_prefix_list_id", plResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "egress_only_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "instance_id", ""), + resource.TestCheckResourceAttr(resourceName, "instance_owner_id", ""), + resource.TestCheckResourceAttr(resourceName, "local_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "nat_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "network_interface_id", ""), + resource.TestCheckResourceAttr(resourceName, "origin", ec2.RouteOriginCreateRoute), + resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateActive), + resource.TestCheckResourceAttr(resourceName, "transit_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "vpc_endpoint_id", ""), + resource.TestCheckResourceAttrPair(resourceName, "vpc_peering_connection_id", pcxResourceName, "id"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateIdFunc: testAccAWSRouteImportStateIdFunc(resourceName), + ImportStateVerify: true, + }, + }, + }) +} - if err != nil { - return err - } +func TestAccAWSRoute_PrefixList_To_NatGateway(t *testing.T) { + var route ec2.Route + resourceName := "aws_route.test" + ngwResourceName := "aws_nat_gateway.test" + plResourceName := "aws_ec2_managed_prefix_list.test" + rName := acctest.RandomWithPrefix("tf-acc-test") - return fmt.Errorf("Route still exists") - } + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSRouteDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSRouteConfigPrefixListNatGateway(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSRouteExists(resourceName, &route), + resource.TestCheckResourceAttr(resourceName, "carrier_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", ""), + resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), + resource.TestCheckResourceAttrPair(resourceName, "destination_prefix_list_id", plResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "egress_only_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "instance_id", ""), + resource.TestCheckResourceAttr(resourceName, "instance_owner_id", ""), + resource.TestCheckResourceAttr(resourceName, "local_gateway_id", ""), + resource.TestCheckResourceAttrPair(resourceName, "nat_gateway_id", ngwResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "network_interface_id", ""), + resource.TestCheckResourceAttr(resourceName, "origin", ec2.RouteOriginCreateRoute), + resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateActive), + resource.TestCheckResourceAttr(resourceName, "transit_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "vpc_endpoint_id", ""), + resource.TestCheckResourceAttr(resourceName, "vpc_peering_connection_id", ""), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateIdFunc: testAccAWSRouteImportStateIdFunc(resourceName), + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAWSRoute_PrefixList_To_TransitGateway(t *testing.T) { + var route ec2.Route + resourceName := "aws_route.test" + tgwResourceName := "aws_ec2_transit_gateway.test" + plResourceName := "aws_ec2_managed_prefix_list.test" + rName := acctest.RandomWithPrefix("tf-acc-test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSRouteDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSRouteConfigPrefixListTransitGateway(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSRouteExists(resourceName, &route), + resource.TestCheckResourceAttr(resourceName, "carrier_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", ""), + resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), + resource.TestCheckResourceAttrPair(resourceName, "destination_prefix_list_id", plResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "egress_only_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "instance_id", ""), + resource.TestCheckResourceAttr(resourceName, "instance_owner_id", ""), + resource.TestCheckResourceAttr(resourceName, "local_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "nat_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "network_interface_id", ""), + resource.TestCheckResourceAttr(resourceName, "origin", ec2.RouteOriginCreateRoute), + resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateActive), + resource.TestCheckResourceAttrPair(resourceName, "transit_gateway_id", tgwResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "vpc_endpoint_id", ""), + resource.TestCheckResourceAttr(resourceName, "vpc_peering_connection_id", ""), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateIdFunc: testAccAWSRouteImportStateIdFunc(resourceName), + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAWSRoute_PrefixList_To_CarrierGateway(t *testing.T) { + var route ec2.Route + resourceName := "aws_route.test" + cgwResourceName := "aws_ec2_carrier_gateway.test" + plResourceName := "aws_ec2_managed_prefix_list.test" + rName := acctest.RandomWithPrefix("tf-acc-test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSWavelengthZoneAvailable(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSRouteDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSRouteConfigPrefixListCarrierGateway(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSRouteExists(resourceName, &route), + resource.TestCheckResourceAttrPair(resourceName, "carrier_gateway_id", cgwResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", ""), + resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), + resource.TestCheckResourceAttrPair(resourceName, "destination_prefix_list_id", plResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "egress_only_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "instance_id", ""), + resource.TestCheckResourceAttr(resourceName, "instance_owner_id", ""), + resource.TestCheckResourceAttr(resourceName, "local_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "nat_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "network_interface_id", ""), + resource.TestCheckResourceAttr(resourceName, "origin", ec2.RouteOriginCreateRoute), + resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateActive), + resource.TestCheckResourceAttr(resourceName, "transit_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "vpc_endpoint_id", ""), + resource.TestCheckResourceAttr(resourceName, "vpc_peering_connection_id", ""), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateIdFunc: testAccAWSRouteImportStateIdFunc(resourceName), + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAWSRoute_PrefixList_To_LocalGateway(t *testing.T) { + var route ec2.Route + resourceName := "aws_route.test" + localGatewayDataSourceName := "data.aws_ec2_local_gateway.first" + plResourceName := "aws_ec2_managed_prefix_list.test" + rName := acctest.RandomWithPrefix("tf-acc-test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSOutpostsOutposts(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSRouteDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSRouteConfigPrefixListLocalGateway(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSRouteExists(resourceName, &route), + resource.TestCheckResourceAttr(resourceName, "carrier_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", ""), + resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), + resource.TestCheckResourceAttrPair(resourceName, "destination_prefix_list_id", plResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "egress_only_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "instance_id", ""), + resource.TestCheckResourceAttr(resourceName, "instance_owner_id", ""), + resource.TestCheckResourceAttrPair(resourceName, "local_gateway_id", localGatewayDataSourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "nat_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "network_interface_id", ""), + resource.TestCheckResourceAttr(resourceName, "origin", ec2.RouteOriginCreateRoute), + resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateActive), + resource.TestCheckResourceAttr(resourceName, "transit_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "vpc_endpoint_id", ""), + resource.TestCheckResourceAttr(resourceName, "vpc_peering_connection_id", ""), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateIdFunc: testAccAWSRouteImportStateIdFunc(resourceName), + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAWSRoute_PrefixList_To_EgressOnlyInternetGateway(t *testing.T) { + var route ec2.Route + resourceName := "aws_route.test" + eoigwResourceName := "aws_egress_only_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) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSRouteDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSRouteConfigPrefixListEgressOnlyInternetGateway(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSRouteExists(resourceName, &route), + resource.TestCheckResourceAttr(resourceName, "carrier_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "destination_cidr_block", ""), + resource.TestCheckResourceAttr(resourceName, "destination_ipv6_cidr_block", ""), + resource.TestCheckResourceAttrPair(resourceName, "destination_prefix_list_id", plResourceName, "id"), + resource.TestCheckResourceAttrPair(resourceName, "egress_only_gateway_id", eoigwResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "instance_id", ""), + resource.TestCheckResourceAttr(resourceName, "instance_owner_id", ""), + resource.TestCheckResourceAttr(resourceName, "local_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "nat_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "network_interface_id", ""), + resource.TestCheckResourceAttr(resourceName, "origin", ec2.RouteOriginCreateRoute), + resource.TestCheckResourceAttr(resourceName, "state", ec2.RouteStateActive), + resource.TestCheckResourceAttr(resourceName, "transit_gateway_id", ""), + resource.TestCheckResourceAttr(resourceName, "vpc_endpoint_id", ""), + resource.TestCheckResourceAttr(resourceName, "vpc_peering_connection_id", ""), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateIdFunc: testAccAWSRouteImportStateIdFunc(resourceName), + ImportStateVerify: true, + }, + }, + }) +} + +func testAccCheckAWSRouteExists(n string, v *ec2.Route) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("No ID is set") + } + + conn := testAccProvider.Meta().(*AWSClient).ec2conn + + var route *ec2.Route + var err error + if v := rs.Primary.Attributes["destination_cidr_block"]; v != "" { + route, err = finder.RouteByIPv4Destination(conn, rs.Primary.Attributes["route_table_id"], v) + } else if v := rs.Primary.Attributes["destination_ipv6_cidr_block"]; v != "" { + route, err = finder.RouteByIPv6Destination(conn, rs.Primary.Attributes["route_table_id"], v) + } else if v := rs.Primary.Attributes["destination_prefix_list_id"]; v != "" { + route, err = finder.RouteByPrefixListIDDestination(conn, rs.Primary.Attributes["route_table_id"], v) + } + + if err != nil { + return err + } + + *v = *route + + return nil + } +} + +func testAccCheckAWSRouteDestroy(s *terraform.State) error { + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_route" { + continue + } + + conn := testAccProvider.Meta().(*AWSClient).ec2conn + + var err error + if v := rs.Primary.Attributes["destination_cidr_block"]; v != "" { + _, err = finder.RouteByIPv4Destination(conn, rs.Primary.Attributes["route_table_id"], v) + } else if v := rs.Primary.Attributes["destination_ipv6_cidr_block"]; v != "" { + _, err = finder.RouteByIPv6Destination(conn, rs.Primary.Attributes["route_table_id"], v) + } else if v := rs.Primary.Attributes["destination_prefix_list_id"]; v != "" { + _, err = finder.RouteByPrefixListIDDestination(conn, rs.Primary.Attributes["route_table_id"], v) + } + + if tfresource.NotFound(err) { + continue + } + + if err != nil { + return err + } + + return fmt.Errorf("Route still exists") + } + + return nil +} + +func testAccAWSRouteImportStateIdFunc(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) + } + + destination := rs.Primary.Attributes["destination_cidr_block"] + if v, ok := rs.Primary.Attributes["destination_ipv6_cidr_block"]; ok && v != "" { + destination = v + } + if v, ok := rs.Primary.Attributes["destination_prefix_list_id"]; ok && v != "" { + destination = v + } + + return fmt.Sprintf("%s_%s", rs.Primary.Attributes["route_table_id"], destination), nil + } +} + +func testAccAWSRouteConfigIpv4InternetGateway(rName, destinationCidr 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_route_table" "test" { + vpc_id = aws_vpc.test.id + + tags = { + Name = %[1]q + } +} + +resource "aws_route" "test" { + route_table_id = aws_route_table.test.id + destination_cidr_block = %[2]q + gateway_id = aws_internet_gateway.test.id +} +`, rName, destinationCidr) +} + +func testAccAWSRouteConfigIpv6InternetGateway(rName, destinationCidr string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { + cidr_block = "10.1.0.0/16" + assign_generated_ipv6_cidr_block = true + + tags = { + Name = %[1]q + } +} + +resource "aws_egress_only_internet_gateway" "test" { + vpc_id = aws_vpc.test.id + + tags = { + Name = %[1]q + } +} + +resource "aws_internet_gateway" "test" { + vpc_id = aws_vpc.test.id + + tags = { + Name = %[1]q + } +} + +resource "aws_route_table" "test" { + vpc_id = aws_vpc.test.id + + tags = { + Name = %[1]q + } +} + +resource "aws_route" "test" { + route_table_id = aws_route_table.test.id + destination_ipv6_cidr_block = %[2]q + gateway_id = aws_internet_gateway.test.id +} +`, rName, destinationCidr) +} + +func testAccAWSRouteConfigIpv6NetworkInterfaceUnattached(rName, destinationCidr string) string { + return composeConfig( + testAccAvailableAZsNoOptInConfig(), + 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_subnet" "test" { + cidr_block = "10.1.1.0/24" + vpc_id = aws_vpc.test.id + availability_zone = data.aws_availability_zones.available.names[0] + ipv6_cidr_block = cidrsubnet(aws_vpc.test.ipv6_cidr_block, 8, 1) + + tags = { + Name = %[1]q + } +} + +resource "aws_network_interface" "test" { + subnet_id = aws_subnet.test.id + + tags = { + Name = %[1]q + } +} + +resource "aws_route_table" "test" { + vpc_id = aws_vpc.test.id + + tags = { + Name = %[1]q + } +} + +resource "aws_route" "test" { + route_table_id = aws_route_table.test.id + destination_ipv6_cidr_block = %[2]q + network_interface_id = aws_network_interface.test.id +} +`, rName, destinationCidr)) +} + +func testAccAWSRouteConfigIpv6Instance(rName, destinationCidr string) string { + return composeConfig( + testAccLatestAmazonNatInstanceAmiConfig(), + testAccAvailableAZsNoOptInConfig(), + testAccAvailableEc2InstanceTypeForAvailabilityZone("data.aws_availability_zones.available.names[0]", "t3.micro", "t2.micro"), + 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_subnet" "test" { + cidr_block = "10.1.1.0/24" + vpc_id = aws_vpc.test.id + availability_zone = data.aws_availability_zones.available.names[0] + ipv6_cidr_block = cidrsubnet(aws_vpc.test.ipv6_cidr_block, 8, 1) + + tags = { + Name = %[1]q + } +} + +resource "aws_instance" "test" { + ami = data.aws_ami.amzn-ami-nat-instance.id + instance_type = data.aws_ec2_instance_type_offering.available.instance_type + subnet_id = aws_subnet.test.id + + ipv6_address_count = 1 + + tags = { + Name = %[1]q + } +} + +resource "aws_route_table" "test" { + vpc_id = aws_vpc.test.id + + tags = { + Name = %[1]q + } +} + +resource "aws_route" "test" { + route_table_id = aws_route_table.test.id + destination_ipv6_cidr_block = %[2]q + instance_id = aws_instance.test.id +} +`, rName, destinationCidr)) +} + +func testAccAWSRouteConfigIpv6VpcPeeringConnection(rName, destinationCidr string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { + cidr_block = "10.1.0.0/16" + assign_generated_ipv6_cidr_block = true + + tags = { + Name = %[1]q + } +} + +resource "aws_vpc" "target" { + cidr_block = "10.0.0.0/16" + assign_generated_ipv6_cidr_block = true + + tags = { + Name = %[1]q + } +} + +resource "aws_vpc_peering_connection" "test" { + vpc_id = aws_vpc.test.id + peer_vpc_id = aws_vpc.target.id + auto_accept = true + + tags = { + Name = %[1]q + } +} + +resource "aws_route_table" "test" { + vpc_id = aws_vpc.test.id + + tags = { + Name = %[1]q + } +} + +resource "aws_route" "test" { + route_table_id = aws_route_table.test.id + destination_ipv6_cidr_block = %[2]q + vpc_peering_connection_id = aws_vpc_peering_connection.test.id +} +`, rName, destinationCidr) +} + +func testAccAWSRouteConfigIpv6EgressOnlyInternetGateway(rName, destinationCidr string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { + cidr_block = "10.1.0.0/16" + assign_generated_ipv6_cidr_block = true + + tags = { + Name = %[1]q + } +} + +resource "aws_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 + + tags = { + Name = %[1]q + } +} + +resource "aws_route" "test" { + route_table_id = aws_route_table.test.id + destination_ipv6_cidr_block = %[2]q + egress_only_gateway_id = aws_egress_only_internet_gateway.test.id +} +`, rName, destinationCidr) +} + +func testAccAWSRouteConfigWithVpcEndpoint(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 + } +} - return nil +resource "aws_route_table" "test" { + vpc_id = aws_vpc.test.id + + tags = { + Name = %[1]q + } } -func testAccAWSRouteImportStateIdFunc(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) - } +resource "aws_route" "test" { + route_table_id = aws_route_table.test.id + destination_cidr_block = "10.3.0.0/16" + gateway_id = aws_internet_gateway.test.id - destination := rs.Primary.Attributes["destination_cidr_block"] - if v, ok := rs.Primary.Attributes["destination_ipv6_cidr_block"]; ok && v != "" { - destination = v - } - if v, ok := rs.Primary.Attributes["destination_prefix_list_id"]; ok && v != "" { - destination = v - } + # Forcing endpoint to create before route - without this the crash is a race. + depends_on = [aws_vpc_endpoint.test] +} - return fmt.Sprintf("%s_%s", rs.Primary.Attributes["route_table_id"], destination), nil - } +data "aws_region" "current" {} + +resource "aws_vpc_endpoint" "test" { + vpc_id = aws_vpc.test.id + service_name = "com.amazonaws.${data.aws_region.current.name}.s3" + route_table_ids = [aws_route_table.test.id] +} +`, rName) } -func testAccAWSRouteConfigIpv4InternetGateway(rName, destinationCidr string) string { - return fmt.Sprintf(` +func testAccAWSRouteConfigIpv4TransitGateway(rName, destinationCidr string) string { + return composeConfig( + testAccAvailableAZsNoOptInDefaultExcludeConfig(), + fmt.Sprintf(` resource "aws_vpc" "test" { cidr_block = "10.1.0.0/16" @@ -1609,8 +2358,26 @@ resource "aws_vpc" "test" { } } -resource "aws_internet_gateway" "test" { - vpc_id = aws_vpc.test.id +resource "aws_subnet" "test" { + availability_zone = data.aws_availability_zones.available.names[0] + cidr_block = "10.1.1.0/24" + vpc_id = aws_vpc.test.id + + tags = { + Name = %[1]q + } +} + +resource "aws_ec2_transit_gateway" "test" { + tags = { + Name = %[1]q + } +} + +resource "aws_ec2_transit_gateway_vpc_attachment" "test" { + subnet_ids = [aws_subnet.test.id] + transit_gateway_id = aws_ec2_transit_gateway.test.id + vpc_id = aws_vpc.test.id tags = { Name = %[1]q @@ -1626,15 +2393,17 @@ resource "aws_route_table" "test" { } resource "aws_route" "test" { - route_table_id = aws_route_table.test.id destination_cidr_block = %[2]q - gateway_id = aws_internet_gateway.test.id + route_table_id = aws_route_table.test.id + transit_gateway_id = aws_ec2_transit_gateway_vpc_attachment.test.transit_gateway_id } -`, rName, destinationCidr) +`, rName, destinationCidr)) } -func testAccAWSRouteConfigIpv6InternetGateway(rName, destinationCidr string) string { - return fmt.Sprintf(` +func testAccAWSRouteConfigIpv6TransitGateway(rName, destinationCidr string) string { + return composeConfig( + testAccAvailableAZsNoOptInConfig(), + fmt.Sprintf(` resource "aws_vpc" "test" { cidr_block = "10.1.0.0/16" assign_generated_ipv6_cidr_block = true @@ -1644,16 +2413,26 @@ resource "aws_vpc" "test" { } } -resource "aws_egress_only_internet_gateway" "test" { - vpc_id = aws_vpc.test.id +resource "aws_subnet" "test" { + availability_zone = data.aws_availability_zones.available.names[0] + cidr_block = "10.1.1.0/24" + vpc_id = aws_vpc.test.id tags = { Name = %[1]q } } -resource "aws_internet_gateway" "test" { - vpc_id = aws_vpc.test.id +resource "aws_ec2_transit_gateway" "test" { + tags = { + Name = %[1]q + } +} + +resource "aws_ec2_transit_gateway_vpc_attachment" "test" { + subnet_ids = [aws_subnet.test.id] + transit_gateway_id = aws_ec2_transit_gateway.test.id + vpc_id = aws_vpc.test.id tags = { Name = %[1]q @@ -1669,17 +2448,18 @@ resource "aws_route_table" "test" { } resource "aws_route" "test" { - route_table_id = aws_route_table.test.id destination_ipv6_cidr_block = %[2]q - gateway_id = aws_internet_gateway.test.id + route_table_id = aws_route_table.test.id + transit_gateway_id = aws_ec2_transit_gateway_vpc_attachment.test.transit_gateway_id } -`, rName, destinationCidr) +`, rName, destinationCidr)) } -func testAccAWSRouteConfigPrefixListInternetGateway(rName string) string { +func testAccAWSRouteConfigConditionalIpv4Ipv6(rName, destinationCidr, destinationIpv6Cidr string, ipv6Route bool) string { return fmt.Sprintf(` resource "aws_vpc" "test" { - cidr_block = "10.1.0.0/16" + cidr_block = "10.1.0.0/16" + assign_generated_ipv6_cidr_block = true tags = { Name = %[1]q @@ -1694,12 +2474,6 @@ resource "aws_internet_gateway" "test" { } } -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 @@ -1708,21 +2482,30 @@ resource "aws_route_table" "test" { } } +locals { + ipv6 = %[4]t + destination = %[2]q + destination_ipv6 = %[3]q +} + resource "aws_route" "test" { - route_table_id = aws_route_table.test.id - destination_prefix_list_id = aws_ec2_managed_prefix_list.test.id - gateway_id = aws_internet_gateway.test.id + route_table_id = aws_route_table.test.id + gateway_id = aws_internet_gateway.test.id + + destination_cidr_block = local.ipv6 ? "" : local.destination + destination_ipv6_cidr_block = local.ipv6 ? local.destination_ipv6 : "" } -`, rName) +`, rName, destinationCidr, destinationIpv6Cidr, ipv6Route) } -func testAccAWSRouteConfigIpv6NetworkInterfaceUnattached(rName, destinationCidr string) string { +func testAccAWSRouteConfigIpv4Instance(rName, destinationCidr string) string { return composeConfig( + testAccLatestAmazonNatInstanceAmiConfig(), testAccAvailableAZsNoOptInConfig(), + testAccAvailableEc2InstanceTypeForAvailabilityZone("data.aws_availability_zones.available.names[0]", "t3.micro", "t2.micro"), fmt.Sprintf(` resource "aws_vpc" "test" { - cidr_block = "10.1.0.0/16" - assign_generated_ipv6_cidr_block = true + cidr_block = "10.1.0.0/16" tags = { Name = %[1]q @@ -1733,15 +2516,16 @@ resource "aws_subnet" "test" { cidr_block = "10.1.1.0/24" vpc_id = aws_vpc.test.id availability_zone = data.aws_availability_zones.available.names[0] - ipv6_cidr_block = cidrsubnet(aws_vpc.test.ipv6_cidr_block, 8, 1) tags = { Name = %[1]q } } -resource "aws_network_interface" "test" { - subnet_id = aws_subnet.test.id +resource "aws_instance" "test" { + ami = data.aws_ami.amzn-ami-nat-instance.id + instance_type = data.aws_ec2_instance_type_offering.available.instance_type + subnet_id = aws_subnet.test.id tags = { Name = %[1]q @@ -1757,22 +2541,19 @@ resource "aws_route_table" "test" { } resource "aws_route" "test" { - route_table_id = aws_route_table.test.id - destination_ipv6_cidr_block = %[2]q - network_interface_id = aws_network_interface.test.id + route_table_id = aws_route_table.test.id + destination_cidr_block = %[2]q + instance_id = aws_instance.test.id } `, rName, destinationCidr)) } -func testAccAWSRouteConfigIpv6Instance(rName, destinationCidr string) string { +func testAccAWSRouteConfigIpv4NetworkInterfaceUnattached(rName, destinationCidr string) string { return composeConfig( - testAccLatestAmazonNatInstanceAmiConfig(), testAccAvailableAZsNoOptInConfig(), - testAccAvailableEc2InstanceTypeForAvailabilityZone("data.aws_availability_zones.available.names[0]", "t3.micro", "t2.micro"), fmt.Sprintf(` resource "aws_vpc" "test" { - cidr_block = "10.1.0.0/16" - assign_generated_ipv6_cidr_block = true + cidr_block = "10.1.0.0/16" tags = { Name = %[1]q @@ -1783,19 +2564,111 @@ resource "aws_subnet" "test" { cidr_block = "10.1.1.0/24" vpc_id = aws_vpc.test.id availability_zone = data.aws_availability_zones.available.names[0] - ipv6_cidr_block = cidrsubnet(aws_vpc.test.ipv6_cidr_block, 8, 1) tags = { Name = %[1]q } } -resource "aws_instance" "test" { - ami = data.aws_ami.amzn-ami-nat-instance.id - instance_type = data.aws_ec2_instance_type_offering.available.instance_type - subnet_id = aws_subnet.test.id +resource "aws_network_interface" "test" { + subnet_id = aws_subnet.test.id - ipv6_address_count = 1 + tags = { + Name = %[1]q + } +} + +resource "aws_route_table" "test" { + vpc_id = aws_vpc.test.id + + tags = { + Name = %[1]q + } +} + +resource "aws_route" "test" { + route_table_id = aws_route_table.test.id + destination_cidr_block = %[2]q + network_interface_id = aws_network_interface.test.id +} +`, rName, destinationCidr)) +} + +func testAccAWSRouteResourceConfigIpv4LocalGateway(rName, destinationCidr string) string { + return fmt.Sprintf(` +data "aws_ec2_local_gateways" "all" {} + +data "aws_ec2_local_gateway" "first" { + id = tolist(data.aws_ec2_local_gateways.all.ids)[0] +} + +data "aws_ec2_local_gateway_route_tables" "all" {} + +data "aws_ec2_local_gateway_route_table" "first" { + local_gateway_route_table_id = tolist(data.aws_ec2_local_gateway_route_tables.all.ids)[0] +} + +resource "aws_vpc" "test" { + cidr_block = "10.0.0.0/16" + + tags = { + Name = %[1]q + } +} + +resource "aws_ec2_local_gateway_route_table_vpc_association" "example" { + local_gateway_route_table_id = data.aws_ec2_local_gateway_route_table.first.id + vpc_id = aws_vpc.test.id + + tags = { + Name = %[1]q + } +} + +resource "aws_route_table" "test" { + vpc_id = aws_vpc.test.id + + tags = { + Name = %[1]q + } + + depends_on = [aws_ec2_local_gateway_route_table_vpc_association.example] +} + +resource "aws_route" "test" { + route_table_id = aws_route_table.test.id + destination_cidr_block = %[2]q + local_gateway_id = data.aws_ec2_local_gateway.first.id +} +`, rName, destinationCidr) +} + +func testAccAWSRouteResourceConfigIpv6LocalGateway(rName, destinationCidr string) string { + return fmt.Sprintf(` +data "aws_ec2_local_gateways" "all" {} + +data "aws_ec2_local_gateway" "first" { + id = tolist(data.aws_ec2_local_gateways.all.ids)[0] +} + +data "aws_ec2_local_gateway_route_tables" "all" {} + +data "aws_ec2_local_gateway_route_table" "first" { + local_gateway_route_table_id = tolist(data.aws_ec2_local_gateway_route_tables.all.ids)[0] +} + +resource "aws_vpc" "test" { + cidr_block = "10.0.0.0/16" + assign_generated_ipv6_cidr_block = true + + tags = { + Name = %[1]q + } +} + +resource "aws_ec2_local_gateway_route_table_vpc_association" "example" { + local_gateway_route_table_id = data.aws_ec2_local_gateway_route_table.first.id + vpc_id = aws_vpc.test.id tags = { Name = %[1]q @@ -1808,40 +2681,58 @@ resource "aws_route_table" "test" { tags = { Name = %[1]q } + + depends_on = [aws_ec2_local_gateway_route_table_vpc_association.example] } resource "aws_route" "test" { route_table_id = aws_route_table.test.id destination_ipv6_cidr_block = %[2]q - instance_id = aws_instance.test.id + local_gateway_id = data.aws_ec2_local_gateway.first.id } -`, rName, destinationCidr)) +`, rName, destinationCidr) } -func testAccAWSRouteConfigIpv6VpcPeeringConnection(rName, destinationCidr string) string { - return fmt.Sprintf(` +func testAccAWSRouteConfigIpv4NetworkInterfaceAttached(rName, destinationCidr string) string { + return composeConfig( + testAccLatestAmazonNatInstanceAmiConfig(), + testAccAvailableAZsNoOptInConfig(), + testAccAvailableEc2InstanceTypeForAvailabilityZone("data.aws_availability_zones.available.names[0]", "t3.micro", "t2.micro"), + fmt.Sprintf(` resource "aws_vpc" "test" { - cidr_block = "10.1.0.0/16" - assign_generated_ipv6_cidr_block = true + cidr_block = "10.1.0.0/16" tags = { Name = %[1]q } } -resource "aws_vpc" "target" { - cidr_block = "10.0.0.0/16" - assign_generated_ipv6_cidr_block = true +resource "aws_subnet" "test" { + cidr_block = "10.1.1.0/24" + vpc_id = aws_vpc.test.id + availability_zone = data.aws_availability_zones.available.names[0] tags = { Name = %[1]q } } -resource "aws_vpc_peering_connection" "test" { - vpc_id = aws_vpc.test.id - peer_vpc_id = aws_vpc.target.id - auto_accept = true +resource "aws_network_interface" "test" { + subnet_id = aws_subnet.test.id + + tags = { + Name = %[1]q + } +} + +resource "aws_instance" "test" { + ami = data.aws_ami.amzn-ami-nat-instance.id + instance_type = data.aws_ec2_instance_type_offering.available.instance_type + + network_interface { + device_index = 0 + network_interface_id = aws_network_interface.test.id + } tags = { Name = %[1]q @@ -1857,60 +2748,69 @@ resource "aws_route_table" "test" { } resource "aws_route" "test" { - route_table_id = aws_route_table.test.id - destination_ipv6_cidr_block = %[2]q - vpc_peering_connection_id = aws_vpc_peering_connection.test.id + route_table_id = aws_route_table.test.id + destination_cidr_block = %[2]q + network_interface_id = aws_network_interface.test.id + + # Wait for the ENI attachment. + depends_on = [aws_instance.test] } -`, rName, destinationCidr) +`, rName, destinationCidr)) } -func testAccAWSRouteConfigIpv6EgressOnlyInternetGateway(rName, destinationCidr string) string { - return fmt.Sprintf(` +func testAccAWSRouteConfigIpv4NetworkInterfaceTwoAttachments(rName, destinationCidr, targetResourceName string) string { + return composeConfig( + testAccLatestAmazonNatInstanceAmiConfig(), + testAccAvailableAZsNoOptInConfig(), + testAccAvailableEc2InstanceTypeForAvailabilityZone("data.aws_availability_zones.available.names[0]", "t3.micro", "t2.micro"), + fmt.Sprintf(` resource "aws_vpc" "test" { - cidr_block = "10.1.0.0/16" - assign_generated_ipv6_cidr_block = true + cidr_block = "10.1.0.0/16" tags = { Name = %[1]q } } -resource "aws_egress_only_internet_gateway" "test" { - vpc_id = aws_vpc.test.id +resource "aws_subnet" "test" { + cidr_block = "10.1.1.0/24" + vpc_id = aws_vpc.test.id + availability_zone = data.aws_availability_zones.available.names[0] tags = { Name = %[1]q } } -resource "aws_route_table" "test" { - vpc_id = aws_vpc.test.id +resource "aws_network_interface" "test1" { + subnet_id = aws_subnet.test.id tags = { Name = %[1]q } } -resource "aws_route" "test" { - route_table_id = aws_route_table.test.id - destination_ipv6_cidr_block = %[2]q - egress_only_gateway_id = aws_egress_only_internet_gateway.test.id -} -`, rName, destinationCidr) -} - -func testAccAWSRouteConfigWithVpcEndpoint(rName string) string { - return fmt.Sprintf(` -resource "aws_vpc" "test" { - cidr_block = "10.1.0.0/16" +resource "aws_network_interface" "test2" { + subnet_id = aws_subnet.test.id tags = { Name = %[1]q } } -resource "aws_internet_gateway" "test" { - vpc_id = aws_vpc.test.id +resource "aws_instance" "test" { + ami = data.aws_ami.amzn-ami-nat-instance.id + instance_type = data.aws_ec2_instance_type_offering.available.instance_type + + network_interface { + device_index = 0 + network_interface_id = aws_network_interface.test1.id + } + + network_interface { + device_index = 1 + network_interface_id = aws_network_interface.test2.id + } tags = { Name = %[1]q @@ -1927,27 +2827,17 @@ resource "aws_route_table" "test" { resource "aws_route" "test" { route_table_id = aws_route_table.test.id - destination_cidr_block = "10.3.0.0/16" - gateway_id = aws_internet_gateway.test.id - - # Forcing endpoint to create before route - without this the crash is a race. - depends_on = [aws_vpc_endpoint.test] -} - -data "aws_region" "current" {} + destination_cidr_block = %[2]q + network_interface_id = %[3]s.id -resource "aws_vpc_endpoint" "test" { - vpc_id = aws_vpc.test.id - service_name = "com.amazonaws.${data.aws_region.current.name}.s3" - route_table_ids = [aws_route_table.test.id] + # Wait for the ENI attachment. + depends_on = [aws_instance.test] } -`, rName) +`, rName, destinationCidr, targetResourceName)) } -func testAccAWSRouteConfigIpv4TransitGateway(rName, destinationCidr string) string { - return composeConfig( - testAccAvailableAZsNoOptInDefaultExcludeConfig(), - fmt.Sprintf(` +func testAccAWSRouteConfigIpv4VpcPeeringConnection(rName, destinationCidr string) string { + return fmt.Sprintf(` resource "aws_vpc" "test" { cidr_block = "10.1.0.0/16" @@ -1956,26 +2846,18 @@ resource "aws_vpc" "test" { } } -resource "aws_subnet" "test" { - availability_zone = data.aws_availability_zones.available.names[0] - cidr_block = "10.1.1.0/24" - vpc_id = aws_vpc.test.id - - tags = { - Name = %[1]q - } -} +resource "aws_vpc" "target" { + cidr_block = "10.0.0.0/16" -resource "aws_ec2_transit_gateway" "test" { tags = { Name = %[1]q } } -resource "aws_ec2_transit_gateway_vpc_attachment" "test" { - subnet_ids = [aws_subnet.test.id] - transit_gateway_id = aws_ec2_transit_gateway.test.id - vpc_id = aws_vpc.test.id +resource "aws_vpc_peering_connection" "test" { + vpc_id = aws_vpc.test.id + peer_vpc_id = aws_vpc.target.id + auto_accept = true tags = { Name = %[1]q @@ -1991,20 +2873,17 @@ resource "aws_route_table" "test" { } resource "aws_route" "test" { - destination_cidr_block = %[2]q - route_table_id = aws_route_table.test.id - transit_gateway_id = aws_ec2_transit_gateway_vpc_attachment.test.transit_gateway_id + route_table_id = aws_route_table.test.id + destination_cidr_block = %[2]q + vpc_peering_connection_id = aws_vpc_peering_connection.test.id } -`, rName, destinationCidr)) +`, rName, destinationCidr) } -func testAccAWSRouteConfigIpv6TransitGateway(rName, destinationCidr string) string { - return composeConfig( - testAccAvailableAZsNoOptInConfig(), - fmt.Sprintf(` +func testAccAWSRouteConfigIpv4NatGateway(rName, destinationCidr string) string { + return fmt.Sprintf(` resource "aws_vpc" "test" { - cidr_block = "10.1.0.0/16" - assign_generated_ipv6_cidr_block = true + cidr_block = "10.1.0.0/16" tags = { Name = %[1]q @@ -2012,29 +2891,41 @@ resource "aws_vpc" "test" { } resource "aws_subnet" "test" { - availability_zone = data.aws_availability_zones.available.names[0] - cidr_block = "10.1.1.0/24" - vpc_id = aws_vpc.test.id + cidr_block = "10.1.1.0/24" + vpc_id = aws_vpc.test.id + + map_public_ip_on_launch = true tags = { Name = %[1]q } } -resource "aws_ec2_transit_gateway" "test" { +resource "aws_internet_gateway" "test" { + vpc_id = aws_vpc.test.id + tags = { Name = %[1]q } } -resource "aws_ec2_transit_gateway_vpc_attachment" "test" { - subnet_ids = [aws_subnet.test.id] - transit_gateway_id = aws_ec2_transit_gateway.test.id - vpc_id = aws_vpc.test.id +resource "aws_eip" "test" { + vpc = true + + tags = { + Name = %[1]q + } +} + +resource "aws_nat_gateway" "test" { + allocation_id = aws_eip.test.id + subnet_id = aws_subnet.test.id tags = { Name = %[1]q } + + depends_on = [aws_internet_gateway.test] } resource "aws_route_table" "test" { @@ -2046,25 +2937,24 @@ resource "aws_route_table" "test" { } resource "aws_route" "test" { - destination_ipv6_cidr_block = %[2]q - route_table_id = aws_route_table.test.id - transit_gateway_id = aws_ec2_transit_gateway_vpc_attachment.test.transit_gateway_id + route_table_id = aws_route_table.test.id + destination_cidr_block = %[2]q + nat_gateway_id = aws_nat_gateway.test.id } -`, rName, destinationCidr)) +`, rName, destinationCidr) } -func testAccAWSRouteConfigConditionalIpv4Ipv6(rName, destinationCidr, destinationIpv6Cidr string, ipv6Route bool) string { +func testAccAWSRouteConfigIpv4VpnGateway(rName, destinationCidr string) string { return fmt.Sprintf(` resource "aws_vpc" "test" { - cidr_block = "10.1.0.0/16" - assign_generated_ipv6_cidr_block = true + cidr_block = "10.1.0.0/16" tags = { Name = %[1]q } } -resource "aws_internet_gateway" "test" { +resource "aws_vpn_gateway" "test" { vpc_id = aws_vpc.test.id tags = { @@ -2080,50 +2970,27 @@ resource "aws_route_table" "test" { } } -locals { - ipv6 = %[4]t - destination = %[2]q - destination_ipv6 = %[3]q -} - resource "aws_route" "test" { - route_table_id = aws_route_table.test.id - gateway_id = aws_internet_gateway.test.id - - destination_cidr_block = local.ipv6 ? "" : local.destination - destination_ipv6_cidr_block = local.ipv6 ? local.destination_ipv6 : "" + route_table_id = aws_route_table.test.id + destination_cidr_block = %[2]q + gateway_id = aws_vpn_gateway.test.id } -`, rName, destinationCidr, destinationIpv6Cidr, ipv6Route) +`, rName, destinationCidr) } -func testAccAWSRouteConfigIpv4Instance(rName, destinationCidr string) string { - return composeConfig( - testAccLatestAmazonNatInstanceAmiConfig(), - testAccAvailableAZsNoOptInConfig(), - testAccAvailableEc2InstanceTypeForAvailabilityZone("data.aws_availability_zones.available.names[0]", "t3.micro", "t2.micro"), - fmt.Sprintf(` +func testAccAWSRouteConfigIpv6VpnGateway(rName, destinationCidr string) string { + return fmt.Sprintf(` resource "aws_vpc" "test" { - cidr_block = "10.1.0.0/16" - - tags = { - Name = %[1]q - } -} - -resource "aws_subnet" "test" { - cidr_block = "10.1.1.0/24" - vpc_id = aws_vpc.test.id - availability_zone = data.aws_availability_zones.available.names[0] + cidr_block = "10.1.0.0/16" + assign_generated_ipv6_cidr_block = true tags = { Name = %[1]q - } -} - -resource "aws_instance" "test" { - ami = data.aws_ami.amzn-ami-nat-instance.id - instance_type = data.aws_ec2_instance_type_offering.available.instance_type - subnet_id = aws_subnet.test.id + } +} + +resource "aws_vpn_gateway" "test" { + vpc_id = aws_vpc.test.id tags = { Name = %[1]q @@ -2139,19 +3006,21 @@ resource "aws_route_table" "test" { } resource "aws_route" "test" { - route_table_id = aws_route_table.test.id - destination_cidr_block = %[2]q - instance_id = aws_instance.test.id + route_table_id = aws_route_table.test.id + destination_ipv6_cidr_block = %[2]q + gateway_id = aws_vpn_gateway.test.id } -`, rName, destinationCidr)) +`, rName, destinationCidr) } -func testAccAWSRouteConfigIpv4NetworkInterfaceUnattached(rName, destinationCidr string) string { +func testAccAWSRouteResourceConfigIpv4VpcEndpoint(rName, destinationCidr string) string { return composeConfig( testAccAvailableAZsNoOptInConfig(), fmt.Sprintf(` +data "aws_caller_identity" "current" {} + resource "aws_vpc" "test" { - cidr_block = "10.1.0.0/16" + cidr_block = "10.10.10.0/25" tags = { Name = %[1]q @@ -2159,17 +3028,39 @@ resource "aws_vpc" "test" { } resource "aws_subnet" "test" { - cidr_block = "10.1.1.0/24" - vpc_id = aws_vpc.test.id availability_zone = data.aws_availability_zones.available.names[0] + cidr_block = cidrsubnet(aws_vpc.test.cidr_block, 2, 0) + vpc_id = aws_vpc.test.id tags = { Name = %[1]q } } -resource "aws_network_interface" "test" { - subnet_id = aws_subnet.test.id +resource "aws_lb" "test" { + load_balancer_type = "gateway" + name = %[1]q + + subnet_mapping { + subnet_id = aws_subnet.test.id + } +} + +resource "aws_vpc_endpoint_service" "test" { + acceptance_required = false + allowed_principals = [data.aws_caller_identity.current.arn] + gateway_load_balancer_arns = [aws_lb.test.arn] + + tags = { + Name = %[1]q + } +} + +resource "aws_vpc_endpoint" "test" { + service_name = aws_vpc_endpoint_service.test.service_name + subnet_ids = [aws_subnet.test.id] + vpc_endpoint_type = aws_vpc_endpoint_service.test.service_type + vpc_id = aws_vpc.test.id tags = { Name = %[1]q @@ -2187,150 +3078,155 @@ resource "aws_route_table" "test" { resource "aws_route" "test" { route_table_id = aws_route_table.test.id destination_cidr_block = %[2]q - network_interface_id = aws_network_interface.test.id + vpc_endpoint_id = aws_vpc_endpoint.test.id } `, rName, destinationCidr)) } -func testAccAWSRouteResourceConfigIpv4LocalGateway(rName, destinationCidr string) string { - return fmt.Sprintf(` -data "aws_ec2_local_gateways" "all" {} - -data "aws_ec2_local_gateway" "first" { - id = tolist(data.aws_ec2_local_gateways.all.ids)[0] -} - -data "aws_ec2_local_gateway_route_tables" "all" {} - -data "aws_ec2_local_gateway_route_table" "first" { - local_gateway_route_table_id = tolist(data.aws_ec2_local_gateway_route_tables.all.ids)[0] +func testAccAWSRouteConfigIpv4FlexiTarget(rName, destinationCidr, targetAttribute, targetValue string) string { + return composeConfig( + testAccLatestAmazonLinuxHvmEbsAmiConfig(), + testAccAvailableAZsNoOptInDefaultExcludeConfig(), + testAccAvailableEc2InstanceTypeForAvailabilityZone("data.aws_availability_zones.available.names[0]", "t3.micro", "t2.micro"), + fmt.Sprintf(` +locals { + target_attr = %[3]q + target_value = %[4]s.id } resource "aws_vpc" "test" { - cidr_block = "10.0.0.0/16" + cidr_block = "10.1.0.0/16" tags = { Name = %[1]q } } -resource "aws_ec2_local_gateway_route_table_vpc_association" "example" { - local_gateway_route_table_id = data.aws_ec2_local_gateway_route_table.first.id - vpc_id = aws_vpc.test.id +resource "aws_vpn_gateway" "test" { + vpc_id = aws_vpc.test.id tags = { Name = %[1]q } } -resource "aws_route_table" "test" { +resource "aws_internet_gateway" "test" { vpc_id = aws_vpc.test.id tags = { Name = %[1]q } - - depends_on = [aws_ec2_local_gateway_route_table_vpc_association.example] } -resource "aws_route" "test" { - route_table_id = aws_route_table.test.id - destination_cidr_block = %[2]q - local_gateway_id = data.aws_ec2_local_gateway.first.id -} -`, rName, destinationCidr) -} +resource "aws_subnet" "test" { + cidr_block = "10.1.1.0/24" + vpc_id = aws_vpc.test.id + availability_zone = data.aws_availability_zones.available.names[0] -func testAccAWSRouteResourceConfigIpv6LocalGateway(rName, destinationCidr string) string { - return fmt.Sprintf(` -data "aws_ec2_local_gateways" "all" {} + map_public_ip_on_launch = true -data "aws_ec2_local_gateway" "first" { - id = tolist(data.aws_ec2_local_gateways.all.ids)[0] + tags = { + Name = %[1]q + } } -data "aws_ec2_local_gateway_route_tables" "all" {} +resource "aws_instance" "test" { + ami = data.aws_ami.amzn-ami-minimal-hvm-ebs.id + instance_type = data.aws_ec2_instance_type_offering.available.instance_type + subnet_id = aws_subnet.test.id -data "aws_ec2_local_gateway_route_table" "first" { - local_gateway_route_table_id = tolist(data.aws_ec2_local_gateway_route_tables.all.ids)[0] + tags = { + Name = %[1]q + } } -resource "aws_vpc" "test" { - cidr_block = "10.0.0.0/16" - assign_generated_ipv6_cidr_block = true - +resource "aws_ec2_transit_gateway" "test" { tags = { Name = %[1]q } } -resource "aws_ec2_local_gateway_route_table_vpc_association" "example" { - local_gateway_route_table_id = data.aws_ec2_local_gateway_route_table.first.id - vpc_id = aws_vpc.test.id +resource "aws_ec2_transit_gateway_vpc_attachment" "test" { + subnet_ids = [aws_subnet.test.id] + transit_gateway_id = aws_ec2_transit_gateway.test.id + vpc_id = aws_vpc.test.id tags = { Name = %[1]q } } -resource "aws_route_table" "test" { - vpc_id = aws_vpc.test.id +resource "aws_network_interface" "test" { + subnet_id = aws_subnet.test.id tags = { Name = %[1]q } - - depends_on = [aws_ec2_local_gateway_route_table_vpc_association.example] } -resource "aws_route" "test" { - route_table_id = aws_route_table.test.id - destination_ipv6_cidr_block = %[2]q - local_gateway_id = data.aws_ec2_local_gateway.first.id -} -`, rName, destinationCidr) +resource "aws_vpc" "target" { + cidr_block = "10.0.0.0/16" + + tags = { + Name = %[1]q + } } -func testAccAWSRouteConfigIpv4NetworkInterfaceAttached(rName, destinationCidr string) string { - return composeConfig( - testAccLatestAmazonNatInstanceAmiConfig(), - testAccAvailableAZsNoOptInConfig(), - testAccAvailableEc2InstanceTypeForAvailabilityZone("data.aws_availability_zones.available.names[0]", "t3.micro", "t2.micro"), - fmt.Sprintf(` -resource "aws_vpc" "test" { - cidr_block = "10.1.0.0/16" +resource "aws_vpc_peering_connection" "test" { + vpc_id = aws_vpc.test.id + peer_vpc_id = aws_vpc.target.id + auto_accept = true tags = { Name = %[1]q } } -resource "aws_subnet" "test" { - cidr_block = "10.1.1.0/24" - vpc_id = aws_vpc.test.id - availability_zone = data.aws_availability_zones.available.names[0] +resource "aws_eip" "test" { + vpc = true tags = { Name = %[1]q } } -resource "aws_network_interface" "test" { - subnet_id = aws_subnet.test.id +resource "aws_nat_gateway" "test" { + allocation_id = aws_eip.test.id + subnet_id = aws_subnet.test.id tags = { Name = %[1]q } + + depends_on = [aws_internet_gateway.test] } -resource "aws_instance" "test" { - ami = data.aws_ami.amzn-ami-nat-instance.id - instance_type = data.aws_ec2_instance_type_offering.available.instance_type +data "aws_caller_identity" "current" {} - network_interface { - device_index = 0 - network_interface_id = aws_network_interface.test.id +resource "aws_lb" "test" { + load_balancer_type = "gateway" + name = %[1]q + + subnet_mapping { + subnet_id = aws_subnet.test.id + } +} + +resource "aws_vpc_endpoint_service" "test" { + acceptance_required = false + allowed_principals = [data.aws_caller_identity.current.arn] + gateway_load_balancer_arns = [aws_lb.test.arn] + + tags = { + Name = %[1]q } +} + +resource "aws_vpc_endpoint" "test" { + service_name = aws_vpc_endpoint_service.test.service_name + subnet_ids = [aws_subnet.test.id] + vpc_endpoint_type = aws_vpc_endpoint_service.test.service_type + vpc_id = aws_vpc.test.id tags = { Name = %[1]q @@ -2348,96 +3244,91 @@ resource "aws_route_table" "test" { resource "aws_route" "test" { route_table_id = aws_route_table.test.id destination_cidr_block = %[2]q - network_interface_id = aws_network_interface.test.id - # Wait for the ENI attachment. - depends_on = [aws_instance.test] + egress_only_gateway_id = (local.target_attr == "egress_only_gateway_id") ? local.target_value : null + gateway_id = (local.target_attr == "gateway_id") ? local.target_value : null + instance_id = (local.target_attr == "instance_id") ? local.target_value : null + local_gateway_id = (local.target_attr == "local_gateway_id") ? local.target_value : null + nat_gateway_id = (local.target_attr == "nat_gateway_id") ? local.target_value : null + network_interface_id = (local.target_attr == "network_interface_id") ? local.target_value : null + transit_gateway_id = (local.target_attr == "transit_gateway_id") ? local.target_value : null + vpc_endpoint_id = (local.target_attr == "vpc_endpoint_id") ? local.target_value : null + vpc_peering_connection_id = (local.target_attr == "vpc_peering_connection_id") ? local.target_value : null } -`, rName, destinationCidr)) +`, rName, destinationCidr, targetAttribute, targetValue)) } -func testAccAWSRouteConfigIpv4NetworkInterfaceTwoAttachments(rName, destinationCidr, targetResourceName string) string { +func testAccAWSRouteConfigIpv6FlexiTarget(rName, destinationCidr, targetAttribute, targetValue string) string { return composeConfig( - testAccLatestAmazonNatInstanceAmiConfig(), + testAccLatestAmazonLinuxHvmEbsAmiConfig(), testAccAvailableAZsNoOptInConfig(), testAccAvailableEc2InstanceTypeForAvailabilityZone("data.aws_availability_zones.available.names[0]", "t3.micro", "t2.micro"), fmt.Sprintf(` -resource "aws_vpc" "test" { - cidr_block = "10.1.0.0/16" - - tags = { - Name = %[1]q - } +locals { + target_attr = %[3]q + target_value = %[4]s.id } -resource "aws_subnet" "test" { - cidr_block = "10.1.1.0/24" - vpc_id = aws_vpc.test.id - availability_zone = data.aws_availability_zones.available.names[0] +resource "aws_vpc" "test" { + cidr_block = "10.1.0.0/16" + assign_generated_ipv6_cidr_block = true tags = { Name = %[1]q } } -resource "aws_network_interface" "test1" { - subnet_id = aws_subnet.test.id +resource "aws_vpn_gateway" "test" { + vpc_id = aws_vpc.test.id tags = { Name = %[1]q } } -resource "aws_network_interface" "test2" { - subnet_id = aws_subnet.test.id +resource "aws_internet_gateway" "test" { + vpc_id = aws_vpc.test.id tags = { Name = %[1]q } } -resource "aws_instance" "test" { - ami = data.aws_ami.amzn-ami-nat-instance.id - instance_type = data.aws_ec2_instance_type_offering.available.instance_type - - network_interface { - device_index = 0 - network_interface_id = aws_network_interface.test1.id - } - - network_interface { - device_index = 1 - network_interface_id = aws_network_interface.test2.id - } +resource "aws_subnet" "test" { + cidr_block = "10.1.1.0/24" + vpc_id = aws_vpc.test.id + availability_zone = data.aws_availability_zones.available.names[0] + ipv6_cidr_block = cidrsubnet(aws_vpc.test.ipv6_cidr_block, 8, 1) + + map_public_ip_on_launch = true tags = { Name = %[1]q } } -resource "aws_route_table" "test" { - vpc_id = aws_vpc.test.id +resource "aws_instance" "test" { + ami = data.aws_ami.amzn-ami-minimal-hvm-ebs.id + instance_type = data.aws_ec2_instance_type_offering.available.instance_type + subnet_id = aws_subnet.test.id + + ipv6_address_count = 1 tags = { Name = %[1]q } } -resource "aws_route" "test" { - route_table_id = aws_route_table.test.id - destination_cidr_block = %[2]q - network_interface_id = %[3]s.id +resource "aws_egress_only_internet_gateway" "test" { + vpc_id = aws_vpc.test.id - # Wait for the ENI attachment. - depends_on = [aws_instance.test] -} -`, rName, destinationCidr, targetResourceName)) + tags = { + Name = %[1]q + } } -func testAccAWSRouteConfigIpv4VpcPeeringConnection(rName, destinationCidr string) string { - return fmt.Sprintf(` -resource "aws_vpc" "test" { - cidr_block = "10.1.0.0/16" +resource "aws_network_interface" "test" { + subnet_id = aws_subnet.test.id tags = { Name = %[1]q @@ -2445,7 +3336,8 @@ resource "aws_vpc" "test" { } resource "aws_vpc" "target" { - cidr_block = "10.0.0.0/16" + cidr_block = "10.0.0.0/16" + assign_generated_ipv6_cidr_block = true tags = { Name = %[1]q @@ -2471,14 +3363,23 @@ resource "aws_route_table" "test" { } resource "aws_route" "test" { - route_table_id = aws_route_table.test.id - destination_cidr_block = %[2]q - vpc_peering_connection_id = aws_vpc_peering_connection.test.id + route_table_id = aws_route_table.test.id + destination_ipv6_cidr_block = %[2]q + + egress_only_gateway_id = (local.target_attr == "egress_only_gateway_id") ? local.target_value : null + gateway_id = (local.target_attr == "gateway_id") ? local.target_value : null + instance_id = (local.target_attr == "instance_id") ? local.target_value : null + local_gateway_id = (local.target_attr == "local_gateway_id") ? local.target_value : null + nat_gateway_id = (local.target_attr == "nat_gateway_id") ? local.target_value : null + network_interface_id = (local.target_attr == "network_interface_id") ? local.target_value : null + transit_gateway_id = (local.target_attr == "transit_gateway_id") ? local.target_value : null + vpc_endpoint_id = (local.target_attr == "vpc_endpoint_id") ? local.target_value : null + vpc_peering_connection_id = (local.target_attr == "vpc_peering_connection_id") ? local.target_value : null } -`, rName, destinationCidr) +`, rName, destinationCidr, targetAttribute, targetValue)) } -func testAccAWSRouteConfigIpv4NatGateway(rName, destinationCidr string) string { +func testAccAWSRouteConfigIpv4NoRoute(rName string) string { return fmt.Sprintf(` resource "aws_vpc" "test" { cidr_block = "10.1.0.0/16" @@ -2488,42 +3389,50 @@ resource "aws_vpc" "test" { } } -resource "aws_subnet" "test" { - cidr_block = "10.1.1.0/24" - vpc_id = aws_vpc.test.id - - map_public_ip_on_launch = true +resource "aws_route_table" "test" { + vpc_id = aws_vpc.test.id tags = { Name = %[1]q } } +`, rName) +} -resource "aws_internet_gateway" "test" { - vpc_id = aws_vpc.test.id - - tags = { - Name = %[1]q - } +func testAccAWSRouteConfigIpv4LocalRoute(rName string) string { + return composeConfig( + testAccAWSRouteConfigIpv4NoRoute(rName), + ` +resource "aws_route" "test" { + route_table_id = aws_route_table.test.id + destination_cidr_block = aws_vpc.test.cidr_block + gateway_id = "local" +} +`) } -resource "aws_eip" "test" { - vpc = true +func testAccAWSRouteConfigPrefixListInternetGateway(rName string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { + cidr_block = "10.1.0.0/16" tags = { Name = %[1]q } } -resource "aws_nat_gateway" "test" { - allocation_id = aws_eip.test.id - subnet_id = aws_subnet.test.id +resource "aws_internet_gateway" "test" { + vpc_id = aws_vpc.test.id tags = { Name = %[1]q } +} - depends_on = [aws_internet_gateway.test] +resource "aws_ec2_managed_prefix_list" "test" { + address_family = "IPv4" + max_entries = 1 + name = %[1]q } resource "aws_route_table" "test" { @@ -2535,14 +3444,14 @@ resource "aws_route_table" "test" { } resource "aws_route" "test" { - route_table_id = aws_route_table.test.id - destination_cidr_block = %[2]q - nat_gateway_id = aws_nat_gateway.test.id + route_table_id = aws_route_table.test.id + destination_prefix_list_id = aws_ec2_managed_prefix_list.test.id + gateway_id = aws_internet_gateway.test.id } -`, rName, destinationCidr) +`, rName) } -func testAccAWSRouteConfigIpv4VpnGateway(rName, destinationCidr string) string { +func testAccAWSRouteConfigPrefixListVpnGateway(rName string) string { return fmt.Sprintf(` resource "aws_vpc" "test" { cidr_block = "10.1.0.0/16" @@ -2560,6 +3469,12 @@ resource "aws_vpn_gateway" "test" { } } +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 @@ -2569,32 +3484,53 @@ resource "aws_route_table" "test" { } resource "aws_route" "test" { - route_table_id = aws_route_table.test.id - destination_cidr_block = %[2]q - gateway_id = aws_vpn_gateway.test.id + route_table_id = aws_route_table.test.id + destination_prefix_list_id = aws_ec2_managed_prefix_list.test.id + gateway_id = aws_vpn_gateway.test.id } -`, rName, destinationCidr) +`, rName) } -func testAccAWSRouteConfigIpv6VpnGateway(rName, destinationCidr string) string { - return fmt.Sprintf(` +func testAccAWSRouteConfigPrefixListInstance(rName string) string { + return composeConfig( + testAccLatestAmazonNatInstanceAmiConfig(), + testAccAvailableAZsNoOptInConfig(), + testAccAvailableEc2InstanceTypeForAvailabilityZone("data.aws_availability_zones.available.names[0]", "t3.micro", "t2.micro"), + fmt.Sprintf(` resource "aws_vpc" "test" { - cidr_block = "10.1.0.0/16" - assign_generated_ipv6_cidr_block = true + cidr_block = "10.1.0.0/16" tags = { Name = %[1]q } } -resource "aws_vpn_gateway" "test" { - vpc_id = aws_vpc.test.id +resource "aws_subnet" "test" { + cidr_block = "10.1.1.0/24" + vpc_id = aws_vpc.test.id + availability_zone = data.aws_availability_zones.available.names[0] + + tags = { + Name = %[1]q + } +} + +resource "aws_instance" "test" { + ami = data.aws_ami.amzn-ami-nat-instance.id + instance_type = data.aws_ec2_instance_type_offering.available.instance_type + subnet_id = aws_subnet.test.id 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 @@ -2604,21 +3540,19 @@ resource "aws_route_table" "test" { } resource "aws_route" "test" { - route_table_id = aws_route_table.test.id - destination_ipv6_cidr_block = %[2]q - gateway_id = aws_vpn_gateway.test.id + route_table_id = aws_route_table.test.id + destination_prefix_list_id = aws_ec2_managed_prefix_list.test.id + instance_id = aws_instance.test.id } -`, rName, destinationCidr) +`, rName)) } -func testAccAWSRouteResourceConfigIpv4VpcEndpoint(rName, destinationCidr string) string { +func testAccAWSRouteConfigPrefixListNetworkInterfaceUnattached(rName string) string { return composeConfig( testAccAvailableAZsNoOptInConfig(), fmt.Sprintf(` -data "aws_caller_identity" "current" {} - resource "aws_vpc" "test" { - cidr_block = "10.10.10.0/25" + cidr_block = "10.1.0.0/16" tags = { Name = %[1]q @@ -2626,43 +3560,27 @@ resource "aws_vpc" "test" { } resource "aws_subnet" "test" { - availability_zone = data.aws_availability_zones.available.names[0] - cidr_block = cidrsubnet(aws_vpc.test.cidr_block, 2, 0) + cidr_block = "10.1.1.0/24" vpc_id = aws_vpc.test.id + availability_zone = data.aws_availability_zones.available.names[0] tags = { Name = %[1]q } } -resource "aws_lb" "test" { - load_balancer_type = "gateway" - name = %[1]q - - subnet_mapping { - subnet_id = aws_subnet.test.id - } -} - -resource "aws_vpc_endpoint_service" "test" { - acceptance_required = false - allowed_principals = [data.aws_caller_identity.current.arn] - gateway_load_balancer_arns = [aws_lb.test.arn] +resource "aws_network_interface" "test" { + subnet_id = aws_subnet.test.id tags = { Name = %[1]q } } -resource "aws_vpc_endpoint" "test" { - service_name = aws_vpc_endpoint_service.test.service_name - subnet_ids = [aws_subnet.test.id] - vpc_endpoint_type = aws_vpc_endpoint_service.test.service_type - 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" { @@ -2674,24 +3592,19 @@ resource "aws_route_table" "test" { } resource "aws_route" "test" { - route_table_id = aws_route_table.test.id - destination_cidr_block = %[2]q - vpc_endpoint_id = aws_vpc_endpoint.test.id + route_table_id = aws_route_table.test.id + destination_prefix_list_id = aws_ec2_managed_prefix_list.test.id + network_interface_id = aws_network_interface.test.id } -`, rName, destinationCidr)) +`, rName)) } -func testAccAWSRouteConfigIpv4FlexiTarget(rName, destinationCidr, targetAttribute, targetValue string) string { +func testAccAWSRouteConfigPrefixListNetworkInterfaceAttached(rName string) string { return composeConfig( - testAccLatestAmazonLinuxHvmEbsAmiConfig(), - testAccAvailableAZsNoOptInDefaultExcludeConfig(), + testAccLatestAmazonNatInstanceAmiConfig(), + testAccAvailableAZsNoOptInConfig(), testAccAvailableEc2InstanceTypeForAvailabilityZone("data.aws_availability_zones.available.names[0]", "t3.micro", "t2.micro"), fmt.Sprintf(` -locals { - target_attr = %[3]q - target_value = %[4]s.id -} - resource "aws_vpc" "test" { cidr_block = "10.1.0.0/16" @@ -2700,15 +3613,45 @@ resource "aws_vpc" "test" { } } -resource "aws_vpn_gateway" "test" { - vpc_id = aws_vpc.test.id +resource "aws_subnet" "test" { + cidr_block = "10.1.1.0/24" + vpc_id = aws_vpc.test.id + availability_zone = data.aws_availability_zones.available.names[0] tags = { Name = %[1]q } } -resource "aws_internet_gateway" "test" { +resource "aws_network_interface" "test" { + subnet_id = aws_subnet.test.id + + tags = { + Name = %[1]q + } +} + +resource "aws_instance" "test" { + ami = data.aws_ami.amzn-ami-nat-instance.id + instance_type = data.aws_ec2_instance_type_offering.available.instance_type + + network_interface { + device_index = 0 + network_interface_id = aws_network_interface.test.id + } + + tags = { + Name = %[1]q + } +} + +resource "aws_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 tags = { @@ -2716,64 +3659,90 @@ resource "aws_internet_gateway" "test" { } } -resource "aws_subnet" "test" { - cidr_block = "10.1.1.0/24" - vpc_id = aws_vpc.test.id - availability_zone = data.aws_availability_zones.available.names[0] +resource "aws_route" "test" { + route_table_id = aws_route_table.test.id + destination_prefix_list_id = aws_ec2_managed_prefix_list.test.id + network_interface_id = aws_network_interface.test.id + + # Wait for the ENI attachment. + depends_on = [aws_instance.test] +} +`, rName)) +} - map_public_ip_on_launch = true +func testAccAWSRouteConfigPrefixListVpcPeeringConnection(rName string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { + cidr_block = "10.1.0.0/16" tags = { Name = %[1]q } } -resource "aws_instance" "test" { - ami = data.aws_ami.amzn-ami-minimal-hvm-ebs.id - instance_type = data.aws_ec2_instance_type_offering.available.instance_type - subnet_id = aws_subnet.test.id +resource "aws_vpc" "target" { + cidr_block = "10.0.0.0/16" tags = { Name = %[1]q } } -resource "aws_ec2_transit_gateway" "test" { +resource "aws_vpc_peering_connection" "test" { + vpc_id = aws_vpc.test.id + peer_vpc_id = aws_vpc.target.id + auto_accept = true + tags = { Name = %[1]q } } -resource "aws_ec2_transit_gateway_vpc_attachment" "test" { - subnet_ids = [aws_subnet.test.id] - transit_gateway_id = aws_ec2_transit_gateway.test.id - vpc_id = aws_vpc.test.id +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 tags = { Name = %[1]q } } -resource "aws_network_interface" "test" { - subnet_id = aws_subnet.test.id +resource "aws_route" "test" { + route_table_id = aws_route_table.test.id + destination_prefix_list_id = aws_ec2_managed_prefix_list.test.id + vpc_peering_connection_id = aws_vpc_peering_connection.test.id +} +`, rName) +} + +func testAccAWSRouteConfigPrefixListNatGateway(rName string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { + cidr_block = "10.1.0.0/16" tags = { Name = %[1]q } } -resource "aws_vpc" "target" { - cidr_block = "10.0.0.0/16" +resource "aws_subnet" "test" { + cidr_block = "10.1.1.0/24" + vpc_id = aws_vpc.test.id + + map_public_ip_on_launch = true tags = { Name = %[1]q } } -resource "aws_vpc_peering_connection" "test" { - vpc_id = aws_vpc.test.id - peer_vpc_id = aws_vpc.target.id - auto_accept = true +resource "aws_internet_gateway" "test" { + vpc_id = aws_vpc.test.id tags = { Name = %[1]q @@ -2799,31 +3768,43 @@ resource "aws_nat_gateway" "test" { depends_on = [aws_internet_gateway.test] } -data "aws_caller_identity" "current" {} +resource "aws_ec2_managed_prefix_list" "test" { + address_family = "IPv4" + max_entries = 1 + name = %[1]q +} -resource "aws_lb" "test" { - load_balancer_type = "gateway" - name = %[1]q +resource "aws_route_table" "test" { + vpc_id = aws_vpc.test.id - subnet_mapping { - subnet_id = aws_subnet.test.id + tags = { + Name = %[1]q } } -resource "aws_vpc_endpoint_service" "test" { - acceptance_required = false - allowed_principals = [data.aws_caller_identity.current.arn] - gateway_load_balancer_arns = [aws_lb.test.arn] +resource "aws_route" "test" { + route_table_id = aws_route_table.test.id + destination_prefix_list_id = aws_ec2_managed_prefix_list.test.id + nat_gateway_id = aws_nat_gateway.test.id +} +`, rName) +} + +func testAccAWSRouteConfigPrefixListTransitGateway(rName string) string { + return composeConfig( + testAccAvailableAZsNoOptInDefaultExcludeConfig(), + fmt.Sprintf(` +resource "aws_vpc" "test" { + cidr_block = "10.1.0.0/16" tags = { Name = %[1]q } } -resource "aws_vpc_endpoint" "test" { - service_name = aws_vpc_endpoint_service.test.service_name - subnet_ids = [aws_subnet.test.id] - vpc_endpoint_type = aws_vpc_endpoint_service.test.service_type +resource "aws_subnet" "test" { + availability_zone = data.aws_availability_zones.available.names[0] + cidr_block = "10.1.1.0/24" vpc_id = aws_vpc.test.id tags = { @@ -2831,61 +3812,55 @@ resource "aws_vpc_endpoint" "test" { } } -resource "aws_route_table" "test" { - vpc_id = aws_vpc.test.id - +resource "aws_ec2_transit_gateway" "test" { tags = { Name = %[1]q } } -resource "aws_route" "test" { - route_table_id = aws_route_table.test.id - destination_cidr_block = %[2]q +resource "aws_ec2_transit_gateway_vpc_attachment" "test" { + subnet_ids = [aws_subnet.test.id] + transit_gateway_id = aws_ec2_transit_gateway.test.id + vpc_id = aws_vpc.test.id - carrier_gateway_id = (local.target_attr == "carrier_gateway_id") ? local.target_value : null - egress_only_gateway_id = (local.target_attr == "egress_only_gateway_id") ? local.target_value : null - gateway_id = (local.target_attr == "gateway_id") ? local.target_value : null - instance_id = (local.target_attr == "instance_id") ? local.target_value : null - local_gateway_id = (local.target_attr == "local_gateway_id") ? local.target_value : null - nat_gateway_id = (local.target_attr == "nat_gateway_id") ? local.target_value : null - network_interface_id = (local.target_attr == "network_interface_id") ? local.target_value : null - transit_gateway_id = (local.target_attr == "transit_gateway_id") ? local.target_value : null - vpc_endpoint_id = (local.target_attr == "vpc_endpoint_id") ? local.target_value : null - vpc_peering_connection_id = (local.target_attr == "vpc_peering_connection_id") ? local.target_value : null -} -`, rName, destinationCidr, targetAttribute, targetValue)) + tags = { + Name = %[1]q + } } -func testAccAWSRouteConfigIpv6FlexiTarget(rName, destinationCidr, targetAttribute, targetValue string) string { - return composeConfig( - testAccLatestAmazonLinuxHvmEbsAmiConfig(), - testAccAvailableAZsNoOptInConfig(), - testAccAvailableEc2InstanceTypeForAvailabilityZone("data.aws_availability_zones.available.names[0]", "t3.micro", "t2.micro"), - fmt.Sprintf(` -locals { - target_attr = %[3]q - target_value = %[4]s.id +resource "aws_ec2_managed_prefix_list" "test" { + address_family = "IPv4" + max_entries = 1 + name = %[1]q } -resource "aws_vpc" "test" { - cidr_block = "10.1.0.0/16" - assign_generated_ipv6_cidr_block = true +resource "aws_route_table" "test" { + vpc_id = aws_vpc.test.id tags = { Name = %[1]q } } -resource "aws_vpn_gateway" "test" { - vpc_id = aws_vpc.test.id +resource "aws_route" "test" { + route_table_id = aws_route_table.test.id + destination_prefix_list_id = aws_ec2_managed_prefix_list.test.id + transit_gateway_id = aws_ec2_transit_gateway_vpc_attachment.test.transit_gateway_id +} +`, rName)) +} + +func testAccAWSRouteConfigPrefixListCarrierGateway(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" { +resource "aws_ec2_carrier_gateway" "test" { vpc_id = aws_vpc.test.id tags = { @@ -2893,64 +3868,63 @@ resource "aws_internet_gateway" "test" { } } -resource "aws_subnet" "test" { - cidr_block = "10.1.1.0/24" - vpc_id = aws_vpc.test.id - availability_zone = data.aws_availability_zones.available.names[0] - ipv6_cidr_block = cidrsubnet(aws_vpc.test.ipv6_cidr_block, 8, 1) +resource "aws_ec2_managed_prefix_list" "test" { + address_family = "IPv4" + max_entries = 1 + name = %[1]q +} - map_public_ip_on_launch = true +resource "aws_route_table" "test" { + vpc_id = aws_vpc.test.id tags = { Name = %[1]q } } -resource "aws_instance" "test" { - ami = data.aws_ami.amzn-ami-minimal-hvm-ebs.id - instance_type = data.aws_ec2_instance_type_offering.available.instance_type - subnet_id = aws_subnet.test.id +resource "aws_route" "test" { + route_table_id = aws_route_table.test.id + destination_prefix_list_id = aws_ec2_managed_prefix_list.test.id + carrier_gateway_id = aws_ec2_carrier_gateway.test.id +} +`, rName) +} - ipv6_address_count = 1 +func testAccAWSRouteConfigPrefixListLocalGateway(rName string) string { + return fmt.Sprintf(` +data "aws_ec2_local_gateways" "all" {} - tags = { - Name = %[1]q - } +data "aws_ec2_local_gateway" "first" { + id = tolist(data.aws_ec2_local_gateways.all.ids)[0] } -resource "aws_egress_only_internet_gateway" "test" { - vpc_id = aws_vpc.test.id +data "aws_ec2_local_gateway_route_tables" "all" {} - tags = { - Name = %[1]q - } +data "aws_ec2_local_gateway_route_table" "first" { + local_gateway_route_table_id = tolist(data.aws_ec2_local_gateway_route_tables.all.ids)[0] } -resource "aws_network_interface" "test" { - subnet_id = aws_subnet.test.id +resource "aws_vpc" "test" { + cidr_block = "10.0.0.0/16" tags = { Name = %[1]q } } -resource "aws_vpc" "target" { - cidr_block = "10.0.0.0/16" - assign_generated_ipv6_cidr_block = true +resource "aws_ec2_local_gateway_route_table_vpc_association" "example" { + local_gateway_route_table_id = data.aws_ec2_local_gateway_route_table.first.id + vpc_id = aws_vpc.test.id tags = { Name = %[1]q } } -resource "aws_vpc_peering_connection" "test" { - vpc_id = aws_vpc.test.id - peer_vpc_id = aws_vpc.target.id - auto_accept = true - - tags = { - Name = %[1]q - } +resource "aws_ec2_managed_prefix_list" "test" { + address_family = "IPv4" + max_entries = 1 + name = %[1]q } resource "aws_route_table" "test" { @@ -2959,56 +3933,57 @@ resource "aws_route_table" "test" { tags = { Name = %[1]q } + + depends_on = [aws_ec2_local_gateway_route_table_vpc_association.example] } resource "aws_route" "test" { - route_table_id = aws_route_table.test.id - destination_ipv6_cidr_block = %[2]q - - carrier_gateway_id = (local.target_attr == "carrier_gateway_id") ? local.target_value : null - egress_only_gateway_id = (local.target_attr == "egress_only_gateway_id") ? local.target_value : null - gateway_id = (local.target_attr == "gateway_id") ? local.target_value : null - instance_id = (local.target_attr == "instance_id") ? local.target_value : null - local_gateway_id = (local.target_attr == "local_gateway_id") ? local.target_value : null - nat_gateway_id = (local.target_attr == "nat_gateway_id") ? local.target_value : null - network_interface_id = (local.target_attr == "network_interface_id") ? local.target_value : null - transit_gateway_id = (local.target_attr == "transit_gateway_id") ? local.target_value : null - vpc_endpoint_id = (local.target_attr == "vpc_endpoint_id") ? local.target_value : null - vpc_peering_connection_id = (local.target_attr == "vpc_peering_connection_id") ? local.target_value : null + route_table_id = aws_route_table.test.id + destination_prefix_list_id = aws_ec2_managed_prefix_list.test.id + local_gateway_id = data.aws_ec2_local_gateway.first.id } -`, rName, destinationCidr, targetAttribute, targetValue)) +`, rName) } -func testAccAWSRouteConfigIpv4NoRoute(rName string) string { +func testAccAWSRouteConfigPrefixListEgressOnlyInternetGateway(rName string) string { return fmt.Sprintf(` resource "aws_vpc" "test" { - cidr_block = "10.1.0.0/16" + cidr_block = "10.1.0.0/16" + assign_generated_ipv6_cidr_block = true tags = { Name = %[1]q } } -resource "aws_route_table" "test" { +resource "aws_egress_only_internet_gateway" "test" { vpc_id = aws_vpc.test.id tags = { Name = %[1]q } } -`, rName) + +resource "aws_ec2_managed_prefix_list" "test" { + address_family = "IPv6" + max_entries = 1 + name = %[1]q +} + +resource "aws_route_table" "test" { + vpc_id = aws_vpc.test.id + + tags = { + Name = %[1]q + } } -func testAccAWSRouteConfigIpv4LocalRoute(rName string) string { - return composeConfig( - testAccAWSRouteConfigIpv4NoRoute(rName), - ` resource "aws_route" "test" { - route_table_id = aws_route_table.test.id - destination_cidr_block = aws_vpc.test.cidr_block - gateway_id = "local" + route_table_id = aws_route_table.test.id + destination_prefix_list_id = aws_ec2_managed_prefix_list.test.id + egress_only_gateway_id = aws_egress_only_internet_gateway.test.id } -`) +`, rName) } func testAccAWSRouteConfigIpv4CarrierGateway(rName, destinationCidr string) string { From 204962d39362e4c3f323ec7943d4dd4fd7b320f1 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 26 Jan 2021 15:19:35 -0500 Subject: [PATCH 4/9] Add CHANGELOG entry. --- .changelog/17291.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/17291.txt diff --git a/.changelog/17291.txt b/.changelog/17291.txt new file mode 100644 index 00000000000..f7a68aecd72 --- /dev/null +++ b/.changelog/17291.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +resource/aws_route: `destination_prefix_list_id` attribute can be specified for managed prefix list destinations +``` From 86fab31beecede0cf64654c7fee676c0159a06a2 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Thu, 28 Jan 2021 09:32:13 -0500 Subject: [PATCH 5/9] r/aws_route: Don't check prefix list owner on import. --- aws/internal/service/ec2/id.go | 4 ---- aws/resource_aws_route.go | 10 ---------- 2 files changed, 14 deletions(-) diff --git a/aws/internal/service/ec2/id.go b/aws/internal/service/ec2/id.go index dc0207beca2..c7fa5040e0f 100644 --- a/aws/internal/service/ec2/id.go +++ b/aws/internal/service/ec2/id.go @@ -7,10 +7,6 @@ import ( "github.com/terraform-providers/terraform-provider-aws/aws/internal/hashcode" ) -const ( - ManagedPrefixListOwnerIdAWS = "AWS" -) - const clientVpnAuthorizationRuleIDSeparator = "," func ClientVpnAuthorizationRuleCreateID(endpointID, targetNetworkCidr, accessGroupID string) string { diff --git a/aws/resource_aws_route.go b/aws/resource_aws_route.go index c036fe20163..ebab5fcc56e 100644 --- a/aws/resource_aws_route.go +++ b/aws/resource_aws_route.go @@ -506,16 +506,6 @@ func resourceAwsRouteImport(d *schema.ResourceData, meta interface{}) ([]*schema } else if strings.Contains(destination, ".") { d.Set("destination_cidr_block", destination) } else { - managedPrefixList, err := finder.ManagedPrefixListByID(meta.(*AWSClient).ec2conn, destination) - - if err != nil { - return nil, err - } - - if managedPrefixList != nil && aws.StringValue(managedPrefixList.OwnerId) == tfec2.ManagedPrefixListOwnerIdAWS { - return nil, fmt.Errorf("Managed prefix list (%s) is owned by AWS", destination) - } - d.Set("destination_prefix_list_id", destination) } From 7947cbc14ce8b05c36327ec8ac0969aa8891f413 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Thu, 28 Jan 2021 09:52:59 -0500 Subject: [PATCH 6/9] r/aws_route: Add acceptance test pre-checks. Acceptance test output: $ make testacc TEST=./aws/ TESTARGS='-run=TestAccAWSRoute_PrefixList_' ACCTEST_PARALLELISM=2 ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws -v -count 1 -parallel 2 -run=TestAccAWSRoute_PrefixList_ -timeout 120m === RUN TestAccAWSRoute_PrefixList_To_InternetGateway === PAUSE TestAccAWSRoute_PrefixList_To_InternetGateway === RUN TestAccAWSRoute_PrefixList_To_VpnGateway === PAUSE TestAccAWSRoute_PrefixList_To_VpnGateway === RUN TestAccAWSRoute_PrefixList_To_Instance === PAUSE TestAccAWSRoute_PrefixList_To_Instance === RUN TestAccAWSRoute_PrefixList_To_NetworkInterface_Unattached === PAUSE TestAccAWSRoute_PrefixList_To_NetworkInterface_Unattached === RUN TestAccAWSRoute_PrefixList_To_NetworkInterface_Attached === PAUSE TestAccAWSRoute_PrefixList_To_NetworkInterface_Attached === RUN TestAccAWSRoute_PrefixList_To_VpcPeeringConnection === PAUSE TestAccAWSRoute_PrefixList_To_VpcPeeringConnection === RUN TestAccAWSRoute_PrefixList_To_NatGateway === PAUSE TestAccAWSRoute_PrefixList_To_NatGateway === RUN TestAccAWSRoute_PrefixList_To_TransitGateway === PAUSE TestAccAWSRoute_PrefixList_To_TransitGateway === RUN TestAccAWSRoute_PrefixList_To_CarrierGateway === PAUSE TestAccAWSRoute_PrefixList_To_CarrierGateway === RUN TestAccAWSRoute_PrefixList_To_LocalGateway === PAUSE TestAccAWSRoute_PrefixList_To_LocalGateway === RUN TestAccAWSRoute_PrefixList_To_EgressOnlyInternetGateway === PAUSE TestAccAWSRoute_PrefixList_To_EgressOnlyInternetGateway === CONT TestAccAWSRoute_PrefixList_To_InternetGateway === CONT TestAccAWSRoute_PrefixList_To_NatGateway --- PASS: TestAccAWSRoute_PrefixList_To_InternetGateway (36.30s) === CONT TestAccAWSRoute_PrefixList_To_EgressOnlyInternetGateway --- PASS: TestAccAWSRoute_PrefixList_To_EgressOnlyInternetGateway (32.35s) === CONT TestAccAWSRoute_PrefixList_To_LocalGateway data_source_aws_outposts_outposts_test.go:66: skipping since no Outposts found --- SKIP: TestAccAWSRoute_PrefixList_To_LocalGateway (1.19s) === CONT TestAccAWSRoute_PrefixList_To_CarrierGateway --- PASS: TestAccAWSRoute_PrefixList_To_CarrierGateway (32.74s) === CONT TestAccAWSRoute_PrefixList_To_TransitGateway --- PASS: TestAccAWSRoute_PrefixList_To_NatGateway (179.80s) === CONT TestAccAWSRoute_PrefixList_To_NetworkInterface_Unattached --- PASS: TestAccAWSRoute_PrefixList_To_NetworkInterface_Unattached (66.06s) === CONT TestAccAWSRoute_PrefixList_To_VpcPeeringConnection --- PASS: TestAccAWSRoute_PrefixList_To_VpcPeeringConnection (33.19s) === CONT TestAccAWSRoute_PrefixList_To_NetworkInterface_Attached --- PASS: TestAccAWSRoute_PrefixList_To_TransitGateway (368.36s) === CONT TestAccAWSRoute_PrefixList_To_Instance --- PASS: TestAccAWSRoute_PrefixList_To_NetworkInterface_Attached (351.56s) === CONT TestAccAWSRoute_PrefixList_To_VpnGateway --- PASS: TestAccAWSRoute_PrefixList_To_VpnGateway (50.39s) --- PASS: TestAccAWSRoute_PrefixList_To_Instance (328.36s) PASS ok github.com/terraform-providers/terraform-provider-aws/aws 799.400s --- aws/resource_aws_route_test.go | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/aws/resource_aws_route_test.go b/aws/resource_aws_route_test.go index 21964132822..493b1a4216f 100644 --- a/aws/resource_aws_route_test.go +++ b/aws/resource_aws_route_test.go @@ -1481,7 +1481,7 @@ func TestAccAWSRoute_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) }, Providers: testAccProviders, CheckDestroy: testAccCheckAWSRouteDestroy, Steps: []resource.TestStep{ @@ -1525,7 +1525,7 @@ func TestAccAWSRoute_PrefixList_To_VpnGateway(t *testing.T) { rName := acctest.RandomWithPrefix("tf-acc-test") resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, + PreCheck: func() { testAccPreCheck(t); testAccPreCheckEc2ManagedPrefixList(t) }, Providers: testAccProviders, CheckDestroy: testAccCheckAWSRouteDestroy, Steps: []resource.TestStep{ @@ -1569,7 +1569,7 @@ func TestAccAWSRoute_PrefixList_To_Instance(t *testing.T) { rName := acctest.RandomWithPrefix("tf-acc-test") resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, + PreCheck: func() { testAccPreCheck(t); testAccPreCheckEc2ManagedPrefixList(t) }, Providers: testAccProviders, CheckDestroy: testAccCheckAWSRouteDestroy, Steps: []resource.TestStep{ @@ -1613,7 +1613,7 @@ func TestAccAWSRoute_PrefixList_To_NetworkInterface_Unattached(t *testing.T) { rName := acctest.RandomWithPrefix("tf-acc-test") resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, + PreCheck: func() { testAccPreCheck(t); testAccPreCheckEc2ManagedPrefixList(t) }, Providers: testAccProviders, CheckDestroy: testAccCheckAWSRouteDestroy, Steps: []resource.TestStep{ @@ -1658,7 +1658,7 @@ func TestAccAWSRoute_PrefixList_To_NetworkInterface_Attached(t *testing.T) { rName := acctest.RandomWithPrefix("tf-acc-test") resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, + PreCheck: func() { testAccPreCheck(t); testAccPreCheckEc2ManagedPrefixList(t) }, Providers: testAccProviders, CheckDestroy: testAccCheckAWSRouteDestroy, Steps: []resource.TestStep{ @@ -1702,7 +1702,7 @@ func TestAccAWSRoute_PrefixList_To_VpcPeeringConnection(t *testing.T) { rName := acctest.RandomWithPrefix("tf-acc-test") resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, + PreCheck: func() { testAccPreCheck(t); testAccPreCheckEc2ManagedPrefixList(t) }, Providers: testAccProviders, CheckDestroy: testAccCheckAWSRouteDestroy, Steps: []resource.TestStep{ @@ -1746,7 +1746,7 @@ func TestAccAWSRoute_PrefixList_To_NatGateway(t *testing.T) { rName := acctest.RandomWithPrefix("tf-acc-test") resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, + PreCheck: func() { testAccPreCheck(t); testAccPreCheckEc2ManagedPrefixList(t) }, Providers: testAccProviders, CheckDestroy: testAccCheckAWSRouteDestroy, Steps: []resource.TestStep{ @@ -1790,7 +1790,7 @@ func TestAccAWSRoute_PrefixList_To_TransitGateway(t *testing.T) { rName := acctest.RandomWithPrefix("tf-acc-test") resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, + PreCheck: func() { testAccPreCheck(t); testAccPreCheckEc2ManagedPrefixList(t) }, Providers: testAccProviders, CheckDestroy: testAccCheckAWSRouteDestroy, Steps: []resource.TestStep{ @@ -1834,7 +1834,11 @@ func TestAccAWSRoute_PrefixList_To_CarrierGateway(t *testing.T) { rName := acctest.RandomWithPrefix("tf-acc-test") resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSWavelengthZoneAvailable(t) }, + PreCheck: func() { + testAccPreCheck(t) + testAccPreCheckEc2ManagedPrefixList(t) + testAccPreCheckAWSWavelengthZoneAvailable(t) + }, Providers: testAccProviders, CheckDestroy: testAccCheckAWSRouteDestroy, Steps: []resource.TestStep{ @@ -1878,7 +1882,11 @@ func TestAccAWSRoute_PrefixList_To_LocalGateway(t *testing.T) { rName := acctest.RandomWithPrefix("tf-acc-test") resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSOutpostsOutposts(t) }, + PreCheck: func() { + testAccPreCheck(t) + testAccPreCheckEc2ManagedPrefixList(t) + testAccPreCheckAWSOutpostsOutposts(t) + }, Providers: testAccProviders, CheckDestroy: testAccCheckAWSRouteDestroy, Steps: []resource.TestStep{ @@ -1922,7 +1930,7 @@ func TestAccAWSRoute_PrefixList_To_EgressOnlyInternetGateway(t *testing.T) { rName := acctest.RandomWithPrefix("tf-acc-test") resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, + PreCheck: func() { testAccPreCheck(t); testAccPreCheckEc2ManagedPrefixList(t) }, Providers: testAccProviders, CheckDestroy: testAccCheckAWSRouteDestroy, Steps: []resource.TestStep{ From 5caf2e99f28dd99bb81724f256f485c1325d56a4 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 26 Mar 2021 16:18:42 -0400 Subject: [PATCH 7/9] r/aws_route: Add 'ErrorCheck' to new acceptance tests. Acceptance test output: $ make testacc TEST=./aws/ TESTARGS='-run=TestAccAWSRoute_' ACCTEST_PARALLELISM=2 ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws -v -count 1 -parallel 2 -run=TestAccAWSRoute_ -timeout 180m === RUN TestAccAWSRoute_basic === PAUSE TestAccAWSRoute_basic === RUN TestAccAWSRoute_disappears === PAUSE TestAccAWSRoute_disappears === RUN TestAccAWSRoute_disappears_RouteTable === PAUSE TestAccAWSRoute_disappears_RouteTable === RUN TestAccAWSRoute_IPv6_To_EgressOnlyInternetGateway === PAUSE TestAccAWSRoute_IPv6_To_EgressOnlyInternetGateway === RUN TestAccAWSRoute_IPv6_To_InternetGateway === PAUSE TestAccAWSRoute_IPv6_To_InternetGateway === RUN TestAccAWSRoute_IPv6_To_Instance === PAUSE TestAccAWSRoute_IPv6_To_Instance === RUN TestAccAWSRoute_IPv6_To_NetworkInterface_Unattached === PAUSE TestAccAWSRoute_IPv6_To_NetworkInterface_Unattached === RUN TestAccAWSRoute_IPv6_To_VpcPeeringConnection === PAUSE TestAccAWSRoute_IPv6_To_VpcPeeringConnection === RUN TestAccAWSRoute_IPv6_To_VpnGateway === PAUSE TestAccAWSRoute_IPv6_To_VpnGateway === RUN TestAccAWSRoute_IPv4_To_VpnGateway === PAUSE TestAccAWSRoute_IPv4_To_VpnGateway === RUN TestAccAWSRoute_IPv4_To_Instance === PAUSE TestAccAWSRoute_IPv4_To_Instance === RUN TestAccAWSRoute_IPv4_To_NetworkInterface_Unattached === PAUSE TestAccAWSRoute_IPv4_To_NetworkInterface_Unattached === RUN TestAccAWSRoute_IPv4_To_NetworkInterface_Attached === PAUSE TestAccAWSRoute_IPv4_To_NetworkInterface_Attached === RUN TestAccAWSRoute_IPv4_To_NetworkInterface_TwoAttachments === PAUSE TestAccAWSRoute_IPv4_To_NetworkInterface_TwoAttachments === RUN TestAccAWSRoute_IPv4_To_VpcPeeringConnection === PAUSE TestAccAWSRoute_IPv4_To_VpcPeeringConnection === RUN TestAccAWSRoute_IPv4_To_NatGateway === PAUSE TestAccAWSRoute_IPv4_To_NatGateway === RUN TestAccAWSRoute_DoesNotCrashWithVpcEndpoint === PAUSE TestAccAWSRoute_DoesNotCrashWithVpcEndpoint === RUN TestAccAWSRoute_IPv4_To_TransitGateway === PAUSE TestAccAWSRoute_IPv4_To_TransitGateway === RUN TestAccAWSRoute_IPv6_To_TransitGateway === PAUSE TestAccAWSRoute_IPv6_To_TransitGateway === RUN TestAccAWSRoute_IPv4_To_CarrierGateway === PAUSE TestAccAWSRoute_IPv4_To_CarrierGateway === RUN TestAccAWSRoute_IPv4_To_LocalGateway === PAUSE TestAccAWSRoute_IPv4_To_LocalGateway === RUN TestAccAWSRoute_IPv6_To_LocalGateway === PAUSE TestAccAWSRoute_IPv6_To_LocalGateway === RUN TestAccAWSRoute_ConditionalCidrBlock === PAUSE TestAccAWSRoute_ConditionalCidrBlock === RUN TestAccAWSRoute_IPv4_Update_Target === PAUSE TestAccAWSRoute_IPv4_Update_Target === RUN TestAccAWSRoute_IPv6_Update_Target === PAUSE TestAccAWSRoute_IPv6_Update_Target === RUN TestAccAWSRoute_IPv4_To_VpcEndpoint === PAUSE TestAccAWSRoute_IPv4_To_VpcEndpoint === RUN TestAccAWSRoute_LocalRoute === PAUSE TestAccAWSRoute_LocalRoute === RUN TestAccAWSRoute_PrefixList_To_InternetGateway === PAUSE TestAccAWSRoute_PrefixList_To_InternetGateway === RUN TestAccAWSRoute_PrefixList_To_VpnGateway === PAUSE TestAccAWSRoute_PrefixList_To_VpnGateway === RUN TestAccAWSRoute_PrefixList_To_Instance === PAUSE TestAccAWSRoute_PrefixList_To_Instance === RUN TestAccAWSRoute_PrefixList_To_NetworkInterface_Unattached === PAUSE TestAccAWSRoute_PrefixList_To_NetworkInterface_Unattached === RUN TestAccAWSRoute_PrefixList_To_NetworkInterface_Attached === PAUSE TestAccAWSRoute_PrefixList_To_NetworkInterface_Attached === RUN TestAccAWSRoute_PrefixList_To_VpcPeeringConnection === PAUSE TestAccAWSRoute_PrefixList_To_VpcPeeringConnection === RUN TestAccAWSRoute_PrefixList_To_NatGateway === PAUSE TestAccAWSRoute_PrefixList_To_NatGateway === RUN TestAccAWSRoute_PrefixList_To_TransitGateway === PAUSE TestAccAWSRoute_PrefixList_To_TransitGateway === RUN TestAccAWSRoute_PrefixList_To_CarrierGateway === PAUSE TestAccAWSRoute_PrefixList_To_CarrierGateway === RUN TestAccAWSRoute_PrefixList_To_LocalGateway === PAUSE TestAccAWSRoute_PrefixList_To_LocalGateway === RUN TestAccAWSRoute_PrefixList_To_EgressOnlyInternetGateway === PAUSE TestAccAWSRoute_PrefixList_To_EgressOnlyInternetGateway === CONT TestAccAWSRoute_basic === CONT TestAccAWSRoute_disappears_RouteTable --- PASS: TestAccAWSRoute_disappears_RouteTable (34.77s) === CONT TestAccAWSRoute_IPv4_To_LocalGateway data_source_aws_outposts_outposts_test.go:67: skipping since no Outposts found --- SKIP: TestAccAWSRoute_IPv4_To_LocalGateway (0.57s) === CONT TestAccAWSRoute_PrefixList_To_EgressOnlyInternetGateway --- PASS: TestAccAWSRoute_basic (36.83s) === CONT TestAccAWSRoute_PrefixList_To_LocalGateway data_source_aws_outposts_outposts_test.go:67: skipping since no Outposts found --- SKIP: TestAccAWSRoute_PrefixList_To_LocalGateway (0.98s) === CONT TestAccAWSRoute_PrefixList_To_CarrierGateway --- PASS: TestAccAWSRoute_PrefixList_To_EgressOnlyInternetGateway (33.33s) === CONT TestAccAWSRoute_PrefixList_To_TransitGateway --- PASS: TestAccAWSRoute_PrefixList_To_CarrierGateway (33.36s) === CONT TestAccAWSRoute_PrefixList_To_NatGateway --- PASS: TestAccAWSRoute_PrefixList_To_NatGateway (209.25s) === CONT TestAccAWSRoute_PrefixList_To_VpcPeeringConnection --- PASS: TestAccAWSRoute_PrefixList_To_VpcPeeringConnection (33.13s) === CONT TestAccAWSRoute_PrefixList_To_NetworkInterface_Attached --- PASS: TestAccAWSRoute_PrefixList_To_TransitGateway (400.32s) === CONT TestAccAWSRoute_PrefixList_To_NetworkInterface_Unattached --- PASS: TestAccAWSRoute_PrefixList_To_NetworkInterface_Unattached (65.97s) === CONT TestAccAWSRoute_PrefixList_To_Instance --- PASS: TestAccAWSRoute_PrefixList_To_NetworkInterface_Attached (349.30s) === CONT TestAccAWSRoute_PrefixList_To_VpnGateway --- PASS: TestAccAWSRoute_PrefixList_To_VpnGateway (59.18s) === CONT TestAccAWSRoute_PrefixList_To_InternetGateway --- PASS: TestAccAWSRoute_PrefixList_To_InternetGateway (35.44s) === CONT TestAccAWSRoute_LocalRoute --- PASS: TestAccAWSRoute_LocalRoute (22.13s) === CONT TestAccAWSRoute_IPv4_To_VpcEndpoint --- PASS: TestAccAWSRoute_PrefixList_To_Instance (328.02s) === CONT TestAccAWSRoute_IPv6_Update_Target --- PASS: TestAccAWSRoute_IPv6_Update_Target (221.14s) === CONT TestAccAWSRoute_IPv4_Update_Target --- PASS: TestAccAWSRoute_IPv4_To_VpcEndpoint (387.03s) === CONT TestAccAWSRoute_ConditionalCidrBlock --- PASS: TestAccAWSRoute_ConditionalCidrBlock (54.14s) === CONT TestAccAWSRoute_IPv6_To_LocalGateway data_source_aws_outposts_outposts_test.go:67: skipping since no Outposts found --- SKIP: TestAccAWSRoute_IPv6_To_LocalGateway (0.57s) === CONT TestAccAWSRoute_IPv4_To_NetworkInterface_Unattached --- PASS: TestAccAWSRoute_IPv4_To_NetworkInterface_Unattached (58.78s) === CONT TestAccAWSRoute_IPv4_To_CarrierGateway --- PASS: TestAccAWSRoute_IPv4_To_CarrierGateway (25.43s) === CONT TestAccAWSRoute_IPv6_To_TransitGateway === CONT TestAccAWSRoute_IPv4_To_TransitGateway --- PASS: TestAccAWSRoute_IPv6_To_TransitGateway (401.51s) --- PASS: TestAccAWSRoute_IPv4_Update_Target (700.08s) === CONT TestAccAWSRoute_DoesNotCrashWithVpcEndpoint --- PASS: TestAccAWSRoute_DoesNotCrashWithVpcEndpoint (47.75s) === CONT TestAccAWSRoute_IPv4_To_NatGateway --- PASS: TestAccAWSRoute_IPv4_To_NatGateway (198.43s) === CONT TestAccAWSRoute_IPv4_To_VpcPeeringConnection --- PASS: TestAccAWSRoute_IPv4_To_VpcPeeringConnection (25.76s) === CONT TestAccAWSRoute_IPv4_To_NetworkInterface_TwoAttachments --- PASS: TestAccAWSRoute_IPv4_To_TransitGateway (380.22s) === CONT TestAccAWSRoute_IPv4_To_NetworkInterface_Attached --- PASS: TestAccAWSRoute_IPv4_To_NetworkInterface_TwoAttachments (176.28s) === CONT TestAccAWSRoute_IPv6_To_NetworkInterface_Unattached --- PASS: TestAccAWSRoute_IPv6_To_NetworkInterface_Unattached (60.62s) === CONT TestAccAWSRoute_IPv4_To_Instance --- PASS: TestAccAWSRoute_IPv4_To_NetworkInterface_Attached (381.16s) === CONT TestAccAWSRoute_IPv4_To_VpnGateway --- PASS: TestAccAWSRoute_IPv4_To_VpnGateway (60.70s) === CONT TestAccAWSRoute_IPv6_To_VpnGateway --- PASS: TestAccAWSRoute_IPv6_To_VpnGateway (50.13s) === CONT TestAccAWSRoute_IPv6_To_VpcPeeringConnection --- PASS: TestAccAWSRoute_IPv6_To_VpcPeeringConnection (26.15s) === CONT TestAccAWSRoute_IPv6_To_InternetGateway --- PASS: TestAccAWSRoute_IPv4_To_Instance (326.49s) === CONT TestAccAWSRoute_IPv6_To_Instance --- PASS: TestAccAWSRoute_IPv6_To_InternetGateway (35.98s) === CONT TestAccAWSRoute_IPv6_To_EgressOnlyInternetGateway --- PASS: TestAccAWSRoute_IPv6_To_EgressOnlyInternetGateway (39.12s) === CONT TestAccAWSRoute_disappears --- PASS: TestAccAWSRoute_disappears (32.59s) --- PASS: TestAccAWSRoute_IPv6_To_Instance (308.78s) PASS ok github.com/terraform-providers/terraform-provider-aws/aws 2928.423s --- aws/resource_aws_route_test.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/aws/resource_aws_route_test.go b/aws/resource_aws_route_test.go index 493b1a4216f..bb7e29e55de 100644 --- a/aws/resource_aws_route_test.go +++ b/aws/resource_aws_route_test.go @@ -847,6 +847,7 @@ func TestAccAWSRoute_IPv6_To_TransitGateway(t *testing.T) { }, }) } + func TestAccAWSRoute_IPv4_To_CarrierGateway(t *testing.T) { var route ec2.Route resourceName := "aws_route.test" @@ -1482,6 +1483,7 @@ func TestAccAWSRoute_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: testAccCheckAWSRouteDestroy, Steps: []resource.TestStep{ @@ -1526,6 +1528,7 @@ func TestAccAWSRoute_PrefixList_To_VpnGateway(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t); testAccPreCheckEc2ManagedPrefixList(t) }, + ErrorCheck: testAccErrorCheck(t, ec2.EndpointsID), Providers: testAccProviders, CheckDestroy: testAccCheckAWSRouteDestroy, Steps: []resource.TestStep{ @@ -1570,6 +1573,7 @@ func TestAccAWSRoute_PrefixList_To_Instance(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t); testAccPreCheckEc2ManagedPrefixList(t) }, + ErrorCheck: testAccErrorCheck(t, ec2.EndpointsID), Providers: testAccProviders, CheckDestroy: testAccCheckAWSRouteDestroy, Steps: []resource.TestStep{ @@ -1614,6 +1618,7 @@ func TestAccAWSRoute_PrefixList_To_NetworkInterface_Unattached(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t); testAccPreCheckEc2ManagedPrefixList(t) }, + ErrorCheck: testAccErrorCheck(t, ec2.EndpointsID), Providers: testAccProviders, CheckDestroy: testAccCheckAWSRouteDestroy, Steps: []resource.TestStep{ @@ -1659,6 +1664,7 @@ func TestAccAWSRoute_PrefixList_To_NetworkInterface_Attached(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t); testAccPreCheckEc2ManagedPrefixList(t) }, + ErrorCheck: testAccErrorCheck(t, ec2.EndpointsID), Providers: testAccProviders, CheckDestroy: testAccCheckAWSRouteDestroy, Steps: []resource.TestStep{ @@ -1703,6 +1709,7 @@ func TestAccAWSRoute_PrefixList_To_VpcPeeringConnection(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t); testAccPreCheckEc2ManagedPrefixList(t) }, + ErrorCheck: testAccErrorCheck(t, ec2.EndpointsID), Providers: testAccProviders, CheckDestroy: testAccCheckAWSRouteDestroy, Steps: []resource.TestStep{ @@ -1747,6 +1754,7 @@ func TestAccAWSRoute_PrefixList_To_NatGateway(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t); testAccPreCheckEc2ManagedPrefixList(t) }, + ErrorCheck: testAccErrorCheck(t, ec2.EndpointsID), Providers: testAccProviders, CheckDestroy: testAccCheckAWSRouteDestroy, Steps: []resource.TestStep{ @@ -1791,6 +1799,7 @@ func TestAccAWSRoute_PrefixList_To_TransitGateway(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t); testAccPreCheckEc2ManagedPrefixList(t) }, + ErrorCheck: testAccErrorCheck(t, ec2.EndpointsID), Providers: testAccProviders, CheckDestroy: testAccCheckAWSRouteDestroy, Steps: []resource.TestStep{ @@ -1839,6 +1848,7 @@ func TestAccAWSRoute_PrefixList_To_CarrierGateway(t *testing.T) { testAccPreCheckEc2ManagedPrefixList(t) testAccPreCheckAWSWavelengthZoneAvailable(t) }, + ErrorCheck: testAccErrorCheck(t, ec2.EndpointsID), Providers: testAccProviders, CheckDestroy: testAccCheckAWSRouteDestroy, Steps: []resource.TestStep{ @@ -1887,6 +1897,7 @@ func TestAccAWSRoute_PrefixList_To_LocalGateway(t *testing.T) { testAccPreCheckEc2ManagedPrefixList(t) testAccPreCheckAWSOutpostsOutposts(t) }, + ErrorCheck: testAccErrorCheck(t, ec2.EndpointsID), Providers: testAccProviders, CheckDestroy: testAccCheckAWSRouteDestroy, Steps: []resource.TestStep{ @@ -1931,6 +1942,7 @@ func TestAccAWSRoute_PrefixList_To_EgressOnlyInternetGateway(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t); testAccPreCheckEc2ManagedPrefixList(t) }, + ErrorCheck: testAccErrorCheck(t, ec2.EndpointsID), Providers: testAccProviders, CheckDestroy: testAccCheckAWSRouteDestroy, Steps: []resource.TestStep{ From c7cb207ed4c7467a263739d18dfa5775d564f56a Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Mon, 29 Mar 2021 11:45:26 -0400 Subject: [PATCH 8/9] r/route: Minor cleaning --- aws/resource_aws_route.go | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/aws/resource_aws_route.go b/aws/resource_aws_route.go index ebab5fcc56e..9465f48fce2 100644 --- a/aws/resource_aws_route.go +++ b/aws/resource_aws_route.go @@ -70,7 +70,6 @@ func resourceAwsRoute() *schema.Resource { validateIpv4CIDRNetworkAddress, ), }, - "destination_ipv6_cidr_block": { Type: schema.TypeString, Optional: true, @@ -81,7 +80,6 @@ func resourceAwsRoute() *schema.Resource { ), DiffSuppressFunc: suppressEqualCIDRBlockDiffs, }, - "destination_prefix_list_id": { Type: schema.TypeString, Optional: true, @@ -97,53 +95,45 @@ func resourceAwsRoute() *schema.Resource { ExactlyOneOf: routeValidTargets, ConflictsWith: []string{"destination_ipv6_cidr_block"}, // IPv4 destinations only. }, - "egress_only_gateway_id": { Type: schema.TypeString, Optional: true, ExactlyOneOf: routeValidTargets, ConflictsWith: []string{"destination_cidr_block"}, // IPv6 destinations only. }, - "gateway_id": { Type: schema.TypeString, Optional: true, ExactlyOneOf: routeValidTargets, }, - "instance_id": { Type: schema.TypeString, Optional: true, Computed: true, ExactlyOneOf: routeValidTargets, }, - "local_gateway_id": { Type: schema.TypeString, Optional: true, ExactlyOneOf: routeValidTargets, }, - "nat_gateway_id": { Type: schema.TypeString, Optional: true, ExactlyOneOf: routeValidTargets, ConflictsWith: []string{"destination_ipv6_cidr_block"}, // IPv4 destinations only. }, - "network_interface_id": { Type: schema.TypeString, Optional: true, Computed: true, ExactlyOneOf: routeValidTargets, }, - "transit_gateway_id": { Type: schema.TypeString, Optional: true, ExactlyOneOf: routeValidTargets, }, - "vpc_endpoint_id": { Type: schema.TypeString, Optional: true, @@ -153,7 +143,6 @@ func resourceAwsRoute() *schema.Resource { "destination_prefix_list_id", // "Cannot create or replace a prefix list route targeting a VPC Endpoint." }, }, - "vpc_peering_connection_id": { Type: schema.TypeString, Optional: true, @@ -167,12 +156,10 @@ func resourceAwsRoute() *schema.Resource { Type: schema.TypeString, Computed: true, }, - "origin": { Type: schema.TypeString, Computed: true, }, - "state": { Type: schema.TypeString, Computed: true, @@ -292,7 +279,7 @@ func resourceAwsRouteCreate(d *schema.ResourceData, meta interface{}) error { } if tfresource.NotFound(err) { - return fmt.Errorf("Route in Route Table (%s) with destination (%s) not found", routeTableID, destination) + return fmt.Errorf("route in Route Table (%s) with destination (%s) not found", routeTableID, destination) } d.SetId(tfec2.RouteCreateID(routeTableID, destination)) From 8f4e1befa7bb3147ff1b5d1f7f2e2c90dd28956c Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Mon, 29 Mar 2021 11:47:18 -0400 Subject: [PATCH 9/9] docs/r/route: Minor cleanup --- website/docs/r/route.html.markdown | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/website/docs/r/route.html.markdown b/website/docs/r/route.html.markdown index 58d93da6fa9..f5679bf935b 100644 --- a/website/docs/r/route.html.markdown +++ b/website/docs/r/route.html.markdown @@ -10,11 +10,7 @@ description: |- Provides a resource to create a routing table entry (a route) in a VPC routing table. -~> **NOTE on Route Tables and Routes:** Terraform currently -provides both a standalone Route resource and a [Route Table](route_table.html) resource with routes -defined in-line. At this time you cannot use a Route Table with in-line routes -in conjunction with any Route resources. Doing so will cause -a conflict of rule settings and will overwrite rules. +~> **NOTE on Route Tables and Routes:** Terraform currently provides both a standalone Route resource and a [Route Table](route_table.html) resource with routes defined in-line. At this time you cannot use a Route Table with in-line routes in conjunction with any Route resources. Doing so will cause a conflict of rule settings and will overwrite rules. ~> **NOTE on `gateway_id` attribute:** The AWS API is very forgiving with the resource ID passed in the `gateway_id` attribute. For example an `aws_route` resource can be created with an [`aws_nat_gateway`](nat_gateway.html) or [`aws_egress_only_internet_gateway`](egress_only_internet_gateway.html) ID specified for the `gateway_id` attribute. Specifying anything other than an [`aws_internet_gateway`](internet_gateway.html) or [`aws_vpn_gateway`](vpn_gateway.html) ID will lead to Terraform reporting a permanent diff between your configuration and recorded state, as the AWS API returns the more-specific attribute. If you are experiencing constant diffs with an `aws_route` resource, the first thing to check is that the correct attribute is being specified. @@ -73,15 +69,13 @@ One of the following target arguments must be supplied: * `vpc_endpoint_id` - (Optional) Identifier of a VPC Endpoint. * `vpc_peering_connection_id` - (Optional) Identifier of a VPC peering connection. -Note that the default route, mapping the VPC's CIDR block to "local", is -created implicitly and cannot be specified. +Note that the default route, mapping the VPC's CIDR block to "local", is created implicitly and cannot be specified. ## Attributes Reference In addition to all arguments above, the following attributes are exported: -~> **NOTE:** Only the arguments that are configured (one of the above) -will be exported as an attribute once the resource is created. +~> **NOTE:** Only the arguments that are configured (one of the above) will be exported as an attribute once the resource is created. * `id` - Route identifier computed from the routing table identifier and route destination. * `instance_owner_id` - The AWS account ID of the owner of the EC2 instance. @@ -90,8 +84,7 @@ will be exported as an attribute once the resource is created. ## Timeouts -`aws_route` provides the following -[Timeouts](https://www.terraform.io/docs/configuration/blocks/resources/syntax.html#operation-timeouts) configuration options: +`aws_route` provides the following [Timeouts](https://www.terraform.io/docs/configuration/blocks/resources/syntax.html#operation-timeouts) configuration options: - `create` - (Default `2 minutes`) Used for route creation - `delete` - (Default `5 minutes`) Used for route deletion