Terraform 循环:for_each
Terraform loop : for_each
我需要帮助 运行 for_each 在 terraform 上使用以下变量集
locals {
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"]]
db_type = ["CLUSTER", "CLUSTER", "CLUSTER"]
},
test_cluster2 = {
db_name = ["db_d", "db_e", "db_f"]
db_role = ["readWrite", "readWrite", "read"]
db_type = ["CLUSTER", "CLUSTER", "CLUSTER"]
}
}
}
db_type
两者都可以看情况。如果我们有多个 db_type 那么两个值都应该与最终资源相关联。
我还尝试了 flatten 变量
value = flatten([
for ip_key, ip in local.db_users : [
for a, b in ip : [
for index in range(length(b.db_name)) : {
username = ip_key
user_index = index
roles = {
role_name = b.db_role[index]
database_name = b.db_name[index]
}
scopes = {
type = b.db_type[index]
name = a
}
}
]
]
])
扁平化后的输出
[
{
"roles" = {
"database_name" = "db_a"
"role_name" = "readWrite"
}
"scopes" = {
"name" = "test_cluster1"
"type" = "CLUSTER"
}
"username" = "test_user1"
},
{
"roles" = {
"database_name" = "db_b"
"role_name" = "read"
}
"scopes" = {
"name" = "test_cluster1"
"type" = "CLUSTER"
}
"username" = "test_user1"
},
...
{
"roles" = {
"database_name" = "db_d"
"role_name" = "readWrite"
}
"scopes" = {
"name" = "test_cluster1"
"type" = "CLUSTER"
}
"username" = "test_user2"
},
{
"roles" = {
"database_name" = "db_e"
"role_name" = "readWrite"
}
"scopes" = {
"name" = "test_cluster1"
"type" = "CLUSTER"
}
"username" = "test_user2"
},
...
]
查看值的类型,如下
tuple([
object({
roles: object({
database_name: string,
role_name: string,
}),
scopes: object({
name: string,
type: string,
}),
username: string,
}),
...
object({
roles: object({
database_name: string,
role_name: string,
}),
scopes: object({
name: string,
type: string,
}),
username: string,
}),
])
问题:
我想达到什么目的???
- 我想从这个特定变量创建资源
负责此的资源如下。
在同一块中可以有尽可能多的 roles 和 scopes 。为此,我们可以为您提供动态块设置
resource "users" "user" {
username = var.username
roles {
database_name = var.database_name
role_name = var.role_name
}
roles {
database_name = var.database_name
role_name = var.role_name
}
...
scopes {
name = var.cluster
type = var.type
}
scopes {
name = var.cluster
type = var.type
}
...
}
资源最终应该类似于以下值。
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"
}
Resource No. 3
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. 4
username=test_user2
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"
}
使用了准确的源代码。 (我知道这是不正确的)。
这里 username
、database_name
、role_name
、name
和 type
都应该是一个字符串值
resource "users" "user" {
for_each = local.db_users
username = each.key
dynamic "roles" {
for_each = each.value
content {
database_name = each.value.db_name
role_name = each.value.db_role
}
}
dynamic "scopes" {
for_each = each.value
content {
name = each.key
type = each.value.db_type
}
}
}
错误
│ Error: Unsupported attribute
│
│ on database_users.tf line 25, in resource "mongodbatlas_database_user" "user":
│ 25: database_name = each.value.db_name
│ ├────────────────
│ │ each.value is object with 2 attributes
│
│ This object does not have an attribute named "db_name".
╷
│ Error: Unsupported attribute
│
│ on database_users.tf line 26, in resource "mongodbatlas_database_user" "user":
│ 26: role_name = each.value.db_role
│ ├────────────────
│ │ each.value is object with 2 attributes
│
│ This object does not have an attribute named "db_role".
╵
╷
│ Error: Unsupported attribute
│
│ on database_users.tf line 33, in resource "mongodbatlas_database_user" "user":
│ 33: type = each.value.db_type
│ ├────────────────
│ │ each.value is object with 2 attributes
│
│ This object does not have an attribute named "db_type".
╵
PS:考虑到上面的flatten value
没有用。如何使用相同的 db_users 内容解决此问题?
PPS:我也可以使用 flatten value
只要它符合我的目的。
您的 db_users
应该以不同的方式展平,即:
locals {
db_users_flat = merge([
for username, clusters in local.db_users :
{
for clustername, cluster in clusters :
"${username}-${clustername}" => {
username = username
clustername = clustername
cluster = cluster
}
}
]...) # please do NOT remove the dots
}
然后
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]
}
}
}
我需要帮助 运行 for_each 在 terraform 上使用以下变量集
locals {
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"]]
db_type = ["CLUSTER", "CLUSTER", "CLUSTER"]
},
test_cluster2 = {
db_name = ["db_d", "db_e", "db_f"]
db_role = ["readWrite", "readWrite", "read"]
db_type = ["CLUSTER", "CLUSTER", "CLUSTER"]
}
}
}
db_type
两者都可以看情况。如果我们有多个 db_type 那么两个值都应该与最终资源相关联。
我还尝试了 flatten 变量
value = flatten([
for ip_key, ip in local.db_users : [
for a, b in ip : [
for index in range(length(b.db_name)) : {
username = ip_key
user_index = index
roles = {
role_name = b.db_role[index]
database_name = b.db_name[index]
}
scopes = {
type = b.db_type[index]
name = a
}
}
]
]
])
扁平化后的输出
[
{
"roles" = {
"database_name" = "db_a"
"role_name" = "readWrite"
}
"scopes" = {
"name" = "test_cluster1"
"type" = "CLUSTER"
}
"username" = "test_user1"
},
{
"roles" = {
"database_name" = "db_b"
"role_name" = "read"
}
"scopes" = {
"name" = "test_cluster1"
"type" = "CLUSTER"
}
"username" = "test_user1"
},
...
{
"roles" = {
"database_name" = "db_d"
"role_name" = "readWrite"
}
"scopes" = {
"name" = "test_cluster1"
"type" = "CLUSTER"
}
"username" = "test_user2"
},
{
"roles" = {
"database_name" = "db_e"
"role_name" = "readWrite"
}
"scopes" = {
"name" = "test_cluster1"
"type" = "CLUSTER"
}
"username" = "test_user2"
},
...
]
查看值的类型,如下
tuple([
object({
roles: object({
database_name: string,
role_name: string,
}),
scopes: object({
name: string,
type: string,
}),
username: string,
}),
...
object({
roles: object({
database_name: string,
role_name: string,
}),
scopes: object({
name: string,
type: string,
}),
username: string,
}),
])
问题: 我想达到什么目的???
- 我想从这个特定变量创建资源
负责此的资源如下。 在同一块中可以有尽可能多的 roles 和 scopes 。为此,我们可以为您提供动态块设置
resource "users" "user" {
username = var.username
roles {
database_name = var.database_name
role_name = var.role_name
}
roles {
database_name = var.database_name
role_name = var.role_name
}
...
scopes {
name = var.cluster
type = var.type
}
scopes {
name = var.cluster
type = var.type
}
...
}
资源最终应该类似于以下值。
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"
}
Resource No. 3
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. 4
username=test_user2
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"
}
使用了准确的源代码。 (我知道这是不正确的)。
这里 username
、database_name
、role_name
、name
和 type
都应该是一个字符串值
resource "users" "user" {
for_each = local.db_users
username = each.key
dynamic "roles" {
for_each = each.value
content {
database_name = each.value.db_name
role_name = each.value.db_role
}
}
dynamic "scopes" {
for_each = each.value
content {
name = each.key
type = each.value.db_type
}
}
}
错误
│ Error: Unsupported attribute
│
│ on database_users.tf line 25, in resource "mongodbatlas_database_user" "user":
│ 25: database_name = each.value.db_name
│ ├────────────────
│ │ each.value is object with 2 attributes
│
│ This object does not have an attribute named "db_name".
╷
│ Error: Unsupported attribute
│
│ on database_users.tf line 26, in resource "mongodbatlas_database_user" "user":
│ 26: role_name = each.value.db_role
│ ├────────────────
│ │ each.value is object with 2 attributes
│
│ This object does not have an attribute named "db_role".
╵
╷
│ Error: Unsupported attribute
│
│ on database_users.tf line 33, in resource "mongodbatlas_database_user" "user":
│ 33: type = each.value.db_type
│ ├────────────────
│ │ each.value is object with 2 attributes
│
│ This object does not have an attribute named "db_type".
╵
PS:考虑到上面的flatten value
没有用。如何使用相同的 db_users 内容解决此问题?
PPS:我也可以使用 flatten value
只要它符合我的目的。
您的 db_users
应该以不同的方式展平,即:
locals {
db_users_flat = merge([
for username, clusters in local.db_users :
{
for clustername, cluster in clusters :
"${username}-${clustername}" => {
username = username
clustername = clustername
cluster = cluster
}
}
]...) # please do NOT remove the dots
}
然后
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]
}
}
}