Как условно добавить атрибут к тегу Dynami c? - PullRequest
0 голосов
/ 29 апреля 2020

в файле config.meta Я храню доступ к наборам данных Google BigQuery. Объект accesses представляет собой список словарей, где каждый словарь содержит роль в качестве первого элемента и элемента второго элемента (например, special_group или group_by_email), который изменяется в списке.

Моя цель - динамически применять доступ. Подход довольно прост, когда каждый словарь в списке accesses имеет один и тот же второй элемент (например, только special_group). Но как их применять динамически, зависит от имени / значения второго элемента?

# config.meta file
{
    "accesses": [
        {
            "role": "OWNER",
            "special_group": "projectOwners"
        },
        {
            "role": "READER",
            "group_by_email": "myemail@myemail.com"
        },
       ...
    ]
    ...
}

файл terraform:

resource "google_bigquery_dataset" "dataset" {
    dataset_id    = "${var.dataset}"
    location      = "${var.bq_region}"
    friendly_name = "${var.dataset}"

    dynamic "access" {
        # get accesses (list of dictionaries) from a file
        for_each = [for a in jsondecode(file("$config.meta"))["access"]: {
            role = a.role
            special_group = a.special_group
            # how to get special_group/group_by name conditionally?
            # like: if dictionary has the key 'special_group' create that variable
            # othervise create 'group_by_name'
        }]

        content {
            role = access.value.role
            special_group = access.value.special_group
            # how to get special_group/group_by name conditionally?
            # like: if the 'special_group' had been declared add 'special_group' to the access block
            # othervise add 'group_by_name'.
        }
    }

}

Как условно добавить атрибут в тег Dynami c?

Ответы [ 2 ]

2 голосов
/ 30 апреля 2020

Внутри блока конфигурации в Terraform пропуск необязательного аргумента и установка этого аргумента в null эквивалентны. Поскольку access является вложенным блоком, мы можем использовать его для написания выражений, которые условно устанавливают аргумент.

  dynamic "access" {
    # get accesses (list of dictionaries) from a file
    for_each = [for a in jsondecode(file("$config.meta"))["access"]: {
      role           = a.role
      special_group  = try(a.special_group, null)
      group_by_email = try(a.group_by_email, null)
    }]

    content {
      role           = access.value.role
      special_group  = access.value.special_group
      group_by_email = access.value.group_by_email
    }
  }

Сначала используется функция try , чтобы отсутствующий атрибут приведет к снижению значения null, а не к ошибке. Это означает, что результирующие объекты будут выглядеть примерно так:

[
  {
    "role": "OWNER",
    "special_group": "projectOwners",
    "group_by_name": null,
  },
  {
    "role": "READER",
    "special_group": null,
    "group_by_email": "myemail@myemail.com",
  },
]

Внутри блока content мы просто назначим все эти объекты напрямую. Те, которые null будут обрабатываться Terraform, как будто они вообще не установлены, из-за поведения, которое я описал ранее. (Обратите внимание, что поведение при обработке значения null как неустановленного не применяется при построении значений объекта: это специальное поведение только для прямых аргументов внутри блока.)

Это должно иметь такой же эффект, как если бы вы бы выписали следующие два access блока напрямую:

access {
  role          = "OWNER"
  special_group = "projectOwners"
}

access {
  role           = "READER"
  group_by_email = "myemail@myemail.com"
}
0 голосов
/ 29 апреля 2020
locals {
  items = fileexists("$config.meta") ? jsondecode(file("$config.meta")).accesses : []
  special_groups = [for v in local.items: v if lookup(v, "special_group", "") != ""]
  group_by_emails = [for v in local.items: v if lookup(v, "group_by_email", "") != ""]
}

Вы можете использовать несколько определений dynamic block

resource "google_bigquery_dataset" "dataset" {

  ...

  dynamic "access" {
    for_each = [for a in local.special_groups: {
      role = lookup(a, "role", "")
      special_group = lookup(a, "special_group", "")
    }]

    content {
      role          = access.value.role
      special_group = access.value.special_group
    }
  }

  dynamic "access" {

    for_each = [for a in local.group_by_emails: {
      role = lookup(a, "role", "")
      group_by_email = lookup(a, "group_by_email", "")
    }]

    content {
      role           = access.value.role
      group_by_email = access.value.group_by_email
    }
  }

}
...