如何使用一个元组和两个字符串列表创建用于for_each的单个对象映射
假设我有一个来自ec2模块的实例ID或实例IP的元组/列表,以及来自ALB模块的目标组arns的元组/列表,如下所示。
instance_ids = ["10.1.1.1", "10.2.2.2"]
target_gropup_arn = ["arn1", "arn2"]
在main.tf中
output "out" {
value = local.aws_lb_target_group_attachment
}
variable "target_groups" {
type = any
default = [
{
protocol = "TCP"
port = "22"
},
{
protocol = "TCP"
port = "443"
}
]
}
locals {
instance_ips = toset(["10.1.1.1", "10.2.2.2"])
target_gropup_arn = toset(["arn1", "arn2"])
aws_lb_target_group_attachment = { for idx in flatten([for instance_ids in local.instance_ids :
[for tg in var.target_groups :
[for arn in local.target_gropup_arn :
{
target_id = instance_ids
target_group_arn = arn
port = tg.port
}]
]]) : "${idx.target_id}:${idx.port}:${idx.target_group_arn}" => idx }
}
当我运行terraform apply时,我得到以下输出,但这不是我需要的预期地图。
Outputs:
out = {
"10.1.1.1:22:arn1" = {
"port" = "22"
"target_group_arn" = "arn1"
"target_id" = "10.1.1.1"
}
"10.1.1.1:22:arn2" = {
"port" = "22"
"target_group_arn" = "arn2"
"target_id" = "10.1.1.1"
}
"10.1.1.1:443:arn1" = {
"port" = "443"
"target_group_arn" = "arn1"
"target_id" = "10.1.1.1"
}
"10.1.1.1:443:arn2" = {
"port" = "443"
"target_group_arn" = "arn2"
"target_id" = "10.1.1.1"
}
"10.2.2.2:22:arn1" = {
"port" = "22"
"target_group_arn" = "arn1"
"target_id" = "10.2.2.2"
}
"10.2.2.2:22:arn2" = {
"port" = "22"
"target_group_arn" = "arn2"
"target_id" = "10.2.2.2"
}
"10.2.2.2:443:arn1" = {
"port" = "443"
"target_group_arn" = "arn1"
"target_id" = "10.2.2.2"
}
"10.2.2.2:443:arn2" = {
"port" = "443"
"target_group_arn" = "arn2"
"target_id" = "10.2.2.2"
}
}
预期输出为(伪输出)
out = {
"10.1.1.1:22" = {
"port" = "22"
"target_id" = "10.1.1.1"
"target_group_arn" = "arn1"
}
"10.1.1.1:443" = {
"port" = "443"
"target_id" = "10.1.1.1"
"target_group_arn" = "arn1"
}
"10.2.2.2:22" = {
"port" = "22"
"target_id" = "10.2.2.2"
"target_group_arn" = "arn2"
}
"10.2.2.2:443" = {
"port" = "443"
"target_id" = "10.2.2.2"
"target_group_arn" = "arn2"
}
}
这是必需的,以便以后我可以使用它使用“ aws_lb_target_group_attachment”资源附加多个实例。
您的技术无法奏效,因为您正在创建ips和arns的笛卡尔积,但是根据示例输出,您只希望将第一个ip与第一个arn分组,将第二个ip分组。与第二个arn分组。
output "out" {
value = local.aws_lb_target_group_attachment
}
variable "target_groups" {
type = any
default = [
{
protocol = "TCP"
port = "22"
},
{
protocol = "TCP"
port = "443"
}
]
}
locals {
instance_ids = ["10.1.1.1", "10.2.2.2"]
target_arns = ["arn1", "arn2"]
arn_id_map = [for i, id in local.instance_ids : { "target_id" : id, "target_group_arn" : local.target_arns[i] }]
aws_lb_target_group_attachment = merge([for tg in var.target_groups :
{ for pair in local.arn_id_map :
"${pair.target_id}:${tg.port}" => merge(pair, { "port" : tg.port })
}
]...)
}
arn_id_map = [for i, id in local.instance_ids : { "target_id" : id, "target_group_arn" : local.target_arns[i] }]
在这里,我们遍历ips列表并构造一个新映射,其中包含您希望在最终输出中使用的三个键中的两个。我们利用了一个事实,即ips和arns之间存在1-1映射。也就是说,第一个ip对应于第一个arn,第二个ip对应于第二个arn,依此类推。
aws_lb_target_group_attachment = merge([for tg in var.target_groups :
{ for pair in local.arn_id_map :
"${pair.target_id}:${tg.port}" => merge(pair, { "port" : tg.port })
}
]...)
从第一个循环开始,我们迭代目标组以创建列表理解,这意味着该层的值将是列表。然后在内部进行映射理解,迭代上一步中创建的ip + arn对。
在内部,我们创建一个地图,其结构是您所需的最终输出。内部合并是采用我们的ip + arn对并使用端口创建新映射的一种干净方法。
但是随着层展开,我们最终得到一个包含两个映射的列表,每个映射包含2个子映射(每个ip + port组合一个)。我们需要“展平”结构,但flatten()
不适用于地图列表。
为了平展地图,我们通常会到达merge()
,但是在这种情况下,它不能直接起作用,因为merge()
希望每个参数都是一个地图。但是我们有一张地图清单。因此,我们使用扩展符号 ...
将列表传递给merge并将其扩展为merge可以直接接受的参数。
结果如您所愿:
out = {
"10.1.1.1:22" = {
"port" = "22"
"target_group_arn" = "arn1"
"target_id" = "10.1.1.1"
}
"10.1.1.1:443" = {
"port" = "443"
"target_group_arn" = "arn1"
"target_id" = "10.1.1.1"
}
"10.2.2.2:22" = {
"port" = "22"
"target_group_arn" = "arn2"
"target_id" = "10.2.2.2"
}
"10.2.2.2:443" = {
"port" = "443"
"target_group_arn" = "arn2"
"target_id" = "10.2.2.2"
}
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句