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: AWS Wavelength support #16963

Merged
merged 5 commits into from
Mar 26, 2021
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/16963.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-notes:enhancement
data-source/aws_route: Add `carrier_gateway_id` attribute
```
184 changes: 77 additions & 107 deletions aws/data_source_aws_route.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ package aws

import (
"fmt"
"log"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
tfec2 "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/ec2"
"github.com/terraform-providers/terraform-provider-aws/aws/internal/service/ec2/finder"
)

func dataSourceAwsRoute() *schema.Resource {
Expand All @@ -19,6 +19,10 @@ func dataSourceAwsRoute() *schema.Resource {
Type: schema.TypeString,
Required: true,
},

///
// Destinations.
///
"destination_cidr_block": {
Type: schema.TypeString,
Optional: true,
Expand All @@ -29,6 +33,15 @@ func dataSourceAwsRoute() *schema.Resource {
Optional: true,
Computed: true,
},

//
// Targets.
//
"carrier_gateway_id": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"egress_only_gateway_id": {
Type: schema.TypeString,
Optional: true,
Expand All @@ -44,27 +57,27 @@ func dataSourceAwsRoute() *schema.Resource {
Optional: true,
Computed: true,
},
"nat_gateway_id": {
"local_gateway_id": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"local_gateway_id": {
"nat_gateway_id": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"transit_gateway_id": {
"network_interface_id": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"vpc_peering_connection_id": {
"transit_gateway_id": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"network_interface_id": {
"vpc_peering_connection_id": {
Type: schema.TypeString,
Optional: true,
Computed: true,
Expand All @@ -75,63 +88,19 @@ func dataSourceAwsRoute() *schema.Resource {

func dataSourceAwsRouteRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).ec2conn
req := &ec2.DescribeRouteTablesInput{}
rtbId := d.Get("route_table_id")
cidr := d.Get("destination_cidr_block")
ipv6Cidr := d.Get("destination_ipv6_cidr_block")

req.Filters = buildEC2AttributeFilterList(
map[string]string{
"route-table-id": rtbId.(string),
"route.destination-cidr-block": cidr.(string),
"route.destination-ipv6-cidr-block": ipv6Cidr.(string),
},
)

log.Printf("[DEBUG] Reading Route Table: %s", req)
resp, err := conn.DescribeRouteTables(req)
if err != nil {
return err
}
if resp == nil || len(resp.RouteTables) == 0 {
return fmt.Errorf("Your query returned no results. Please change your search criteria and try again.")
}
if len(resp.RouteTables) > 1 {
return fmt.Errorf("Your query returned more than one route table. Please change your search criteria and try again.")
}
routeTableID := d.Get("route_table_id").(string)

results := getRoutes(resp.RouteTables[0], d)
routeTable, err := finder.RouteTableByID(conn, routeTableID)

if len(results) == 0 {
return fmt.Errorf("No routes matching supplied arguments found in table(s)")
}
if len(results) > 1 {
return fmt.Errorf("Multiple routes matched; use additional constraints to reduce matches to a single route")
if err != nil {
return fmt.Errorf("error reading Route Table (%s): %w", routeTableID, err)
}
route := results[0]

d.SetId(resourceAwsRouteID(d, route)) // using function from "resource_aws_route.go"
d.Set("destination_cidr_block", route.DestinationCidrBlock)
d.Set("destination_ipv6_cidr_block", route.DestinationIpv6CidrBlock)
d.Set("egress_only_gateway_id", route.EgressOnlyInternetGatewayId)
d.Set("gateway_id", route.GatewayId)
d.Set("instance_id", route.InstanceId)
d.Set("nat_gateway_id", route.NatGatewayId)
d.Set("local_gateway_id", route.LocalGatewayId)
d.Set("transit_gateway_id", route.TransitGatewayId)
d.Set("vpc_peering_connection_id", route.VpcPeeringConnectionId)
d.Set("network_interface_id", route.NetworkInterfaceId)

return nil
}

func getRoutes(table *ec2.RouteTable, d *schema.ResourceData) []*ec2.Route {
ec2Routes := table.Routes
routes := make([]*ec2.Route, 0, len(ec2Routes))
// Loop through the routes and add them to the set
for _, r := range ec2Routes {
routes := []*ec2.Route{}

if r.Origin != nil && *r.Origin == "EnableVgwRoutePropagation" {
for _, r := range routeTable.Routes {
if aws.StringValue(r.Origin) == ec2.RouteOriginEnableVgwRoutePropagation {
continue
}

Expand All @@ -141,79 +110,80 @@ func getRoutes(table *ec2.RouteTable, d *schema.ResourceData) []*ec2.Route {
continue
}

if v, ok := d.GetOk("destination_cidr_block"); ok {
if r.DestinationCidrBlock == nil || *r.DestinationCidrBlock != v.(string) {
continue
}
if v, ok := d.GetOk("destination_cidr_block"); ok && aws.StringValue(r.DestinationCidrBlock) != v.(string) {
continue
}

if v, ok := d.GetOk("destination_ipv6_cidr_block"); ok {
if r.DestinationIpv6CidrBlock == nil || *r.DestinationIpv6CidrBlock != v.(string) {
continue
}
if v, ok := d.GetOk("destination_ipv6_cidr_block"); ok && aws.StringValue(r.DestinationIpv6CidrBlock) != v.(string) {
continue
}

if v, ok := d.GetOk("egress_only_gateway_id"); ok {
if r.EgressOnlyInternetGatewayId == nil || *r.EgressOnlyInternetGatewayId != v.(string) {
continue
}
if v, ok := d.GetOk("carrier_gateway_id"); ok && aws.StringValue(r.CarrierGatewayId) != v.(string) {
continue
}

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

if v, ok := d.GetOk("gateway_id"); ok {
if r.GatewayId == nil || *r.GatewayId != v.(string) {
continue
}
if v, ok := d.GetOk("gateway_id"); ok && aws.StringValue(r.GatewayId) != v.(string) {
continue
}

if v, ok := d.GetOk("instance_id"); ok {
if r.InstanceId == nil || *r.InstanceId != v.(string) {
continue
}
if v, ok := d.GetOk("instance_id"); ok && aws.StringValue(r.InstanceId) != v.(string) {
continue
}

if v, ok := d.GetOk("nat_gateway_id"); ok {
if r.NatGatewayId == nil || *r.NatGatewayId != v.(string) {
continue
}
if v, ok := d.GetOk("local_gateway_id"); ok && aws.StringValue(r.LocalGatewayId) != v.(string) {
continue
}

if v, ok := d.GetOk("local_gateway_id"); ok {
if r.LocalGatewayId == nil || *r.LocalGatewayId != v.(string) {
continue
}
if v, ok := d.GetOk("nat_gateway_id"); ok && aws.StringValue(r.NatGatewayId) != v.(string) {
continue
}

if v, ok := d.GetOk("transit_gateway_id"); ok {
if r.TransitGatewayId == nil || *r.TransitGatewayId != v.(string) {
continue
}
if v, ok := d.GetOk("network_interface_id"); ok && aws.StringValue(r.NetworkInterfaceId) != v.(string) {
continue
}

if v, ok := d.GetOk("vpc_peering_connection_id"); ok {
if r.VpcPeeringConnectionId == nil || *r.VpcPeeringConnectionId != v.(string) {
continue
}
if v, ok := d.GetOk("transit_gateway_id"); ok && aws.StringValue(r.TransitGatewayId) != v.(string) {
continue
}

if v, ok := d.GetOk("network_interface_id"); ok {
if r.NetworkInterfaceId == nil || *r.NetworkInterfaceId != v.(string) {
continue
}
if v, ok := d.GetOk("vpc_peering_connection_id"); ok && aws.StringValue(r.VpcPeeringConnectionId) != v.(string) {
continue
}

routes = append(routes, r)
}
return routes
}

// Helper: Create an ID for a route
func resourceAwsRouteID(d *schema.ResourceData, r *ec2.Route) string {
routeTableID := d.Get("route_table_id").(string)
if len(routes) == 0 {
return fmt.Errorf("No routes matching supplied arguments found in Route Table (%s)", routeTableID)
}

if len(routes) > 1 {
return fmt.Errorf("%d routes matched in Route Table (%s); use additional constraints to reduce matches to a single route", len(routes), routeTableID)
}

route := routes[0]

if destination := aws.StringValue(r.DestinationCidrBlock); destination != "" {
return tfec2.RouteCreateID(routeTableID, destination)
} else if destination := aws.StringValue(r.DestinationIpv6CidrBlock); destination != "" {
return tfec2.RouteCreateID(routeTableID, destination)
if destination := aws.StringValue(route.DestinationCidrBlock); destination != "" {
d.SetId(tfec2.RouteCreateID(routeTableID, destination))
} else if destination := aws.StringValue(route.DestinationIpv6CidrBlock); destination != "" {
d.SetId(tfec2.RouteCreateID(routeTableID, destination))
}

return ""
d.Set("carrier_gateway_id", route.CarrierGatewayId)
d.Set("destination_cidr_block", route.DestinationCidrBlock)
d.Set("destination_ipv6_cidr_block", route.DestinationIpv6CidrBlock)
d.Set("egress_only_gateway_id", route.EgressOnlyInternetGatewayId)
d.Set("gateway_id", route.GatewayId)
d.Set("instance_id", route.InstanceId)
d.Set("local_gateway_id", route.LocalGatewayId)
d.Set("nat_gateway_id", route.NatGatewayId)
d.Set("network_interface_id", route.NetworkInterfaceId)
d.Set("transit_gateway_id", route.TransitGatewayId)
d.Set("vpc_peering_connection_id", route.VpcPeeringConnectionId)

return nil
}
62 changes: 62 additions & 0 deletions aws/data_source_aws_route_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,29 @@ func TestAccAWSRouteDataSource_LocalGatewayID(t *testing.T) {
})
}

func TestAccAWSRouteDataSource_CarrierGatewayID(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); testAccPreCheckAWSWavelengthZoneAvailable(t) },
ErrorCheck: testAccErrorCheck(t, ec2.EndpointsID),
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSRouteDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSRouteDataSourceConfigIpv4CarrierGateway(rName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrPair(resourceName, "destination_cidr_block", dataSourceName, "destination_cidr_block"),
resource.TestCheckResourceAttrPair(resourceName, "route_table_id", dataSourceName, "route_table_id"),
resource.TestCheckResourceAttrPair(resourceName, "carrier_gateway_id", dataSourceName, "carrier_gateway_id"),
),
},
},
})
}

func testAccDataSourceAwsRouteConfigBasic(rName string) string {
return composeConfig(
testAccLatestAmazonLinuxHvmEbsAmiConfig(),
Expand Down Expand Up @@ -352,3 +375,42 @@ data "aws_route" "by_local_gateway_id" {
}
`, rName)
}

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

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

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

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

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

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

resource "aws_route" "test" {
destination_cidr_block = "0.0.0.0/0"
route_table_id = aws_route_table.test.id
carrier_gateway_id = aws_ec2_carrier_gateway.test.id
}

data "aws_route" "test" {
route_table_id = aws_route.test.route_table_id
carrier_gateway_id = aws_route.test.carrier_gateway_id
}
`, rName)
}
Loading