【问题标题】:Looping over list of list循环列表列表
【发布时间】:2021-11-25 21:00:09
【问题描述】:

我有一个aws_route 资源,我想用新路由更新列表中的所有路由表。以下是相关代码:

resource "aws_route" "private_route" {
  for_each = data.aws_route_tables.private_route_tables.ids

  route_table_id          = each.key
  destination_cidr_block  = var.tgw_destination_cidr_block
  transit_gateway_id      = module.tgw.ec2_transit_gateway_id
}

当变量tgw_destination_cidr_block 中定义了一个CIDR 时,上述代码可以正常工作,因为aws_route 需要destination_cidr_block 属性的字符串类型。

tgw_destination_cidr_block = "10.255.160.0/20"

现在我想在这个变量中添加多个 CIDR 范围,并对其进行迭代。

tgw_destination_cidr_block = ["10.255.160.0/20", "10.255.176.0/22"]

为了在每个路由表中创建两条新路由。所以,我想我需要变量中的字符串列表并遍历 CIDR 范围列表。

知道怎么做吗?

【问题讨论】:

  • 您需要在路由表和 CIDR 上都有一个嵌套循环,因此这需要您首先使用 setproduct 创建这两个列表/集的产品。 stackoverflow.com/a/62565413/2291321 提供了一个很好的例子来说明如何做到这一点。
  • 如果以上链接的答案解决了您的问题,那就太好了,我们可以将其作为副本关闭,以改善人们找到该答案的方式。如果没有,您能否编辑您的问题,以显示您从该答案中尝试了哪些对您不起作用的答案,以便人们可以帮助缩小任何问题的范围?
  • 谢谢@ydaetskcoR。我使用了下面提供的解决方案,因为它是指我的用例。但是你发布的链接也非常接近这个。

标签: amazon-web-services terraform terraform-provider-aws


【解决方案1】:

在考虑for_each 表达式时,我总是首先考虑“为每个...声明一个实例”这句话的结尾可能是什么,在这种情况下,这句话似乎是:

为每一对私有路由表和目标 CIDR 块声明一个实例。

这告诉我们,我们需要一个集合,其中每个元素代表其中一对。

查找多组项目的所有组合的常用方法是the setproduct function,其文档中有一个部分Finding combinations for for_each 显示了为许多不同的基础网络声明一组系统子网的工作示例.

我们可以根据您的问题调整该示例,如下所示。文档中的示例已经通过小步骤完成了它,因此为了简单起见,我将在这里将所有本地值表达式合并为一个:

locals {
  route_table_routes = [
    for pair in setproduct(data.aws_route_tables.private_route_tables.ids, var.tgw_destination_cidr_blocks) : {
      route_table_id         = pair[0]
      destination_cidr_block = pair[1]
    }
  ]
}

resource "aws_route" "private_route" {
  for_each = {
    for rtr in local.route_table_routes : "${rtr.route_table_id}:${rtr.destination_cidr_block}" => rtr
  }

  route_table_id          = each.value.route_table_id
  destination_cidr_block  = each.value.destination_cidr_block
  transit_gateway_id      = module.tgw.ec2_transit_gateway_id
}

上面将声明 aws_route.private_route 实例,其键是路由表 ID 和目标 CIDR 块的组合。

请注意,将远程系统分配的 id 用作 Terraform 中实例键的一部分可能会出现问题,因为 Terraform 需要在整个计划和应用过程中完全知道这些实例键。但是,在您的情况下,您正在使用数据源检索这些路由表 ID,因此只要在规划期间可以完全了解您的数据资源配置本身,它们就会在规划期间为人所知。

通常我建议使用相同的配置来负责声明路由表和这些路由,从而能够为每个路由表提供一个完全从配置中知道的静态密钥(不是由远程系统决定)全部),但是这种设计在分解的系统中并不总是实用的,因此只要您注意确保以正确的顺序将更改应用于单独的 Terraform 配置,您在这里所做的事情就可以了这样更改将以您想要的方式级联,即使 Terraform 无法看到整个依赖结构,因此无法保证排序本身。

【讨论】:

  • 这是一个很好的答案,但我认为我评论中的另一个链接答案(也是你的!)可能是一个更好的答案(尽管在一般意义上,因为它不使用这些特定资源)所以认为最好将其作为重复项关闭,并尝试为这些类型的问题设置一个更规范的目标。
  • 我还考虑过我们是否应该创建一个完整的、通用的问答组合(例如在一些更多的流量标签上发生)以一个很好的通用解决方案来解决我们经常出现的某些类型的问题方式,但没有时间看,当我是唯一的金标签徽章持有人时,我不想单方面这样做。尽管考虑到标签上的问题数量相对较少,但可能有一个很好的论点认为这是过早的优化。
  • 感谢@Martin 提供如此详细的解释和解决方案,这实际上是您为此类任务共享的 terraform 文档中所写的内容。也非常感谢我的用例的解决方案。
  • Martin 也写了这些文档 :)
猜你喜欢
  • 2012-12-04
  • 2016-02-25
  • 1970-01-01
  • 2016-08-01
  • 2015-05-07
  • 2012-10-10
  • 1970-01-01
  • 1970-01-01
  • 2013-03-10
相关资源
最近更新 更多