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

New Resource: d/aws_route #4529

Merged
merged 2 commits into from
May 26, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
183 changes: 183 additions & 0 deletions aws/data_source_aws_route.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
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, rtbOk := d.GetOk("route_table_id")
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure we need a check here, since the schema marks route_table_id as required.

cidr := d.Get("destination_cidr_block")
ipv6Cidr := d.Get("destination_ipv6_cidr_block")

if !rtbOk {
Copy link
Contributor

Choose a reason for hiding this comment

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

Similarly, I'm not sure this guard clause is required.

return fmt.Errorf("Route table must be assigned")
}
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 @@ -226,6 +226,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 @@ -247,6 +247,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