Terraform - 如何在 for_each 循环下递增变量?

问题描述 投票:0回答:1

我需要增加以下资源块中存在的每个数据项的优先级。例如:优先级=1,优先级=2等等。

resource "okta_app_group_assignments" "idc_app_assignments" {
    app_id   = okta_app_saml.aws_identity_center.id
    for_each = data.okta_groups.all_groups
    group {
       id       = each.value.groups.0.id
       priority = 1
    }
}

我无法使用索引函数,因为 data.okta_groups.all_groups 是一个对象并且不受支持。另外,尝试使用局部变量并在优先级下使用它,但它似乎不起作用。如果有什么方法可以实现,请告诉我。

    data "okta_groups" "all_groups" {
       for_each = {
          for okta_account in local.aws_okta_accounts : 
 "${okta_account.name}.${okta_account.role}.${okta_account.env_name}" => okta_account}
         q = "${each.value.name}-${each.value.env_name}#AWS#OKTA#${each.value.role}#${each.value.account_id}"
#example value for q - abc-dev#AWS#OKTA#dev#12345
}

example for data.okta_groups.all_groups: 
+ "abc.dev.qa"                           = {
      + groups = [
          + {
              + custom_profile_attributes = jsonencode({})
              + description               = ""
              + id                        = "00xxxxxxxxxxxxxb416"
              + name                      = "abc-qa#AWS#OKTA#dev#12345"
              + type                      = "OKTA_GROUP"
            },
        ]
      + id     = "987654"
      + q      = "abc-qa#AWS#OKTA#dev#12345"
      + search = null
      + type   = null
    }
terraform terraform-provider-aws okta
1个回答
0
投票

Terraform 地图不是有序的数据结构,因此“地图元素的索引”没有任何有意义的答案。

对于具有有意义的顺序的集合,列表是更合适的数据结构,因为它保留了定义元素的顺序。因此,我建议更改您的方法以使用列表而不是地图。

我无法展示适用于您现有配置的完整示例,因为您只包含了您所拥有的一小部分,但这里有一个更人为的示例,显示了希望您可以适应您的要求的原则:

variable "groups" {
  type = list(object({
    id = string
    # (and any other attributes you need)
  }))
}

resource "okta_app_group_assignments" "idc_app_assignments" {
  app_id   = okta_app_saml.aws_identity_center.id

  dynamic "group" {
    for_each = var.groups
    content {
      id       = group.value.id
      priority = group.key + 1
    }
  }
}

您的情况似乎需要一个具有多个

group
块的资源,而不是为每个组提供单独的资源,所以在这里我使用了
dynamic
来实现这一点。

dynamic
块允许在其
for_each
中收集任何类型,因为与
resource
for_each
不同,Terraform不需要单独跟踪每个块对于嵌套块,这是提供者的责任,提供者可以决定是否将块序列视为有序列表或某种其他类型的数据结构。

content
dynamic "group"
块内,
group.key
表示当前元素的键,并且由于
var.groups
是一个列表,因此本例中的“键”是列表元素索引。因此,
group.key
将是从零开始计数的整数,因此我添加了 1 以代替生成从 1 开始计数的整数。

group.value
是当前元素 value,类似于资源级别
each.value
for_each
,因此
group.value.id
是当前元素的
id
属性。


如果您did需要使用

resource
for_each
而不是
dynamic
块来执行此操作,那么这也是可能的,但它需要一个额外的步骤:Terraform无法使用资源级列表
for_each
因为这没有为 Terraform 提供足够的信息来决定资源的每个实例的跟踪键。

在这种情况下,典型的答案是使用

for
表达式 将列表投影到地图中,然后将其分配给
for_each
,如下所示:

resource "example" "example" {
  for_each = tomap({
    for idx, group in var.groups : group.id => merge(
      group,
      { priority = idx + 1 },
    )
  })

  # ...
}

for
表达式生成一个映射,其中给定列表的每个元素都有一个元素,并将其切换为通过其
id
属性而不是索引来标识每个元素。

但是仍然需要索引来决定优先级,因此

merge
调用为每个对象添加了一个额外的
priority
属性,然后该属性可用作
each.value.priority
块中的其他参数。
    

© www.soinside.com 2019 - 2024. All rights reserved.