Наследование значений из output.tf с условными ресурсами с использованием TF 0,12+ - PullRequest
0 голосов
/ 24 апреля 2020

У меня есть модуль для служебных учетных записей в GCP, который используется для заполнения секретов kubernetes

Вот мой модуль

resource "google_service_account" "service_account" {
  count        = var.enabled ? 1 : 0
  account_id   = var.account_id
  display_name = var.display_name
}

resource "google_project_iam_member" "service_account_roles" {
  count  = var.enabled ? length(var.roles) : 0
  role   = "roles/${element(var.roles, count.index)}"
  member = "serviceAccount:${google_service_account.service_account[0].email}"
}

resource "google_service_account_key" "service_account_key" {
  count              = var.enabled ? 1 : 0
  service_account_id = google_service_account.service_account[0].name
}

'output.tf' содержит следующее

output "private_decoded_key" {
  value = base64decode(
    element(
      concat(
        google_service_account_key.service_account_key.*.private_key,
        [""],
      ),
      0,
    ),
  )
  description = "The base 64 decoded version of the credentials"
}

Поскольку существует условие, что ни один из этих ресурсов не создается без флага enabled, мне пришлось обрабатывать его в TF 0.11.14 таким образом, и инструмент автообновления tf0.12 не внес много изменений.

Как я могу упростить это в Terraform 0.12.24, я попытался изменить вывод просто на

value = base64decode(google_service_account_key.service_account_key[0].private_key)

Но проблема в том, что если соответствующий кластер kubernetes удаляется во время удаления, и на полпути есть ошибки, потому что terraform, я не смогу очистить состояние terraform остальных ресурсов, используя `terraform destroy '

Попытки преобразовать count в for_each, как показано ниже, дали мне следующие ошибки

resource "google_service_account" "service_account" {
  # count        = var.enabled ? 1 : 0
  for_each     = var.enabled ? 1 : 0
  account_id   = var.account_id
  display_name = var.display_name
}

resource "google_project_iam_member" "service_account_roles" {
  # count  = var.enabled ? length(var.roles) : 0
  for_each = var.enabled ? toset(var.roles) : 0
  # role   = "roles/${element(var.roles, count.index)}"
  role     = "roles/${each.value}" 
  member   = "serviceAccount:${google_service_account.service_account[0].email}"
}
for_each = var.enabled ? toset(var.roles) : 0

The true and false result expressions must have consistent types. The given
expressions are set of dynamic and number, respectively.

Что я не так делаю выше?

1 Ответ

1 голос
/ 25 апреля 2020

В упомянутой вами версии terraform (0.12.24) вы можете использовать try() в своем outputs.tf:

value = try(base64decode(google_service_account_key.service_account_key[0].private_key), "")

По умолчанию это будет "" если google_service_account_key.service_account_key[0].private_key невозможно решить по любой причине; Вы также можете по умолчанию null.

Редактировать / обновить : Чтобы ответить на вторую (отредактированную) часть вопроса:

Чтобы избавиться от ошибки что обе стороны должны иметь одинаковый тип, вам нужно использовать [] как пустой набор вместо 0 при преобразовании в for_each:

for_each = var.enabled ? toset(var.roles) : []

Пожалуйста, обратите внимание на существующую инфраструктуру, так как вы необходимо манипулировать файлом состояния при преобразовании из count в for_each, иначе terraform попытается уничтожить и создать ресурсы.

(я расскажу об этом более подробно в части 3 серии рассказов, которые я В настоящее время мы работаем над тем, как писать модули terraform. Вы можете найти часть 1 на носителе , а часть 2 будет выпущена на следующей неделе.)

...