作为对Terraform 0.12 nested for loops的跟踪。我试图从嵌套循环中产生一个对象,但惨不忍睹:(
您将如何制作:
Outputs:
association-list = {
"policy1" = "user1"
"policy2" = "user1"
"policy2" = "user2"
}
发件人:
iam-policy-users-map = {
"policy1" = [ "user1" ]
"policy2" = [ "user1", "user2" ]
}
我尝试了以下各种变化:
variable iam-policy-users-map {
default = {
"policy1" = [ "user1" ]
"policy2" = [ "user1", "user2" ]
}
}
locals {
association-map = merge({
for policy, users in var.iam-policy-users-map : {
for user in users : {
policy => user
}
}
})
output association-map {
value = local.association-map
}
到目前为止,成功率为零。只能根据变化获得以下信息:
错误:“ for”表达式无效。 “ for”表达式末尾的多余字符。
错误:缺少属性值。 期望的属性值,由等号(“ =”)引入。
错误:“ for”表达式无效。 构建对象时需要键表达式。
错误:缺少键/值分隔符。预期等号(“ =”) 标记属性值的开头。
作为参考,以下代码可以生成地图列表:
variable iam-policy-users-map {
default = {
"policy1" = [ "user1" ]
"policy2" = [ "user1", "user2" ]
}
}
locals {
association-list = flatten([
for policy, users in var.iam-policy-users-map : [
for user in users : {
user = user
policy = policy
}
]
])
}
output association-list {
value = local.association-list
}
输出:
association-list = [{ “ policy” =“ policy1” “ user” =“ user1”},{ “ policy” =“ policy2” “ user” =“ user1”},{ “ policy” =“ policy2” “ user” =“ user2”},]
答案 0 :(得分:0)
可以在https://github.com/hashicorp/terraform/issues/22263找到部分答案。 长话短说:这是一个愚蠢的尝试,地图不能包含重复的键。
但是,我仍然对理解如何从嵌套的for循环中生成一张地图的地图感兴趣。参见上面的第二个代码示例,生成地图列表。
编辑:上面链接的github问题上给出了完整的答案。
“(显然)这是一个无用的结构,但我想说明这是可能的:
locals {
association-list = {
for policy, users in var.iam-policy-users-map:
policy => { // can't have the nested for expression before the key!
for u in users:
policy => u...
}
}
}
Outputs:
association-list = {
"policy1" = {
"policy1" = [
"user1",
]
}
"policy2" = {
"policy2" = [
"user1",
"user2",
]
}
}
”
答案 1 :(得分:0)
我也能做这样的事情。分享这些 terraform 列表理解想法是否有助于其他人尝试变异以制作衍生地图。 (我最初通过这个错误 Invalid 'for' expression: Key expression is not valid when building a tuple.
发现了这个和上面链接的问题。
我的目标是让 tfstate 中的资源不成为列表,因为这些资源很难对它们进行 tfstate 操作...[0]
,...[1]
不清楚它们是什么资源。
我有一个这样的变量,它代表用户在某些 s3 存储桶中创建一些默认文件夹。
locals {
#really in a tfvars file
bucket_users =
"testuser-abc" = {
make_extra_dirs = ["this-dir", "that-dir-2"]
}
}
# Create extra folders for non-standard use cases per their configuration.
locals {
# This is the easy way to get an array of extra directories to create
# But, we don't want to create it or the `tfstate list` command shows non-helpful indices.
# e.g.
# aws_s3_bucket_object.loop_user_folders_extra_customized_folders["0"]
# aws_s3_bucket_object.loop_user_folders_extra_customized_folders["1"]
# aws_s3_bucket_object.loop_user_folders_extra_customized_folders["2"]
# So use the below trick
users_with_extra_dirs_flat = flatten([
for username, user_data in local.bucket_users : [
for extra_dir in user_data["make_extra_dirs"]: {
username = username,
extra_dir = extra_dir,
unique_key = format("%s--%s", username, extra_dir)
}
] if length(user_data["make_extra_dirs"]) > 0
])
# This is much easier to reason about as it creates nice `tfstate list`
# output in case we need to do any future refactorings.
# e.g.
# aws_s3_bucket_object.loop_user_folders_extra_customized_folders["testuser-abc--this-dir"]
# aws_s3_bucket_object.loop_user_folders_extra_customized_folders["testuser-abc--that-dir-2"]
users_with_extra_dirs_hash_makes_more_maintainable_tfstate_keys_vs_array = {
for each in local.users_with_extra_dirs_flat : each.unique_key => { username = each.username, extra_dir = each.extra_dir }
}
}
resource "aws_s3_bucket_object" "loop_user_folders_extra_customized_folders" {
for_each = local.users_with_extra_dirs_hash_makes_more_maintainable_tfstate_keys_vs_array
# lesser way for_each = {for idx, value in local.users_with_extra_dirs_flat : idx => value }
bucket = "my-example-bucket"
acl = "private"
key = "somepath/${each.value.username}/${each.value.extra_dir}/" # Note this must end in a "/" to make that appear as 'directory'
source = "/dev/null"
}
可能有几种方法可以进一步清理这个问题,尽管有一个中间变量,然后进行转换,这有助于解释正在发生的事情和调试。