Skip to content

Commit

Permalink
Merge pull request #4529 from VeganBroccoli/data_source_aws_route
Browse files Browse the repository at this point in the history
New Resource: d/aws_route
  • Loading branch information
jen20 authored May 26, 2018
2 parents 50b338c + e1cca9a commit 255f252
Show file tree
Hide file tree
Showing 5 changed files with 425 additions and 0 deletions.
180 changes: 180 additions & 0 deletions aws/data_source_aws_route.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
package aws

import (
"fmt"
"log"

"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/terraform/helper/schema"
)

func dataSourceAwsRoute() *schema.Resource {
return &schema.Resource{
Read: dataSourceAwsRouteRead,

Schema: map[string]*schema.Schema{
"route_table_id": {
Type: schema.TypeString,
Required: true,
},
"destination_cidr_block": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"destination_ipv6_cidr_block": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"egress_only_gateway_id": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"gateway_id": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"instance_id": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"nat_gateway_id": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"vpc_peering_connection_id": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"network_interface_id": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
},
}
}

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.")
}

results := getRoutes(resp.RouteTables[0], d)

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")
}
route := results[0]

d.SetId(routeIDHash(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("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 {

if r.Origin != nil && *r.Origin == "EnableVgwRoutePropagation" {
continue
}

if r.DestinationPrefixListId != nil {
// Skipping because VPC endpoint routes are handled separately
// See aws_vpc_endpoint
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_ipv6_cidr_block"); ok {
if r.DestinationIpv6CidrBlock == nil || *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("gateway_id"); ok {
if r.GatewayId == nil || *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("nat_gateway_id"); ok {
if r.NatGatewayId == nil || *r.NatGatewayId != 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("network_interface_id"); ok {
if r.NetworkInterfaceId == nil || *r.NetworkInterfaceId != v.(string) {
continue
}
}
routes = append(routes, r)
}
return routes
}
174 changes: 174 additions & 0 deletions aws/data_source_aws_route_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
package aws

import (
"fmt"
"testing"

"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)

func TestAccDataSourceAwsRoute_basic(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccDataSourceAwsRouteGroupConfig,
Check: resource.ComposeTestCheckFunc(
testAccDataSourceAwsRouteCheck("data.aws_route.by_destination_cidr_block"),
testAccDataSourceAwsRouteCheck("data.aws_route.by_instance_id"),
testAccDataSourceAwsRouteCheck("data.aws_route.by_peering_connection_id"),
),
ExpectNonEmptyPlan: true,
},
},
})
}

func testAccDataSourceAwsRouteCheck(name string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[name]

if !ok {
return fmt.Errorf("root module has no resource called %s", name)
}

r, ok := s.RootModule().Resources["aws_route.test"]
if !ok {
return fmt.Errorf("can't find aws_route.test in state")
}
rts, ok := s.RootModule().Resources["aws_route_table.test"]
if !ok {
return fmt.Errorf("can't find aws_route_table.test in state")
}

attr := rs.Primary.Attributes

if attr["route_table_id"] != r.Primary.Attributes["route_table_id"] {
return fmt.Errorf(
"route_table_id is %s; want %s",
attr["route_table_id"],
r.Primary.Attributes["route_table_id"],
)
}

if attr["route_table_id"] != rts.Primary.Attributes["id"] {
return fmt.Errorf(
"route_table_id is %s; want %s",
attr["route_table_id"],
rts.Primary.Attributes["id"],
)
}

return nil
}
}

const testAccDataSourceAwsRouteGroupConfig = `
provider "aws" {
region = "ap-southeast-2"
}
resource "aws_vpc" "test" {
cidr_block = "172.16.0.0/16"
tags {
Name = "terraform-testacc-route-table-data-source"
}
}
resource "aws_vpc" "dest" {
cidr_block = "172.17.0.0/16"
tags {
Name = "terraform-testacc-route-table-data-source"
}
}
resource "aws_vpc_peering_connection" "test" {
peer_vpc_id = "${aws_vpc.dest.id}"
vpc_id = "${aws_vpc.test.id}"
auto_accept = true
}
resource "aws_subnet" "test" {
cidr_block = "172.16.0.0/24"
vpc_id = "${aws_vpc.test.id}"
tags {
Name = "tf-acc-route-table-data-source"
}
}
resource "aws_route_table" "test" {
vpc_id = "${aws_vpc.test.id}"
tags {
Name = "terraform-testacc-routetable-data-source"
}
}
resource "aws_route" "pcx" {
route_table_id = "${aws_route_table.test.id}"
vpc_peering_connection_id = "${aws_vpc_peering_connection.test.id}"
destination_cidr_block = "10.0.2.0/24"
}
resource "aws_route_table_association" "a" {
subnet_id = "${aws_subnet.test.id}"
route_table_id = "${aws_route_table.test.id}"
}
data "aws_ami" "ubuntu" {
most_recent = true
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-trusty-14.04-amd64-server-*"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
owners = ["099720109477"] # Canonical
}
resource "aws_instance" "web" {
ami = "${data.aws_ami.ubuntu.id}"
instance_type = "t2.micro"
subnet_id = "${aws_subnet.test.id}"
tags {
Name = "HelloWorld"
}
}
resource "aws_route" "test" {
route_table_id = "${aws_route_table.test.id}"
destination_cidr_block = "10.0.1.0/24"
instance_id = "${aws_instance.web.id}"
timeouts {
create ="5m"
}
}
data "aws_route" "by_peering_connection_id"{
route_table_id = "${aws_route_table.test.id}"
vpc_peering_connection_id = "${aws_route.pcx.vpc_peering_connection_id}"
}
data "aws_route" "by_destination_cidr_block"{
route_table_id = "${aws_route_table.test.id}"
destination_cidr_block = "10.0.1.0/24"
depends_on = ["aws_route.test"]
}
data "aws_route" "by_instance_id"{
route_table_id = "${aws_route_table.test.id}"
instance_id = "${aws_instance.web.id}"
depends_on = ["aws_route.test"]
}
`
1 change: 1 addition & 0 deletions aws/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ func Provider() terraform.ResourceProvider {
"aws_redshift_cluster": dataSourceAwsRedshiftCluster(),
"aws_redshift_service_account": dataSourceAwsRedshiftServiceAccount(),
"aws_region": dataSourceAwsRegion(),
"aws_route": dataSourceAwsRoute(),
"aws_route_table": dataSourceAwsRouteTable(),
"aws_route53_zone": dataSourceAwsRoute53Zone(),
"aws_s3_bucket": dataSourceAwsS3Bucket(),
Expand Down
3 changes: 3 additions & 0 deletions website/aws.erb
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,9 @@
<li<%= sidebar_current("docs-aws-datasource-route-table") %>>
<a href="/docs/providers/aws/d/route_table.html">aws_route_table</a>
</li>
<li<%= sidebar_current("docs-aws-datasource-route") %>>
<a href="/docs/providers/aws/d/route.html">aws_route</a>
</li>
<li<%= sidebar_current("docs-aws-datasource-s3-bucket") %>>
<a href="/docs/providers/aws/d/s3_bucket.html">aws_s3_bucket</a>
</li>
Expand Down
Loading

0 comments on commit 255f252

Please sign in to comment.