Claudio Palmeira
Claudio Palmeira

Reputation: 31

Terraform - Iterate over a list generated from a for_each on a data block

UPDATE -> To all folks with this particular problem, I found the solution, it is at the end of this question.

UPDATE 2 -> The last solution that I presented here was WRONG, see the update at the end.

I am retrieving a list of cidr_blocks from a data block to use as a value on a aws_ec2_transit_gateway_route, but so far I have been unable to iterate through that list to get individual values and set it on the appropriate place. The important piece of my data_block.tf looks like this:

data "aws_vpc" "account_vpc" {
 provider = aws.dev
 count = "${length(data.aws_vpcs.account_vpcs.ids)}"
 id    = element(tolist(data.aws_vpcs.account_vpcs.ids), 0)
}

data "aws_subnet_ids" "account_subnets" {
 provider = aws.dev
 vpc_id   = element(tolist(data.aws_vpcs.account_vpcs.ids), 0)
}

data "aws_subnet" "cidrblocks" {
  provider = aws.dev
  for_each = data.aws_subnet_ids.account_subnets.ids
  id    = each.value
}

And the part where I intend to use it is this one, tgw_rt.tf:

resource "aws_ec2_transit_gateway_route" "shared-routes" {
 provider                      = aws.shared
 #count = length(data.aws_subnet.cidrblocks.cidr_block)
 #destination_cidr_block         = lookup(data.aws_subnet.cidrblocks.cidr_block[count.index], element(keys(data.aws_subnet.cidrblocks.cidr_block[count.index]),0), "127.0.0.1/32")
 #destination_cidr_block          = data.aws_subnet.cidrblocks.cidr_block[count.index]
 #destination_cidr_block          = [data.aws_subnet.cidrblocks.*.cidr_block]
 destination_cidr_block          = [for s in data.aws_subnet.cidrblocks : s.cidr_block]
 /* for_each                         = [for s in data.aws_subnet.cidrblocks: {
   destination_cidr_block         = s.cidr_block
  }] */
 #destination_cidr_block         = [for s in data.aws_subnet.cidrblocks : s.cidr_block]
 #destination_cidr_block         = data.aws_subnet.cidrblocks.cidr_block[count.index]
 transit_gateway_attachment_id  = aws_ec2_transit_gateway_vpc_attachment.fromshared.id
 transit_gateway_route_table_id = aws_ec2_transit_gateway_route_table.shared.id
}

The part in comments is what I have tried so far and nothing worked. The error that is happening currently when using that uncommented part is

Error: Incorrect attribute value type

  on modules/tgw/tgw_rt.tf line 20, in resource "aws_ec2_transit_gateway_route" "shared-routes":
  20:  destination_cidr_block          = [for s in data.aws_subnet.cidrblocks : s.cidr_block]
    |----------------
    | data.aws_subnet.cidrblocks is object with 3 attributes

Inappropriate value for attribute "destination_cidr_block": string required.

I would really appreciate it if one of the terraform gods present here could shed some light on this problem.

SOLUTION - THIS IS WRONG Since it was complaining about it being an object with 3 attributes (3 Cidr blocks), to iterate i had to use this:

destination_cidr_block          = element([for s in data.aws_subnet.cidrblocks : s.cidr_block], 0)

CORRECT SOLUTION The solution was to add a small part to @kyle suggestion, I had to use an object to represent the data and convert it to a map, you rock @kyle:

for_each                         = {for s in data.aws_subnet.cidrblocks: s.cidr_block => s}
destination_cidr_block           = each.value.cidr_block

Thank you all in Advance

Upvotes: 2

Views: 6872

Answers (1)

user11714757
user11714757

Reputation:

I haven't used data.aws_subnet, but I think you were close with your for_each attempt-

resource "aws_ec2_transit_gateway_route" "shared-routes" {
...
 for_each                = [for s in data.aws_subnet.cidrblocks: s.cidr_block]
 destination_cidr_block  = each.value
...
}

Upvotes: 2

Related Questions