I am trying to generate attributes dynamically in terraform 13. I've read through the docs but I can't seem to get this to work:
Given the following terraform:
#main.tf
locals {
secrets = {
secret1 = [
{
name = "user",
value = "secret"
},
{
name = "password",
value = "password123"
}
],
secret2 = [
{
name = "token",
value = "secret"
}
]
}
}
resource "kubernetes_secret" "secrets" {
for_each = local.secret
metadata {
name = each.key
}
data = {
[for name, value in each.value : name = value]
}
}
I would expect the following resources to be rendered:
resource "kubernetes_secret" "secrets[secret1]" {
metadata {
name = "secret1"
}
data = {
user = "secret"
password = "password123"
}
}
resource "kubernetes_secret" "secrets[secret2]" {
metadata {
name = "secret2"
}
data = {
token = "secret"
}
}
However I just get the following error:
Error: Invalid 'for' expression
on ../../main.tf line 96, in resource "kubernetes_secret" "secrets":
96: [for name, value in each.value : name = value]
Extra characters after the end of the 'for' expression.
Does anybody know how to make this work?
The correct syntax for generating a mapping using a for
expression is the following:
data = {
for name, value in each.value : name => value
}
The above would actually be totally redundant, because it would produce the same value as each.value
. However, because your local value has a list of objects with name
and value
attributes instead of maps from name to value, so to get a working result we'd either need to change the input to already be a map, like this:
locals {
secrets = {
secret1 = {
user = "secret"
password = "password123"
}
secret2 = {
token = "secret"
}
}
}
resource "kubernetes_secret" "secrets" {
for_each = local.secrets
metadata {
name = each.key
}
# each.value is already a map of a suitable shape
data = each.value
}
or, if the input being a list of objects is important for some reason, you can project from the list of objects to the mapping like this:
locals {
secrets = {
secret1 = [
{
name = "user",
value = "secret"
},
{
name = "password",
value = "password123"
}
],
secret2 = [
{
name = "token",
value = "secret"
}
]
}
}
resource "kubernetes_secret" "secrets" {
for_each = local.secrets
metadata {
name = each.key
}
data = {
for obj in each.value : obj.name => obj.value
}
}
Both of these should produce the same result, so which to choose will depend on what shape of local value data structure you find most readable or most convenient.