Terraform 地图列表中的地形循环

Terraform 地图列表中的地形循环,terraform,terraform-provider-azure,Terraform,Terraform Provider Azure,我有一个Terraform模块,可以生成地图输出列表: object_ids = [ { "object_id" = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx" "upn" = "john@domain.com" "user" = "john" }, { "object_id" = &qu

我有一个Terraform模块,可以生成地图输出列表:

object_ids = [
  {
    "object_id" = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx"
    "upn" = "john@domain.com"
    "user" = "john"
  },
  {
    "object_id" = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx"
    "upn" = "martin@domain.com"
    "user" = "martin"
  },
]
使用for_each,我可以循环一个值来构建此资源:

resource "azurerm_role_assignment" "subread" {
    for_each = toset(module.user.map_object_ids[*].object_id)
    scope                = data.azurerm_subscription.primary.id
    role_definition_name = "Reader"
    principal_id         = each.value
}
但是,我不知道如何循环多个值

我对另一个需要输出2个不同值的资源尝试了以下操作:

resource "azurerm_role_assignment" "contribrg" {
    scope                = [for map in module.user.map_object_ids[*]: "${data.azurerm_subscription.primary.id}/resourceGroups/${lookup(map,"user")}"]
    role_definition_name = "Contributor"
    principal_id         = [for map in module.user.map_object_ids[*]: lookup(map,"object_id")]
}
出现以下错误:

Error: Incorrect attribute value type
module.user.map_object_ids is tuple with 2 elements
Inappropriate value for attribute "scope": string required.
Inappropriate value for attribute "principal_id": string required.

resource
对每个
的一个基本要求是,您使用的集合必须在每个要创建的实例中有一个元素,因此不可能基于多个值重复,但幸运的是,我认为这并不是您在这里要求的

相反,似乎您希望为
module.user.map\u object\u id
的每个元素都有一个实例,因此我们需要处理的唯一附加问题是
for\u each
希望得到一个对象映射,而不是对象列表,因此它可以使用映射键作为每个实例的标识符

我们可以通过使用将对象列表转换为对象映射,不过我们需要标识嵌套对象的一个属性,该属性将用作每个元素的唯一键。我将在这里使用
user
,因为它似乎是一个很好的人类理解的、配置选择的唯一标识符:

resource "azurerm_role_assignment" "contribrg" {
  for_each = { for obj in module.user.map_object_ids : obj.user => obj }

  scope                = "${data.azurerm_subscription.primary.id}/resourceGroups/${each.value.user}"
  role_definition_name = "Contributor"
  principal_id         = each.value.object_id
}
上面的
for
表达式将对象列表投影到对象地图中,如下所示:

{
  "john" = {
    "object_id" = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx"
    "upn" = "john@domain.com"
    "user" = "john"
  }
  "martin" = {
    "object_id" = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx"
    "upn" = "martin@domain.com"
    "user" = "martin"
  }
}
然后在资源参数表达式中,
each.key
将引用用户名(因为它们现在是键),而
each.value
将引用对象,因此我们可以使用
each.value.object\u id
来获取相应的对象标识符

由此,Terraform将计划创建具有以下地址的资源实例:

  • azurerm\u角色分配。contribrg[“john”]
  • azurerm\u角色分配。contribrg[“martin”]


旁注:我发现输出名为
object\u ids
有点令人困惑,因为它不仅仅返回id。将其命名为
objects

可能会更清晰。非常感谢Martin对解决方案的详细解释。