Terraform For表达式使用一个元组和两个字符串列表创建要在for_each中使用的单个映射

你叫

如何使用一个元组和两个字符串列表创建用于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] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章