Terraform newbie here.
I'd like to iterate a list using for_each, but it seems like the key and value are the same:
provider "aws" {
profile = "default"
region = "us-east-1"
}
variable "vpc_cidrs" {
default = ["10.0.0.0/16", "10.1.0.0/16"]
}
resource "aws_vpc" "vpc" {
for_each = toset(var.vpc_cidrs)
cidr_block = each.value
enable_dns_hostnames = true
tags = { Name = "Company0${each.key}" }
}
I'd like the tag Name to be "Name" = "Company01" and "Name" = "Company02" but according to terraform apply, I get:
"Name" = "Company010.0.0.0/16" and "Name" = "Company010.1.0.0/16"
What am I missing?
Found an easy solution using the index function:
tags = { Name = "Company0${index(var.vpc_cidrs, each.value) + 1}" }
There is also another way of achieving the wanted result without using index():
change the following three lines:
for_each = { for idx, cidr_block in var.vpc_cidrs: cidr_block => idx}
cidr_block = each.key
tags = { Name = format("Company%02d", each.value + 1) }
for_each will use a map of cidr_block to index mapping as returned by for cidr_block can then just use the each.key valuetags also use format() on each.value to have a two digit with leading zeros of the index
Full example will be:
provider "aws" {
profile = "default"
region = "us-east-1"
}
variable "vpc_cidrs" {
default = ["10.0.0.0/16", "10.1.0.0/16"]
}
resource "aws_vpc" "vpc" {
for_each = { for idx, cidr_block in var.vpc_cidrs: cidr_block => idx}
cidr_block = each.key
enable_dns_hostnames = true
tags = { Name = format("Company%02d", each.value + 1) }
}
When for_each is used with a set, each.key and each.value are the same.
To generate strings like "Company01", "Company02", etc., you need the index of each CIDR block in the list. One way to do this is to create a local map using a for expression like:
locals {
vpc_cidrs = {for s in var.vpc_cidrs: index(var.vpc_cidrs, s) => s}
}
resource "aws_vpc" "vpc" {
for_each = local.vpc_cidrs
cidr_block = each.value
enable_dns_hostnames = true
tags = { Name = "Company0${each.key}" }
}
As a bonus, you can use the format function to build the zero-padded name string:
resource "aws_vpc" "vpc" {
...
tags = { Name = format("Company%02d", each.key) }
}
You could use the count function and use the index to do this:
provider "aws" {
profile = "default"
region = "us-east-1"
}
variable "vpc_cidrs" {
type = list(string)
default = ["10.0.0.0/16", "10.1.0.0/16"]
}
resource "aws_vpc" "vpc" {
count = length(var.vpc_cidrs)
cidr_block = var.vpc_cidrs[count.index]
enable_dns_hostnames = true
tags = { Name = "Company0${count.index}" }
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With