Terraform循环: for_each for tuple

标签 terraform infrastructure-as-code

引用:original question Terraform loop : for_each

与问题类似,我有一些更改也需要使用相同的方法进行处理。

更改

db_type 的值可以介于这两者之间

db_type = [["CLUSTER", "LAKE"], ["CLUSTER", "LAKE"], ["CLUSTER", "LAKE"]]

OR

db_type = ["CLUSTER", "CLUSTER", "CLUSTER"]

在这种情况下,当我尝试使用相同的示例时(仅对 db_type 进行更改),按照 solution original question 观察到以下错误

╷
│ Error: Incorrect attribute value type
│
│   on database_users.tf line 143, in resource "user" "user":
│  143:       type = each.value.cluster.db_type[scopes.key]
│     ├────────────────
│     │ each.value.cluster.db_type is tuple with 3 elements
│
│ Inappropriate value for attribute "type": string required.
╵
╷
│ Error: Incorrect attribute value type
│
│   on database_users.tf line 143, in resource "user" "user":
│  143:       type = each.value.cluster.db_type[scopes.key]
│     ├────────────────
│     │ each.value.cluster.db_type is tuple with 3 elements
│
│ Inappropriate value for attribute "type": string required.
╵
╷
│ Error: Incorrect attribute value type
│
│   on database_users.tf line 143, in resource "user" "user":
│  143:       type = each.value.cluster.db_type[scopes.key]
│     ├────────────────
│     │ each.value.cluster.db_type is tuple with 3 elements
│
│ Inappropriate value for attribute "type": string required.

问题:我真正想要什么?我如何实现这一目标?

  • 如果我按照上面的说明更改 db_type 的值,结果应该如下
  # mongodbatlas_database_user.user["test_user2-test_cluster2"] will be created
  + resource "mongodbatlas_database_user" "user" {
      + auth_database_name = "admin"
      + aws_iam_type       = "NONE"
      + id                 = (known after apply)
      + ldap_auth_type     = "NONE"
      + password           = (sensitive value)
      + project_id         = "6216f27d3f350c275ea78efb"
      + username           = "test_user2"
      + x509_type          = "NONE"

      + labels {
          + key   = (known after apply)
          + value = (known after apply)
        }

      + roles {
          + collection_name = (known after apply)
          + database_name   = "db_d"
          + role_name       = "readWrite"
        }
      + roles {
          + collection_name = (known after apply)
          + database_name   = "db_e"
          + role_name       = "readWrite"
        }
      + roles {
          + collection_name = (known after apply)
          + database_name   = "db_f"
          + role_name       = "read"
        }

      + scopes {
          + name = "test_cluster2"
          + type = "CLUSTER"
        }
      + scopes {
          + name = "test_cluster2"
          + type = "LAKE"
        }
    }

如果 db_type 的值 = [["CLUSTER", "LAKE"], ["CLUSTER", "LAKE"], ["CLUSTER", "LAKE"]],则 < strong>预期输出应该是

Resource No. 1

username=test_user1
role = {
  db_name=db_a
  role=readWrite
}
role = {
  db_name=db_b
  role=read
}
role = {
  db_name=db_c
  role=readWrite
}
scope = {
  name = test_cluster1
  type = "cluster"
}
scope = {
  name = test_cluster1
  type = "lake"
}

Resource No. 2

username=test_user1
role = {
  db_name=db_d
  role=readWrite
}
role = {
  db_name=db_e
  role=read
}
role = {
  db_name=db_f
  role=readWrite
}
scope = {
  name = test_cluster2
  type = "cluster"
}
scope = {
  name = test_cluster2
  type = "lake"
}
...

如果 db_type = db_type = ["CLUSTER", "CLUSTER", "CLUSTER"] 的值,则预期输出应为

Resource No. 1

username=test_user1
role = {
  db_name=db_a
  role=readWrite
}
role = {
  db_name=db_b
  role=read
}
role = {
  db_name=db_c
  role=readWrite
}
scope = {
  name = test_cluster1
  type = "cluster"
}

Resource No. 2

username=test_user1
role = {
  db_name=db_d
  role=readWrite
}
role = {
  db_name=db_e
  role=read
}
role = {
  db_name=db_f
  role=readWrite
}
scope = {
  name = test_cluster2
  type = "cluster"
}
...

最佳答案

如果我理解正确的话,最好使用以下形式的db_users:

  db_users = {
    test_user1 = {      #user
      test_cluster1 = { #cluster
        db_name = ["db_a", "db_b", "db_c"]
        db_role = ["readWrite", "read", "readWrite"]
        db_type = [["CLUSTER"], ["CLUSTER"], ["CLUSTER"]]
      },
      test_cluster2 = {
        db_name = ["db_a", "db_b", "db_c"]
        db_role = ["readWrite", "read", "readWrite"]
        db_type = [["CLUSTER"], ["CLUSTER"], ["CLUSTER"]]
      }
    },
    test_user2 = {
      test_cluster1 = {
        db_name = ["db_d", "db_e", "db_f"]
        db_role = ["readWrite", "readWrite", "read"]
        db_type = [["CLUSTER", "LAKE"], ["CLUSTER", "LAKE"], ["CLUSTER", "LAKE"]]
      },
      test_cluster2 = {
        db_name = ["db_d", "db_e", "db_f"]
        db_role = ["readWrite", "readWrite", "read"]
        db_type = [["CLUSTER"], ["CLUSTER"], ["CLUSTER"]]
      }
    }
  }

然后你展平为:

  
  db_users_flat = merge(flatten([
    for username, clusters in local.db_users : 
      [
         for clustername, cluster in clusters : 
         {
             for idx, db_types in cluster.db_type: 
                 "${username}-${clustername}-${idx}" => {
                       username = username
                       clustername = clustername
                       cluster = {
                         db_name = cluster.db_name
                         db_role = cluster.db_role
                         db_type = db_types
                       }
                  }
               }
       ]
  ])...)

并用作:

resource "users" "user" {
    for_each = local.db_users_flat
    username = each.value.username
    dynamic "roles" {
      for_each = range(length(each.value.cluster.db_name))
      content {
        database_name = each.value.cluster.db_name[roles.key]
        role_name     = each.value.cluster.db_role[roles.key]
      }
    }
    dynamic "scopes" {
      for_each = range(length(each.value.cluster.db_type))
      content {
        name = each.value.clustername
        type = each.value.cluster.db_type[scopes.key]
      }
    }
}

关于Terraform循环: for_each for tuple,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71293523/

相关文章:

terraform - 如何在 terraform 模板文件中附加索引号

azure - 如何使用 terraform 使 azure 子网安装可重入?

amazon-web-services - AWS 模块中的 Terraform 条件

google-cloud-platform - 如何使用 terraform 停止 GCP vm 实例

azure - 当强制 NSG 与子网关联时,如何使应用服务虚拟网络快速连接

google-cloud-functions - trigger_topic 不适用于 terraform 资源 google_cloudfunctions_function

Terraform JSON 需要嵌套在 Azure Vnet 对象中的 Azure 子网才能拥有 ID,但不允许对其进行设置

azure - 在 Azure 中通过 Bicep 构建资源配置结构多环境的最佳实践

amazon-web-services - 适用于 IaC 的 AWS CDK 与 SDK

azure - 如何在 ARM Bicep 模板中添加条件?