Terraform:从具有嵌套列表的地图列表创建资源?

问题描述 投票:0回答:1

我需要使用 Terraform 在 AWS 中创建多个子网,并希望使该过程尽可能易于重复和标准化。我想创建一个

list
maps
的变量,其中包含创建子网所需的信息,如下所示:

my_subnet_map = [
  {
    name = "subnetA",
    cidr_blocks = ["10.0.0.0/24"]
  },
  {
    name = "subnetB",
    cidr_blocks = ["10.0.1.0/24", "10.0.2.0/24"]
  },
  {
    name = "subnetC",
    cidr_blocks = ["10.0.3.0/24", "10.0.4.0/24"]
  },
  ...
]

我设想能够做这样的事情:

resource "aws_subnet" "private" {
   count = ???
   vpc_id = var.vpc_id
   availability_zone = XXX

   cidr_block = var.my_subnet_map[SOME KIND OF LOOKUP]

}

我知道如何使用

count
for_each
循环遍历值,但在这种情况下,值具有不同数量的
cidr_blocks
。因此,
count
list
中的条目数不对应。它对应于
cidr_block
的所有成员中
list
值的总数。

我该如何完成这样的事情?对我来说,它几乎像是某种嵌套的

count
,但我对 Terraform 不够熟悉,不知道如何对其进行建模。想法?

amazon-web-services terraform terraform-provider-aws subnet terraform-variables
1个回答
0
投票

您在此处显示的数据结构是一系列对象,如果声明为输入变量,则可能具有以下类型:

list(object({
  name        = string
  cidr_blocks = set(string)
}))

名称“my_subnet_map”因此有点令人困惑,因为这里没有任何地图。我提到这一点只是因为要完成这项工作,您需要将这个对象列表投影到对象映射中,因为这就是

for_each
所需要的,因此当我们开始从中派生其他集合时,直接使用这些名称将使事情变得不那么混乱。这最初的一个。

这似乎也是一个“子网组”列表——这是您自己发明的概念,我现在将其命名为——其中每个对象代表一组子网。因此,为了清楚起见,我们将其命名为

subnet_groups
,并且我还将添加一些类型显式转换,以便更清楚地了解我们在这里要使用的类型:

locals {
  subnet_groups = tolist([
    {
      name = "subnetA",
      cidr_blocks = toset(["10.0.0.0/24"])
    },
    {
      name = "subnetB",
      cidr_blocks = toset(["10.0.1.0/24", "10.0.2.0/24"])
    },
    {
      name = "subnetC",
      cidr_blocks = toset(["10.0.3.0/24", "10.0.4.0/24"])
    },
    ...
  ])
}

为了使其达到

aws_subnet
需要的形状,有必要将其展平为每个实际子网(而不是每个子网组)包含一个元素的集合。这是一种方法: locals { subnets = toset(flatten([ for group in local.subnet_groups : [ for cidr_block in group.cidr_blocks : { group_name = group.name cidr_block = cidr_block } ] ])) } resource "aws_subnet" "private" { for_each = tomap({ for subnet in local.subnets : "${subnet.group_name}:${subnet.cidr_block}" => subnet }) vpc_id = var.vpc_id cidr_block = each.value.cidr_block }

分配给 
subnets

的表达式旨在构造一组形状如下所示的扁平对象:

toset([
  {
    group_name = "subnetA"
    cidr_block = "10.0.0.0/24"
  },
  {
    group_name = "subnetB"
    cidr_block = "10.0.1.0/24"
  },
  {
    group_name = "subnetB"
    cidr_block = "10.0.2.0/24"
  },
  {
    group_name = "subnetC"
    cidr_block = "10.0.3.0/24"
  },
  {
    group_name = "subnetC"
    cidr_block = "10.0.4.0/24"
  },
])

for_each

中的

resource
块需要一个具有唯一键的映射来跟踪每个实例,因此在实际的
for_each
表达式中,我再次将其投影到一个映射中,其中一些键包含组名称和CIDR 块以确保它们都是唯一的。使用我们开始的子网组集,这将声明以下资源实例:

    aws_subnet.private["subnetA:10.0.0.0/24"]
  • aws_subnet.private["subnetB:10.0.1.0/24"]
  • aws_subnet.private["subnetB:10.0.2.0/24"]
  • aws_subnet.private["subnetC:10.0.3.0/24"]
  • aws_subnet.private["subnetC:10.0.4.0/24"]
  • 
    
参考资料:

© www.soinside.com 2019 - 2024. All rights reserved.