【问题标题】:Terraform for each loop or for loop not working每个循环或 for 循环的 Terraform 不起作用
【发布时间】:2020-07-11 09:57:02
【问题描述】:

我正在尝试为多个服务主体设置 azure 容器注册表的角色

variable "custom_role_list" {

  type        = list(object ({ service_principal_id = string, role = string }) )

} 

当我尝试从资源模块设置它时,我不确定这是正确的方法吗?

resource "azurerm_role_assignment" "ad_sp_role_assignment" {

  scope                = azurerm_container_registry.acr.id
  for_each = var.custom_role_list
  role_definition_name           = each.value.role
  principal_id = each.value.service_principal_id

}

基本上我正在尝试将 azure 容器注册表设置为与具有特定访问角色的多个服务主体一起使用。

以下是 var 定义。

custom_role_list = [
    {
        service_principal_id = aserviceprincipal.id
        role = "Contributor"
    },

    {
        service_principal_id = bserviceprincipal.id
        role = "Contributor"
    }


]

当我执行它时,我得到以下错误。

Error: Invalid for_each argument

  on ../modules/az-acr/main.tf line 46, in resource "azurerm_role_assignment" "ad_sp_role_assignment":
  46:   for_each = var.custom_role_list

The given "for_each" argument value is unsuitable: the "for_each" argument
must be a map, or set of strings, and you have provided a value of type list
of object.

如果有人可以指导将非常有帮助。谢谢!

【问题讨论】:

    标签: terraform terraform-provider-azure terraform0.12+


    【解决方案1】:

    正如错误提示,for_each 仅在与资源一起使用时支持地图和集合。您正在尝试使用对象列表。

    相反,也许您的变量可以是简单的map 类型,其中每个服务原则是一个键,其对应的角色是值。例如:

    variable "custom_role_list" {
      type        = map
    }
    

    变量定义:

    custom_role_map = {
      aserviceprincipal.id = "Contributor"
      bserviceprincipal.id = "Contributor"
    }
    

    最后使用for_each:

    resource "azurerm_role_assignment" "ad_sp_role_assignment" {
      for_each = var.custom_role_map
    
      scope                    = azurerm_container_registry.acr.id
      role_definition_name     = each.value
      principal_id             = each.key
    }
    

    您可能会找到 this blog post 来帮助您在 Terraform 中使用循环和条件。

    【讨论】:

    • 是的,我想到了,我使用 count 它对对象列表有很好的实现。
    • 正如我链接的博客文章中提到的,将 count 与列表一起使用的缺点是,如果您从列表中间删除一个项目,它将导致所有其他资源都有一个新索引,并且 Terraform 将要删除并重新创建它们。我建议您尝试使用map 来避免这种情况。
    • 在我目前的情况下,我不能不改变要求。即提供的输入,custom_role_list。
    【解决方案2】:

    您可以通过将代码调整为以下内容,对对象列表使用for_each 循环:

    variable "custom_role_list" {
      type = list(object({
        service_principal_id = string
        role  = string 
      }))
      default = [
        {
            service_principal_id= "27d653c-aB53-4ce1-920",
            role  = "Contributor"
        },
         {
            service_principal_id= "57d634c-aB53-4ce1-397",
            role  = "Contributor"
        }
      ]
    }
        
    resource "azurerm_role_assignment" "ad_sp_role_assignment" {
    
    for_each = {for sp in var.custom_role_list: sp.service_principal_id => sp}
        
    scope                    = azurerm_container_registry.acr.id
    role_definition_name     = each.value.service_principal_id 
    principal_id             = each.value.role 
    }
    

    【讨论】:

      猜你喜欢
      • 2014-08-21
      • 1970-01-01
      • 2015-10-18
      • 2019-12-21
      • 2017-04-13
      • 2013-12-31
      • 2020-03-30
      • 2018-08-21
      • 2018-06-12
      相关资源
      最近更新 更多