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

Added data source for aws_route_tables #4841

Merged
merged 4 commits into from
Jun 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
68 changes: 68 additions & 0 deletions aws/data_source_aws_route_table_ids.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package aws

import (
"fmt"
"log"

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

func dataSourceAwsRouteTableIDs() *schema.Resource {
return &schema.Resource{
Read: dataSourceAwsRouteTableIDsRead,
Schema: map[string]*schema.Schema{

"tags": tagsSchemaComputed(),

"vpc_id": {
Type: schema.TypeString,
Required: true,
Copy link
Contributor

Choose a reason for hiding this comment

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

According the EC2 API Reference, vpc_id should not be a required argument. Its valid to search for route tables across multiple VPCs. Can you please:

  • Change the attribute to Optional: true
  • Use d.GetOk("vpc_id") instead of expecting it to always exist:
if v, ok := d.GetOk("vpc_id"); ok {
	req.Filters = buildEC2AttributeFilterList(
		map[string]string{
			"vpc-id": v.(string),
		},
	)
}
  • Change d.SetId(d.Get("vpc_id").(string)) to d.SetId(resource.UniqueId())
  • Ensure the documentation is updated for the attribute

},

"ids": {
Type: schema.TypeSet,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
Set: schema.HashString,
},
},
}
}

func dataSourceAwsRouteTableIDsRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).ec2conn

req := &ec2.DescribeRouteTablesInput{}

req.Filters = buildEC2AttributeFilterList(
map[string]string{
"vpc-id": d.Get("vpc_id").(string),
},
)

req.Filters = append(req.Filters, buildEC2TagFilterList(
tagsFromMap(d.Get("tags").(map[string]interface{})),
)...)

log.Printf("[DEBUG] DescribeRouteTables %s\n", req)
resp, err := conn.DescribeRouteTables(req)
if err != nil {
return err
}

if resp == nil || len(resp.RouteTables) == 0 {
return fmt.Errorf("no matching route tables found for vpc with id %s", d.Get("vpc_id").(string))
}

routeTables := make([]string, 0)

for _, routeTable := range resp.RouteTables {
routeTables = append(routeTables, *routeTable.RouteTableId)
Copy link
Contributor

Choose a reason for hiding this comment

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

To prevent potential panics, we should prefer to use the SDK helper aws.StringValue(routeTable.RouteTableId) instead of directly dereferencing via *

}

d.SetId(d.Get("vpc_id").(string))
d.Set("ids", routeTables)
Copy link
Contributor

Choose a reason for hiding this comment

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

When using d.Set() with aggregate types (e.g. TypeList/TypeSet/TypeMap) we should perform error checking: https://www.terraform.io/docs/extend/best-practices/detecting-drift.html#error-checking-aggregate-types

if err := d.Set("ids", routeTables); err != nil {
  return fmt.Errorf("error setting ids: %s", err)
}


return nil
}
119 changes: 119 additions & 0 deletions aws/data_source_aws_route_table_ids_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package aws

import (
"fmt"
"testing"

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

func TestAccDataSourceAwsRouteTableIDs(t *testing.T) {
rInt := acctest.RandIntRange(0, 256)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckVpcDestroy,
Steps: []resource.TestStep{
{
Config: testAccDataSourceAwsRouteTableIDsConfig(rInt),
},
{
Config: testAccDataSourceAwsRouteTableIDsConfigWithDataSource(rInt),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("data.aws_route_table_ids.selected", "ids.#", "3"),
resource.TestCheckResourceAttr("data.aws_route_table_ids.private", "ids.#", "2"),
),
},
},
})
}

