Вывод идентификатора участника для нескольких Azure сервисов приложений через Terraform - PullRequest
1 голос
/ 23 января 2020

Использование: Terraform v0.12.6 + provider.azurerm v1.37.0

Я создаю несколько Azure служб приложений через Terraform и добавляю идентификационный блок, чтобы приложение стало AD Приложение.

resource "azurerm_app_service" "apiApp" {
  count               = "${length(var.apiName)}"
  name                = "${var.apiName[count.index]}-${var.environment}"
  .
  .
  .

  identity  {
    type  = "SystemAssigned"
  }
}

Согласно документации Terraform, https://www.terraform.io/docs/providers/azurerm/r/app_service.html#principal_id мы можем экспортировать идентификатор участника приложения в файле output.tf:

${azurerm_app_service.apiApp.identity.0.principal_id}

Так как в этом случае у нас есть несколько служб приложений, я написал это в файле output.tf:

output "ApiAppPrincipalId" {
  value = "${azurerm_app_service.apiApp.*.identity.0.principal_id}"
}

Когда я выполняю план terraform , я получаю эту ошибку:

Error: Invalid index

  on modules\app-service\output.tf line 10, in output "ApiAppPrincipalId":
  10:   value = "${azurerm_app_service.apiApp.*.identity.0.principal_id}"

The given key does not identify an element in this collection value.

Также я не уверен, что означает 0. Пожалуйста, помогите.

1 Ответ

0 голосов
/ 24 января 2020

Похоже, что поставщик Azure представляет этот блок identity в виде списка, когда мы ссылаемся на него в выражениях. Зная это, мы можем написать выражение, которое генерирует плоский список основных идентификаторов, посещая все блоки identity во всех экземплярах службы приложения, что составляет два уровня списка:

output "ApiAppPrincipalId" {
  value = flatten([
    for identity in azurerm_app_service.apiApp[*].identity : identity[*].principal_id
  ])
}

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

  • azurerm_app_service.apiApp[*].identity извлекает атрибут identity для каждого из экземпляров службы приложения, создавая список результатов. Как отмечалось выше, блок identity представляется в виде списка, поэтому результатом этого выражения является список списков объектов , описывающий содержимое каждого блока identity.
  • Выражение [ for ... : ... ] создает новый список, посещая каждый элемент данного списка (в данном случае, результат предыдущего выражения) и оценивая выражение после : (выражение результата ) против этого. Поскольку это список списков объектов, identity в результирующем выражении является списком объектов.
  • identity[*].principal_id возвращает атрибут principal_id каждого из объектов, представляющих блоки identity, снова составление списка результатов. В этом случае, поскольку principal_id является строковым атрибутом, результатом является список строк.
  • Функция flatten(...) имеет дело с тем фактом, что только наше выражение for .... вернет список списков строки. flatten преобразует этот результат в плоский список строк, отбрасывая вложенность промежуточного списка. В результате получаются все значения principal_id для всех identity во всех экземплярах службы приложения.

Это не имеет прямого отношения к вашему вопросу, но обратите внимание, что оно стиль idiomati c в Terraform для именования объектов, используя слова, разделенные подчеркиванием, например api_app_principal_id вместо ApiAppPrincipalId. Также принято использовать множественное имя для значения коллекции, например api_app_principal_ids вместо api_app_principal_id.

Конечно, именование здесь не влияет на функциональность Terraform, но использование согласованного именования может быть полезным, если вы смешиваете свои собственные модули Terraform с модулями, написанными другими людьми, и повышаете удобство использования ваших модулей для тех, кто уже знаком с Terraform, с тем, чтобы использовать его где-либо еще.

output "api_app_principal_ids" {
  value = flatten([
    for identity in azurerm_app_service.api_app[*].identity : identity[*].principal_id
  ])
}
...