Home > Software engineering >  JSON iteration on Terraform
JSON iteration on Terraform

Time:12-01

Trying to create a simple VPC and a Subnet by iterating over a JSON file to Terraform code.

I already figured most of it out.. the only variable missing is the cidr_block for my subnet, How do i approach this?

{
    "vpc1" : {
    "name": "first-vpc",
    "cidr": "192.168.0.0/16",
    "subnets" :[
    {"name":"subnet-one", "cidr": "192.168.1.0/24"}, {"name":"subnet-two", "cidr":
    "192.168.4.0/24"}
    ]
    },
    "vpc2" : {
    "name": "second-vpc",
    "cidr": "172.16.0.0/16",
    "subnets" :[
    {"name":"subnet-three", "cidr": "172.16.1.0/24"}, {"name":"subnet-four", "cidr":
    "172.16.7.0/24"}
    ]
    }
}

resource "aws_vpc" "main" {
  for_each = { for index, vm in local.json : vm.name => vm }

  cidr_block = each.value.cidr

  tags = {
    Name = each.value.name
  }
}

resource "aws_subnet" "main" {
  for_each = { for key, map in local.json : key => map.subnets }

  vpc_id     = each.key
  cidr_block = each.value
}

Terraform console output :

> { for key, map in local.json : key => map.subnets }
{
  "vpc1" = [
    {
      "cidr" = "192.168.1.0/24"
      "name" = "subnet-one"
    },
    {
      "cidr" = "192.168.4.0/24"
      "name" = "subnet-two"
    },
  ]
  "vpc2" = [
    {
      "cidr" = "172.16.1.0/24"
      "name" = "subnet-three"
    },
    {
      "cidr" = "172.16.7.0/24"
      "name" = "subnet-four"
    },
  ]
}

Error message

Error: Incorrect attribute value type
│
│   on main.tf line 15, in resource "aws_subnet" "main":
│   15:   cidr_block = each.value
│     ├────────────────
│     │ each.value is tuple with 2 elements
│
│ Inappropriate value for attribute "cidr_block": string required.

Followed this documentation

@Cloudkollektiv Thanks for the instructions

CodePudding user response:

You have to flatten your json structure. For example:


locals {  
  json_flat = merge([
    for vpc in local.json: {
      for subnet in vpc.subnets:
      "${vpc.name}-${subnet.name}" => {
        vpc_name = vpc.name
        vpc_cidr = vpc.cidr
        subnet_name = subnet.name
        subnet_cidr = subnet.cidr
      }
    }
  ]...) 
}

then


resource "aws_vpc" "main" {
  for_each = { for index, vm in local.json : vm.name => vm }

  cidr_block = each.value.cidr

  tags = {
    Name = each.value.name
  }
}



resource "aws_subnet" "main" {
  for_each = local.json_flat

  vpc_id     = aws_vpc.main[each.value.vpc_name].id
  cidr_block = each.value.subnet_cidr
}
  • Related