【问题标题】:Output for Principal ID for multiple Azure App Services through Terraform通过 Terraform 输出多个 Azure 应用服务的主体 ID
【发布时间】:2020-05-09 13:43:54
【问题描述】:

使用: Terraform v0.12.6 + provider.azurerm v1.37.0

我正在通过 Terraform 创建多个 Azure 应用服务,并添加了标识块以使该应用成为 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 我们可以通过以下方式将 App 的 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 plan 时,我收到此错误:

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 指的是什么。请帮忙。

【问题讨论】:

  • 您的错误信息暗示var.apiName 是一个空字符串。
  • 您需要提供更多您使用的 Terraform 代码。比如变量apiName的定义。
  • 焦点不在var.apiName上,你可以在里面放随机值。我需要有关错误消息的帮助。
  • 经测试,问题不在输出设置或应用服务设置。

标签: azure azure-web-app-service terraform terraform-provider-azure


【解决方案1】:

当我们在表达式中引用 identity 块时,Azure 提供程序似乎将它表示为一个列表。知道了这一点,我们可以编写一个表达式,通过访问所有应用服务实例中的所有 identity 块来生成一个简单的原则 id 列表,这是两级列表:

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 ... : ... ] 表达式通过访问给定列表的每个元素(在本例中为前一个表达式的结果)并评估 : 之后的表达式(结果表达式 em>) 反对它。因为这是一个对象列表的列表,所以结果表达式中的identity 是一个对象列表。
  • identity[*].principal_id 检索代表identity 块的每个对象的principal_id 属性,再次生成结果列表。在这种情况下,因为principal_id 是一个字符串属性,所以结果是一个字符串列表。
  • flatten(...) 函数处理我们的for .... 表达式将返回一个字符串列表列表这一事实。 flatten 通过丢弃中间列表嵌套将结果转换为字符串的平面列表。结果是所有应用服务实例中所有identity 中的所有principal_id 值。

这与您的问题没有直接关系,但请注意,使用下划线分隔的单词命名对象是 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
  ])
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-18
    • 1970-01-01
    • 1970-01-01
    • 2022-11-26
    相关资源
    最近更新 更多