Terraform динамически генерирует атрибуты (не блоки)

Я пытаюсь динамически генерировать атрибуты в terraform 13. Я прочитал документацию, но не могу заставить это работать:

Учитывая следующую терраформу:

#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]
  }
}

Я ожидаю, что будут отображены следующие ресурсы:

resource "kubernetes_secret" "secrets[secret1]" {
  metadata {
    name = "secret1"
  }

  data = {
    user     = "secret"
    password = "password123"
  }
}

resource "kubernetes_secret" "secrets[secret2]" {
  metadata {
    name = "secret2"
  }

  data = {
    token = "secret"
  }
}

Однако я получаю следующую ошибку:

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.

Кто-нибудь знает, как это сделать?


person Jamesla    schedule 12.11.2020    source источник
comment
Можете ли вы опубликовать полное сообщение об ошибке? Какое выражение недопустимо?   -  person Marcin    schedule 13.11.2020
comment
добавлен в вопрос   -  person Jamesla    schedule 13.11.2020


Ответы (1)


Правильный синтаксис для создания сопоставления с использованием выражения for следующий:

  data = {
    for name, value in each.value : name => value
  }

Вышеупомянутое будет фактически полностью избыточным, потому что оно даст то же значение, что и each.value. Однако, поскольку ваше локальное значение имеет список объектов с атрибутами name и value вместо сопоставления от имени к значению, поэтому для получения рабочего результата нам нужно либо изменить ввод, чтобы он уже был картой, например:

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
}

или, если вход, являющийся списком объектов, по какой-то причине важен, вы можете проецировать из списка объектов на сопоставление следующим образом:

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
  }
}

Оба они должны дать одинаковый результат, поэтому выбор будет зависеть от того, какую форму структуры данных локальных значений вы считаете наиболее читаемой или наиболее удобной.

person Martin Atkins    schedule 13.11.2020
comment
о да, конечно, спасибо за такую ​​отличную запись - все работает хорошо :-) - person Jamesla; 17.11.2020