terraform - Terraform For 表达式使用一个元组和两个字符串列表创建单个映射以在 for_each 中使用
问题描述
如何使用一个元组和两个字符串列表创建要在 for_each 中使用的单个对象映射
假设我有一个来自 ec2 模块的实例 ID 或实例 IP 的元组/列表和一个来自 ALB 模块的目标组 arn 的元组/列表,如下所示。
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"
}
}
推荐阅读
- python - 数据框列形状在安装到管道后反转,特别是在 kNearestNeighbor() 之后
- javascript - React Data Grid - 能够查看但不能编辑单元格
- python - 如何在 Python 中使用空值初始化对象?
- python - 使用 python 从investing.com 抓取数据
- php - 检查是否在wordpress中使用ajax发布多个点击事件
- r - R包括带有leafpop :: addpopupGraphs()的plot_ly()图
- julia - 升级 makie 包
- php - 带有限制记录的laravel分页
- google-sheets-formula - 谷歌表格拆分问题
- javascript - 在 TRX 文件中添加日志文件或失败截图