Terraform 循环:for_each 元组

Terraform loop : for_each for tuple

参考:

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

变化

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

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

OR

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

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

╷
│ 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.

问题:我到底想要什么?我该如何实现?

  # 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"]] 的值,预期输出 应该是

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]
      }
    }
}