func testAccDataSourceAwsRouteTableIDsConfigWithDataSource(rInt int) string {
return fmt.Sprintf(`
resource "aws_vpc" "test" {
cidr_block = "172.%d.0.0/16"

tags {
Name = "terraform-testacc-route-table-ids-data-source"
}
}

resource "aws_route_table" "test_public_a" {
vpc_id = "${aws_vpc.test.id}"

tags {
Name = "tf-acc-route-table-ids-data-source-public-a"
Tier = "Public"
}
}

resource "aws_route_table" "test_private_a" {
vpc_id = "${aws_vpc.test.id}"

tags {
Name = "tf-acc-route-table-ids-data-source-private-a"
Tier = "Private"
}
}

resource "aws_route_table" "test_private_b" {
vpc_id = "${aws_vpc.test.id}"

tags {
Name = "tf-acc-route-table-ids-data-source-private-b"
Tier = "Private"
}
}

data "aws_route_table_ids" "selected" {
vpc_id = "${aws_vpc.test.id}"
}

data "aws_route_table_ids" "private" {
vpc_id = "${aws_vpc.test.id}"
tags {
Tier = "Private"
}
}
`, rInt)
}

func testAccDataSourceAwsRouteTableIDsConfig(rInt int) string {
return fmt.Sprintf(`
resource "aws_vpc" "test" {
cidr_block = "172.%d.0.0/16"

tags {
Name = "terraform-testacc-route-table-ids-data-source"
}
}

resource "aws_route_table" "test_public_a" {
vpc_id = "${aws_vpc.test.id}"

tags {
Name = "tf-acc-route-table-ids-data-source-public-a"
Tier = "Public"
}
}

resource "aws_route_table" "test_private_a" {
vpc_id = "${aws_vpc.test.id}"

tags {
Name = "tf-acc-route-table-ids-data-source-private-a"
Tier = "Private"
}
}

resource "aws_route_table" "test_private_b" {
vpc_id = "${aws_vpc.test.id}"

tags {
Name = "tf-acc-route-table-ids-data-source-private-b"
Tier = "Private"
}
}
`, rInt)
}
1 change: 1 addition & 0 deletions aws/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ func Provider() terraform.ResourceProvider {
"aws_region": dataSourceAwsRegion(),
"aws_route": dataSourceAwsRoute(),
"aws_route_table": dataSourceAwsRouteTable(),
"aws_route_table_ids": dataSourceAwsRouteTableIDs(),
Copy link
Contributor

Choose a reason for hiding this comment

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

Sorry this is going to seem real pedantic, but can you please:

  • Rename the data source aws_route_tables along with the file names
  • Rename the functions to match, e.g. dataSourceAwsRouteTables() and dataSourceAwsRouteTablesRead()

This is mainly for future maintainability as the data source may be adjusted to return information other than just IDs. We unfortunately have some other _ids data sources (e.g. aws_subnet_ids) that will likely need to be renamed at some point. 😅

"aws_route53_zone": dataSourceAwsRoute53Zone(),
"aws_s3_bucket": dataSourceAwsS3Bucket(),
"aws_s3_bucket_object": dataSourceAwsS3BucketObject(),
Expand Down
44 changes: 44 additions & 0 deletions website/docs/d/route_table_ids.html.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
---
layout: "aws"
page_title: "AWS: aws_route_table_ids"
sidebar_current: "docs-aws-datasource-route-table-ids"
description: |-
Provides a list of route table Ids for a VPC
---

# Data Source: aws_route_table_ids

`aws_route_table_ids` provides a list of ids for a vpc_id

This resource can be useful for getting back a list of route table ids for a vpc.

## Example Usage

The following adds a route for a particular cidr block to every route table
in the vpc to use a particular vpc peering connection.

```hcl

data "aws_route_table_ids" "rts" {
vpc_id = "${var.vpc_id}"
}

resource "aws_route" "r" {
count = "${length(data.aws_route_table_ids.rts.ids)}"
route_table_id = "${data.aws_route_table_ids.rts.ids[count.index]}"
destination_cidr_block = "10.0.1.0/22"
vpc_peering_connection_id = "pcx-0e9a7a9ecd137dc54"
}

```

## Argument Reference

* `vpc_id` - (Required) The VPC ID that you want to filter from.

* `tags` - (Optional) A mapping of tags, each pair of which must exactly match
a pair on the desired route tables.

## Attributes Reference

* `ids` - A list of all the route table ids found. This data source will fail if none are found.