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

provider/aws: data source for AWS Route Table #10301

Closed

Conversation

mathieuherbert
Copy link
Contributor

Hi,

I added an AWS provider, aws_route_table.
We can retrieve, for example a route table from a subnet id and add a route with this route table

variable "subnet_id" {}

data "aws_route_table" "selected" {
  subnet_id = "${var.subnet_id}"
}

resource "aws_route" "route" {
  route_table_id = "${data.aws_route_table.selected.id}"
  destination_cidr_block = "10.0.1.0/22"
  vpc_peering_connection_id = "pcx-45ff3dc1"
}

Tests:

/opt/gopath/src/github.com/hashicorp/terraform$ TF_ACC=true go test -trace /tmp/toto.txt -v github.com/hashicorp/terraform/builtin/providers/aws -run ^TestAccDataSourceAwsRouteTable$
=== RUN   TestAccDataSourceAwsRouteTable
--- PASS: TestAccDataSourceAwsRouteTable (46.92s)
PASS
ok  	github.com/hashicorp/terraform/builtin/providers/aws	46.966s

Read: dataSourceAwsRouteTableRead,

Schema: map[string]*schema.Schema{
"subnet_id": &schema.Schema{
Copy link
Contributor

Choose a reason for hiding this comment

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

As of Go 1.7+ the explicit type is no longer needed here, so &schema.Schema can be removed.

Schema: map[string]*schema.Schema{
"subnet_id": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Copy link
Contributor

Choose a reason for hiding this comment

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

I am not sure if this should be optional? It seem that rest of the attributes are also optional, is this desirable?

Copy link
Contributor

Choose a reason for hiding this comment

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

Is this ever going to be empty? Given the first req.Filters getting some minimal filters.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think we can get a Route Table with

  • subnet_id
  • tags
  • vpc_id and tags
  • filters
    What do you think ?

rt := resp.RouteTables[0]

d.SetId(*rt.RouteTableId)
d.Set("id", *rt.RouteTableId)
Copy link
Contributor

Choose a reason for hiding this comment

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

The d.SetId() would set id, there is no need to have it explicitly set.

req.Filters = append(req.Filters, buildEC2CustomFilterList(
d.Get("filter").(*schema.Set),
)...)
if len(req.Filters) == 0 {
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this ever going to be empty? Given the first req.Filters getting some minimal filters.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I add an error if there is no filter

Copy link
Contributor

Choose a reason for hiding this comment

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

I see, so you want to use the sheer fact that buildEC2AttributeFilterList would return empty slice given that values in the map are empty. Which is fine, albeit it can be make a whole lot simpler should you break even before getting to this helper. You can do this as follows:

vpcId, vpcIdOk := d.GetOk("vpc_id")
subnetId, subnetIdOk := d.GetOk("subnet_id")

if !vpcIdOk && !subnetIdOk {
	return fmt.Errorf("One of vpc_id or subnet_id must be assigned")
}

req.Filters = buildEC2AttributeFilterList(
 	map[string]string{
		"vpc-id":                vpcId.(string),
		"association.subnet-id": subnetId.(string),
 	},
 )

@mathieuherbert
Copy link
Contributor Author

Hi @kwilczynski,
Thank you for your review :)
I think we can get a Route Table with

  • subnet_id
  • tags
  • vpc_id and tags
  • filters
    The subnet is just one of the possibilities. What do you think ?

},
"filter": ec2CustomFiltersSchema(),

"id": {
Copy link
Contributor

Choose a reason for hiding this comment

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

This is not needed (as per the earlier comment, you do not to set id explicitly - this is done via the d.SetId().

@kwilczynski
Copy link
Contributor

@mathieuherbert hi there! Thank you for your updates!

I see, you are allowing to set either and then narrow the result down with either tags or filters. Which is fine, but in such a case I would add a check whether at least one is set, and issue an appropriate message should that not be the case.

@kwilczynski
Copy link
Contributor

@mathieuherbert hi there again!

I was wondering, how would you feel about adding associations and routes too? It would be an additional computed attribute (a sub-schema, etc.). Would it be something you could consider? It would make this data source more feature complete.

@mathieuherbert
Copy link
Contributor Author

Hi @kwilczynski,

So now, I export every routesand associations from the route table. I hope it is the good way. I take some code from aws_route_table resource.

d.Set("vpc_id", rt.VpcId)
d.Set("tags", tagsToMap(rt.Tags))

routes := make([]map[string]interface{}, 0, len(rt.Routes))
Copy link
Contributor

Choose a reason for hiding this comment

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

Very nice! I think it might be better served as a function.

}
d.Set("routes", routes)

associations := make([]map[string]interface{}, 0, len(rt.Associations))
Copy link
Contributor

Choose a reason for hiding this comment

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

Same as above, if we turn this into a function it would be great.

return err
}
if resp == nil || len(resp.RouteTables) == 0 {
return fmt.Errorf("no matching Route Table found")
Copy link
Contributor

Choose a reason for hiding this comment

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

Check the Amazon AMI data source for an idea of more user-friendly error messages.


routes = append(routes, m)
}
d.Set("routes", routes)
Copy link
Contributor

Choose a reason for hiding this comment

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

When storing complex values, if would recommend adding an error check, for example:

if err := d.Set("routes", routes); err != nil {
    return err
}

@mathieuherbert
Copy link
Contributor Author

@kwilczynski , thank you very much for your help, it is very interesting !

@kwilczynski
Copy link
Contributor

@mathieuherbert thank you for working on it!

@mathieuherbert
Copy link
Contributor Author

@kwilczynski , do you have some comments on my last commit please ? Thanks !


d.SetId(*rt.RouteTableId)
d.Set("vpc_id", rt.VpcId)
d.Set("tags", tagsToMap(rt.Tags))
Copy link
Contributor

Choose a reason for hiding this comment

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

if err := d.Set("tags", tagsToMap(rt.Tags)); err != nil {
    return err
}

associations := make([]map[string]interface{}, 0, len(ec2Assocations))
// Loop through the routes and add them to the set
for _, a := range ec2Assocations {

Copy link
Contributor

Choose a reason for hiding this comment

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

No need for the extra line.

@kwilczynski
Copy link
Contributor

@mathieuherbert hi there! Looks good! Two minor comments, and then I think ready to go.

@stack72
Copy link
Contributor

stack72 commented Nov 28, 2016

% make testacc TEST=./builtin/providers/aws TESTARGS='-run=TestAccDataSourceAwsRouteTable'          ✹
==> Checking that code complies with gofmt requirements...
go generate $(go list ./... | grep -v /terraform/vendor/)
2016/11/28 18:02:00 Generated command/internal_plugin_list.go
TF_ACC=1 go test ./builtin/providers/aws -v -run=TestAccDataSourceAwsRouteTable -timeout 120m
=== RUN   TestAccDataSourceAwsRouteTable
--- PASS: TestAccDataSourceAwsRouteTable (21.16s)
PASS
ok  	github.com/hashicorp/terraform/builtin/providers/aws	21.199s

Massive thanks to @kwilczynski for all the work here!

@stack72
Copy link
Contributor

stack72 commented Nov 28, 2016

Merged manually :)

@stack72 stack72 closed this Nov 28, 2016
@mathieuherbert mathieuherbert deleted the routetable-datasource branch November 28, 2016 20:21

* `filter` - (Optional) Custom filter block as described below.

* `id` - (Optional) The id of the specific Route Table to retrieve.
Copy link
Contributor

Choose a reason for hiding this comment

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

Was this parameter implemented? I can't see any reference to it in data_source_aws_route_table.go and get this when I try to use it,

Errors:
  * data.aws_route_table.selected: : invalid or unknown key: id

@ghost
Copy link

ghost commented Apr 18, 2020

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues.

If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

@ghost ghost locked and limited conversation to collaborators Apr 18, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants