结合使用 Terraform 的 zipmap、地图和列表

Combining usage of Terraform's zipmap, maps, and lists

我有两种不同的场景,一种是 public 个子网,另一种是私有的。

对于两者,我想应用 for-loop 和 zipmask 的某种组合以获得单个地图对象。您可以假设我已经检查了两个输入 maps/lists 的顺序并且它们是对齐的。

使用 public-子网作为第一个示例,我为每个用户分配了一个 cidr:

pub_cidr_map = {
  "user2" = "10.0.8.0/21"
  "user4" = "10.0.24.0/21"
  "user1" = "10.0.0.0/21"
  "user3" = "10.0.16.0/21"
}

pub_id_list = [
  "subnet-666666662ee6f3442",
  "subnet-6666666696b92d895",
  "subnet-66666666cbaa4bfb3",
  "subnet-6666666655a09d064",
]

我希望它看起来像这样,这样我就可以使用一个键访问这两个值:

pub_lookup_map = {
  "user2" = ["10.0.8.0/21", "subnet-666666662ee6f3442"]
  "user4" = ["10.0.24.0/21", "subnet-6666666696b92d895"]
  "user1" = ["10.0.0.0/21", "subnet-66666666cbaa4bfb3"]
  "user3" = ["10.0.16.0/21", "subnet-6666666655a09d064"]
}

我也想用我的私人子网完成类似的事情,每个用户分配两个:

priv_cidr_map = {
  "user1" = [
    "10.0.96.0/20",
    "10.0.112.0/20",
  ]
  "user2" = [
    "10.0.160.0/20",
    "10.0.176.0/20",
  ]
  "user3" = [
    "10.0.64.0/20",
    "10.0.80.0/20",
  ]
  "user4" = [
    "10.0.128.0/20",
    "10.0.144.0/20",
  ]
}

priv_id_list = [
  "subnet-666666662f611f9a5",
  "subnet-6666666689f1eff5e",
  "subnet-66666666a3fe6efb9",
  "subnet-66666666faf4a62a8",
  "subnet-666666668f1442700",
  "subnet-66666666328a4b134",
  "subnet-666666661b147a933",
  "subnet-666666661ce02c330"
]

我希望它看起来像

priv_lookup_map = {
  "user1" = [
    ["10.0.96.0/20","subnet-666666662f611f9a5"]
    ["10.0.112.0/20","subnet-6666666689f1eff5e"]
  ]
  "user2" = [
    ["10.0.160.0/20","subnet-66666666a3fe6efb9"]
    ["10.0.176.0/20","subnet-66666666faf4a62a8"]
  ]
  "user3" = [
    ["10.0.64.0/20","subnet-666666668f1442700"]
    ["10.0.80.0/20","subnet-66666666328a4b134"]
  ]
  "user4" = [
    ["10.0.128.0/20","subnet-666666661b147a933"]
    ["10.0.144.0/20","subnet-666666661ce02c330"]
  ]
}

我对任何其他人可能认为有用的结构持开放态度;这里的用例是在部署位于这些范围内的资源(如 EC2、RDS)之前,将子网和 EIP 作为单独的、有状态的 VPC 部署的一部分。

我不能保证这个解决方案是正确的,无论如何我会分享我的尝试,希望它可能有所帮助。

对于 public 个子网:

locals {
  pub_lookup_map = {for key, value in zipmap(keys(var.pub_cidr_map), var.pub_id_list) : key => [var.pub_cidr_map[key], value] }
}

这将产生以下输出:

pub = {
  "user1" = [
    "10.0.0.0/21",
    "subnet-666666662ee6f3442",
  ]
  "user2" = [
    "10.0.8.0/21",
    "subnet-6666666696b92d895",
  ]
  "user3" = [
    "10.0.16.0/21",
    "subnet-66666666cbaa4bfb3",
  ]
  "user4" = [
    "10.0.24.0/21",
    "subnet-6666666655a09d064",
  ]
}

这个输出的问题是,正如我在评论中指出的那样,对映射键的迭代是按字典顺序发生的。这意味着 user1 将映射到 pub_id_list 的第一个条目,user2 映射到第二个条目,等等。即使你在评论中建议“我已经检查了这个顺序问题,不用担心”,请在使用前仔细检查此解决方案。

对于私有子网:

locals {
  cidr_subnet_id = zipmap(flatten(values(var.priv_cidr_map)), var.priv_id_list)

  priv_lookup_map = {for key, value in var.priv_cidr_map: key => [ for cidr in value: [cidr, local.cidr_subnet_id[cidr]]]}
}

请注意,我正在使用一个中间局部变量来使我的代码可读。 cidr_subnet_id 的值将是:

cidr_subnet_id = {
  "10.0.112.0/20" = "subnet-6666666689f1eff5e"
  "10.0.128.0/20" = "subnet-666666661b147a933"
  "10.0.144.0/20" = "subnet-666666661ce02c330"
  "10.0.160.0/20" = "subnet-66666666a3fe6efb9"
  "10.0.176.0/20" = "subnet-66666666faf4a62a8"
  "10.0.64.0/20" = "subnet-666666668f1442700"
  "10.0.80.0/20" = "subnet-66666666328a4b134"
  "10.0.96.0/20" = "subnet-666666662f611f9a5"
}

这本质上是 CIDR 和子网 ID 之间的映射。显然,这可以正常工作,因为 priv_lookup_map 中的键在提供时是按字典顺序排列的。我认为这在一定程度上回答了您在评论中提出的问题“如果两张地图都按词典顺序排列,这不是一个问题吗?”

priv_lookup_map 的输出将是:

priv = {
  "user1" = [
    [
      "10.0.96.0/20",
      "subnet-666666662f611f9a5",
    ],
    [
      "10.0.112.0/20",
      "subnet-6666666689f1eff5e",
    ],
  ]
  "user2" = [
    [
      "10.0.160.0/20",
      "subnet-66666666a3fe6efb9",
    ],
    [
      "10.0.176.0/20",
      "subnet-66666666faf4a62a8",
    ],
  ]
  "user3" = [
    [
      "10.0.64.0/20",
      "subnet-666666668f1442700",
    ],
    [
      "10.0.80.0/20",
      "subnet-66666666328a4b134",
    ],
  ]
  "user4" = [
    [
      "10.0.128.0/20",
      "subnet-666666661b147a933",
    ],
    [
      "10.0.144.0/20",
      "subnet-666666661ce02c330",
    ],
  ]
}