Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

d/aws_route: 'destination_prefix_list_id' attribute set for managed prefix list destinations #17295

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .changelog/17295.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-notes:enhancement
data-source/aws_route: Add `destination_prefix_list_id` attribute
```
16 changes: 15 additions & 1 deletion aws/data_source_aws_route.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package aws

import (
"fmt"
"strings"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
Expand Down Expand Up @@ -34,6 +35,12 @@ func dataSourceAwsRoute() *schema.Resource {
Computed: true,
},

"destination_prefix_list_id": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},

//
// Targets.
//
Expand Down Expand Up @@ -104,7 +111,7 @@ func dataSourceAwsRouteRead(d *schema.ResourceData, meta interface{}) error {
continue
}

if r.DestinationPrefixListId != nil {
if r.DestinationPrefixListId != nil && strings.HasPrefix(aws.StringValue(r.GatewayId), "vpce-") {
// Skipping because VPC endpoint routes are handled separately
// See aws_vpc_endpoint
continue
Expand All @@ -118,6 +125,10 @@ func dataSourceAwsRouteRead(d *schema.ResourceData, meta interface{}) error {
continue
}

if v, ok := d.GetOk("destination_prefix_list_id"); ok && aws.StringValue(r.DestinationPrefixListId) != v.(string) {
continue
}

if v, ok := d.GetOk("carrier_gateway_id"); ok && aws.StringValue(r.CarrierGatewayId) != v.(string) {
continue
}
Expand Down Expand Up @@ -171,11 +182,14 @@ func dataSourceAwsRouteRead(d *schema.ResourceData, meta interface{}) error {
d.SetId(tfec2.RouteCreateID(routeTableID, destination))
} else if destination := aws.StringValue(route.DestinationIpv6CidrBlock); destination != "" {
d.SetId(tfec2.RouteCreateID(routeTableID, destination))
} else if destination := aws.StringValue(route.DestinationPrefixListId); destination != "" {
d.SetId(tfec2.RouteCreateID(routeTableID, destination))
}

d.Set("carrier_gateway_id", route.CarrierGatewayId)
d.Set("destination_cidr_block", route.DestinationCidrBlock)
d.Set("destination_ipv6_cidr_block", route.DestinationIpv6CidrBlock)
d.Set("destination_prefix_list_id", route.DestinationPrefixListId)
d.Set("egress_only_gateway_id", route.EgressOnlyInternetGatewayId)
d.Set("gateway_id", route.GatewayId)
d.Set("instance_id", route.InstanceId)
Expand Down
170 changes: 170 additions & 0 deletions aws/data_source_aws_route_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package aws

import (
"fmt"
"regexp"
"testing"

"github.com/aws/aws-sdk-go/service/ec2"
Expand Down Expand Up @@ -138,6 +139,58 @@ func TestAccAWSRouteDataSource_CarrierGatewayID(t *testing.T) {
})
}

func TestAccAWSRouteDataSource_DestinationPrefixListId(t *testing.T) {
dataSourceName := "data.aws_route.test"
resourceName := "aws_route.test"
rName := acctest.RandomWithPrefix("tf-acc-test")

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t); testAccPreCheckEc2ManagedPrefixList(t) },
ErrorCheck: testAccErrorCheck(t, ec2.EndpointsID),
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSRouteDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSRouteDataSourceConfigPrefixListNatGateway(rName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrPair(resourceName, "destination_prefix_list_id", dataSourceName, "destination_prefix_list_id"),
resource.TestCheckResourceAttrPair(resourceName, "nat_gateway_id", dataSourceName, "nat_gateway_id"),
resource.TestCheckResourceAttrPair(resourceName, "route_table_id", dataSourceName, "route_table_id"),
),
},
},
})
}

func TestAccAWSRouteDataSource_GatewayVpcEndpoint(t *testing.T) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test validates this change by adding a Gateway VPC Endpoint (S3), specifying that endpoint's prefix list ID to the data source and verifying that no route is returned.

var routeTable ec2.RouteTable
var vpce ec2.VpcEndpoint
rtResourceName := "aws_route_table.test"
vpceResourceName := "aws_vpc_endpoint.test"
rName := acctest.RandomWithPrefix("tf-acc-test")

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ErrorCheck: testAccErrorCheck(t, ec2.EndpointsID),
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSRouteDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSRouteDataSourceConfigGatewayVpcEndpointNoDataSource(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckRouteTableExists(rtResourceName, &routeTable),
testAccCheckVpcEndpointExists(vpceResourceName, &vpce),
testAccCheckAWSRouteTableWaitForVpcEndpointRoute(&routeTable, &vpce),
),
},
{
Config: testAccAWSRouteDataSourceConfigGatewayVpcEndpointWithDataSource(rName),
ExpectError: regexp.MustCompile(`No routes matching supplied arguments found in Route Table`),
},
},
})
}

func testAccDataSourceAwsRouteConfigBasic(rName string) string {
return composeConfig(
testAccLatestAmazonLinuxHvmEbsAmiConfig(),
Expand Down Expand Up @@ -414,3 +467,120 @@ data "aws_route" "test" {
}
`, rName)
}

