Sagar Jadhav
Sagar Jadhav

Reputation: 521

How to get string value from an array of string defined in json template using terraform

I am trying to create routes in Transit gateway route table using a json template. However, while fetching each string value from an array of string defined in json template, getting error as below;

Error: Incorrect attribute value type\n\n  on main.tf line 90, in resource \"aws_ec2_transit_gateway_route\" \"ip_route\":\n  90:   destination_cidr_block         = each.value.ip_network\n    |----------------\n    | each.value.ip_network is tuple with 3 elements\n\nInappropriate value for attribute \"destination_cidr_block\": string require

Here below is my code -->

resource "aws_ec2_transit_gateway_route" "ip_route" {
  for_each                       = jsondecode(file("templates/my.json"))
  destination_cidr_block         = each.value.ip_network
  transit_gateway_attachment_id  = "tgw-attach-123"
  transit_gateway_route_table_id = each.value.tgw_rt_id
}

json file -->

{
  
  "RT-1": {
    "tgw_rt_id": "tgw-rtb-00128",
    "ip_network": [ 
      "1.1.1.0/24",
      "1.1.2.0/24",
      "1.1.3.0/24"
    ]
    },

  "RT-2": {
    "tgw_rt_id": "tgw-rtb-01f1b",
    "ip_network": [ 
      "1.1.1.0/24",
      "1.1.2.0/24",
      "1.1.3.0/24"
    ]
    }
  
}

I am able to get the "destination_cidr_block" value as "string" if only single string is passed in "ip_network" (eg: "ip_network": "1.1.1.0/24") but failed to fetch when defined with array of string.

Upvotes: 1

Views: 778

Answers (1)

Jordan
Jordan

Reputation: 4512

As you've identified, the destination_cidr_block only accepts a single CIDR block (a string), not multiple CIDR blocks. You need to create a separate aws_ec2_transit_gateway_route for each CIDR block for each route table. You can do this by flattening the map so there's one element for each RT/CIDR combination.

locals {
  route_tables = jsondecode(file("templates/my.json"))
  rt_cidr_blocks = merge([
    for k, rt in local.route_tables:
    { 
      for i, ip_network in rt.ip_network:
      "${k}-${i}" => {
        tgw_rt_id = rt.tgw_rt_id
        ip_network = ip_network
      }
    }
  ]...)
}

resource "aws_ec2_transit_gateway_route" "ip_route" {
  for_each                       = local.rt_cidr_blocks
  destination_cidr_block         = each.value.ip_network
  transit_gateway_attachment_id  = each.key
  transit_gateway_route_table_id = each.value.tgw_rt_id
}

If you want to see what the flattened map looks like now:

output "rt_cidr_blocks" {
  value = local.rt_cidr_blocks
}

Output:

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

Outputs:

blocks = {
  "RT-1-0" = {
    "ip_network" = "1.1.1.0/24"
    "tgw_rt_id" = "tgw-rtb-00128"
  }
  "RT-1-1" = {
    "ip_network" = "1.1.2.0/24"
    "tgw_rt_id" = "tgw-rtb-00128"
  }
  "RT-1-2" = {
    "ip_network" = "1.1.3.0/24"
    "tgw_rt_id" = "tgw-rtb-00128"
  }
  "RT-2-0" = {
    "ip_network" = "1.1.1.0/24"
    "tgw_rt_id" = "tgw-rtb-01f1b"
  }
  "RT-2-1" = {
    "ip_network" = "1.1.2.0/24"
    "tgw_rt_id" = "tgw-rtb-01f1b"
  }
  "RT-2-2" = {
    "ip_network" = "1.1.3.0/24"
    "tgw_rt_id" = "tgw-rtb-01f1b"
  }
}

Upvotes: 3

Related Questions