# #terraform #nested-loops #terraform-provider-gitlab
Вопрос:
Описание
У меня следующая структура ввода (*.tfvars.json)
{ "projects":[ { "name":"Project 1", "gitlab":{ "variables":[ { "name":"Variable 1", "value":"Value 1" } ] } } ] }
Анализируется в следующую переменную tf:
variable "projects" { type = list( object({ name = string gitlab = object({ variables = list( object({ name = string value = string }) ) }) }
количество проектов, а также количество переменных в каждом проекте могут варьироваться, поэтому они определяются как списки.
Сначала я создаю проекты (поставщик gitlab) с помощью простого мета-параметра «количество» :
resource "gitlab_project" "projects" { count = length(var.projects) name = var.projects[count.index].name (...) }
но тогда я изо всех сил пытаюсь создать переменные проектов.
Вопрос
Использование «подсчета» не будет работать, так как оно не поддерживает вложенность;
поэтому другой подход, который я нашел, состоял в том, чтобы использовать для каждого цикла.
Я выровнял карту:
locals { project_variables = flatten([ for project in var.projects : [ for variable in project.gitlab.variables : { project_name = project.name variable = variable } ] ]) }
но это все равно ничего мне не дает, так как я не вижу возможности получить созданный идентификатор проекта с использованием уникальных атрибутов (например, имени), а идентификатор проекта требуется для создания переменного ресурса:
resource "gitlab_project_variable" "project_variables" { project = gitlab_project.projects[...].id key = "" value = "" }
Это действительно кажется достаточно простым требованием (просто вложенный цикл, который использует первый итератор цикла в качестве индекса для извлечения идентификатора проекта), но решения, которые я нахожу, либо не охватывают этот конкретный случай (с неопределенным/переменным числом аргументов в циклах), либо чрезмерно сложны…
Не могли бы вы, ребята, поделиться тем, как бы вы подошли к такой проблеме с новичком в терраформировании?
Комментарии:
1. * Я знаю, что технически ресурс «gitlab_project_variable» может получать имя проекта в качестве атрибута «проект», но почему — то это не работает для моего экземпляра GitLab — /api/v4/проекты/{идентификатор} работает, а /api/v4/проекты/{имя} — нет.
Ответ №1:
Вы правы, вы должны сгладить свои projects
, но по-другому:
variable "projects" { type = list( object({ name = string gitlab = object({ variables = list( object({ name = string value = string }) ) }) })) default = [ { "name":"Project 1", "gitlab":{ "variables":[ { "name":"Variable 1", "value":"Value 1" } ] } }, { "name":"Project 2", "gitlab":{ "variables":[ { "name":"Variable 2", "value":"Value 2" }, { "name":"Variable 3", "value":"Value 3" } ] } }, ] } locals { project_names = distinct([for project in var.projects: project.name]) project_variables = merge([ for project in var.projects: { for variable in project["gitlab"]["variables"]: "${project.name}-${variable.name}" =gt; { project_name = project["name"] var_name = variable.name var_value = variable.value } } ]...) # do NOT remove the dots }
что даст:
project_variables = { "Project 1-Variable 1" = { "project_name" = "Project 1" "var_name" = "Variable 1" "var_value" = "Value 1" } "Project 2-Variable 2" = { "project_name" = "Project 2" "var_name" = "Variable 2" "var_value" = "Value 2" } "Project 2-Variable 3" = { "project_name" = "Project 2" "var_name" = "Variable 3" "var_value" = "Value 3" }
затем:
resource "gitlab_project" "projects" { for_each = toset(local.project_names) name = each.key (...) } resource "gitlab_project_variable" "project_variables" { for_each = local.project_variables project = gitlab_project.projects[each.value.project_name].id key = each.value.var_name value = each.value.var_value }
Комментарии:
1. Спасибо @Marcin, я начинаю понимать. И просто продолжение: если в объекте «проект» есть больше данных, кроме имени (описание и т. Д.); вы бы изменили набор на карту с именем в качестве ключа и другим объектом с остальными данными в качестве значения? Или есть какое-то лучшее решение?
2. @jarobar435 Я бы расширил внутреннюю карту, как я это сделал
project_name
. Также могут быть возможны другие, более автоматизированные способы, такие какmerge
. В любом случае, попробуйте, что сможете, и если вы застряли, пожалуйста, задайте новый вопрос. Кроме того, если бы мой ответ был полезен, мы были бы признательны за его принятие.