func testAccAWSRouteDataSourceConfigPrefixListNatGateway(rName string) string {
return fmt.Sprintf(`
resource "aws_vpc" "test" {
cidr_block = "10.1.0.0/16"

tags = {
Name = %[1]q
}
}

resource "aws_subnet" "test" {
cidr_block = "10.1.1.0/24"
vpc_id = aws_vpc.test.id

map_public_ip_on_launch = true

tags = {
Name = %[1]q
}
}

resource "aws_internet_gateway" "test" {
vpc_id = aws_vpc.test.id

tags = {
Name = %[1]q
}
}

resource "aws_eip" "test" {
vpc = true

tags = {
Name = %[1]q
}
}

resource "aws_nat_gateway" "test" {
allocation_id = aws_eip.test.id
subnet_id = aws_subnet.test.id

tags = {
Name = %[1]q
}

depends_on = [aws_internet_gateway.test]
}

resource "aws_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
nat_gateway_id = aws_nat_gateway.test.id
}

data "aws_route" "test" {
route_table_id = aws_route.test.route_table_id
destination_prefix_list_id = aws_route.test.destination_prefix_list_id
nat_gateway_id = aws_route.test.nat_gateway_id
}
`, rName)
}

func testAccAWSRouteDataSourceConfigGatewayVpcEndpointNoDataSource(rName string) string {
return fmt.Sprintf(`
resource "aws_vpc" "test" {
cidr_block = "10.1.0.0/16"

tags = {
Name = %[1]q
}
}

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]
}

resource "aws_route_table" "test" {
vpc_id = aws_vpc.test.id

tags = {
Name = %[1]q
}
}
`, rName)
}

func testAccAWSRouteDataSourceConfigGatewayVpcEndpointWithDataSource(rName string) string {
return composeConfig(testAccAWSRouteDataSourceConfigGatewayVpcEndpointNoDataSource(rName), `
data "aws_prefix_list" "test" {
name = aws_vpc_endpoint.test.service_name
}

data "aws_route" "test" {
route_table_id = aws_route_table.test.id
destination_prefix_list_id = data.aws_prefix_list.test.id
}
`)
}
2 changes: 1 addition & 1 deletion aws/resource_aws_default_route_table_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ func TestAccAWSDefaultRouteTable_IPv4_To_VpcEndpoint(t *testing.T) {
destinationCidr := "0.0.0.0/0"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
PreCheck: func() { testAccPreCheck(t); testAccPreCheckElbv2GatewayLoadBalancer(t) },
ErrorCheck: testAccErrorCheck(t, ec2.EndpointsID, "elasticloadbalancing"),
Providers: testAccProviders,
CheckDestroy: testAccCheckRouteTableDestroy,
Expand Down
2 changes: 1 addition & 1 deletion aws/resource_aws_route_table_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -559,7 +559,7 @@ func TestAccAWSRouteTable_IPv4_To_VpcEndpoint(t *testing.T) {

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t); testAccPreCheckElbv2GatewayLoadBalancer(t) },
ErrorCheck: testAccErrorCheck(t, ec2.EndpointsID),
ErrorCheck: testAccErrorCheck(t, ec2.EndpointsID, "elasticloadbalancing"),
Providers: testAccProviders,
CheckDestroy: testAccCheckRouteTableDestroy,
Steps: []resource.TestStep{
Expand Down
2 changes: 1 addition & 1 deletion aws/resource_aws_route_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1397,7 +1397,7 @@ func TestAccAWSRoute_IPv4_To_VpcEndpoint(t *testing.T) {
destinationCidr := "172.16.1.0/24"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
PreCheck: func() { testAccPreCheck(t); testAccPreCheckElbv2GatewayLoadBalancer(t) },
ErrorCheck: testAccErrorCheck(t, ec2.EndpointsID, "elasticloadbalancing"),
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSRouteDestroy,
Expand Down
1 change: 1 addition & 0 deletions website/docs/d/route.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ The following arguments are optional:
* `carrier_gateway_id` - (Optional) EC2 Carrier Gateway ID of the Route belonging to the Route Table.
* `destination_cidr_block` - (Optional) CIDR block of the Route belonging to the Route Table.
* `destination_ipv6_cidr_block` - (Optional) IPv6 CIDR block of the Route belonging to the Route Table.
* `destination_prefix_list_id` - (Optional) The ID of a [managed prefix list](ec2_managed_prefix_list.html) destination of the Route belonging to the Route Table.
* `egress_only_gateway_id` - (Optional) Egress Only Gateway ID of the Route belonging to the Route Table.
* `gateway_id` - (Optional) Gateway ID of the Route belonging to the Route Table.
* `instance_id` - (Optional) Instance ID of the Route belonging to the Route Table.
Expand Down