【问题标题】:Combining usage of Terraform's zipmap, maps, and lists结合使用 Terraform 的 zipmap、地图和列表
【发布时间】:2022-01-26 10:27:15
【问题描述】:

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

对于这两者,我想应用for-loop 和zipmask 的某种组合来拥有一个地图对象。您可以假设我已经检查了两个输入映射/列表的顺序并且它们是对齐的。

使用公共子网作为第一个示例,我为每个用户设置一个 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 的单独有状态部署的一部分预置。

【问题讨论】:

  • "您可以假设我已经检查了两个输入地图/列表的顺序并且它们是对齐的" - 在 Terraform 中,地图是无序的(如哈希图),因此当您迭代它们时,原始订单将不会被保留。实际上,键将按字典顺序排序:discuss.hashicorp.com/t/does-map-sort-keys/12056
  • @ErvinSzilagyi 当我在 AWS 控制台中根据它们所代表的 CIDR(例如 pub_cidr_map)检查子网 ID 的值(例如,pub_id_list)时,这两者至少在到目前为止,我已经完成了 4 或 5 次部署。我也有一个非常基本的尝试,zipmap(keys(var.pub_cidrs), module.vpc.public_subnets) 似乎也将 ID 与其正确的 CIDR 对齐...也就是说,我 100% 愿意使用键“查找”要附加的正确条目...
  • 我刚刚根据您的输入尝试了zipmap(keys(var.pub_cidr_map), var.pub_id_list)。结果会映射user1subnet-666666662ee6f3442user2subnet-6666666696b92d895 等等,这是不正确的。
  • @ErvinSzilagyi 我在此站点上手动清理了输入名称和 ID,这可能会产生影响。这就是为什么我说你可以假设我已经检查了这个订购问题而不用担心它。我也对Terraform maps are unorderedsorted in lexicographical order 感到有些困惑——如果两张地图都按字典顺序排列,这不是问题吗?

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


【解决方案1】:

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

对于公共子网:

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",
  ]
}

这个输出的问题在于,正如我在 cmets 中所指出的,对映射键的迭代以字典顺序发生。这意味着user1 将映射到第一个条目,从pub_id_listuser2 映射到第二个条目,等等。即使您在 cmets 中建议“我已经检查了这个排序问题并且不用担心它”,请在使用前仔细检查此解决方案。

对于私有子网:

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 的键在提供时按字典顺序排列。我认为这在一定程度上回答了您在 cmets 中的问题,即“如果两张地图都按字典顺序排列,这不是问题吗?”

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",
    ],
  ]
}

【讨论】:

  • 太棒了!谢谢!
猜你喜欢
  • 2021-01-07
  • 1970-01-01
  • 1970-01-01
  • 2018-02-12
  • 1970-01-01
  • 2019-08-24
  • 1970-01-01
  • 2020-10-13
  • 2017-07-23
相关资源
最近更新 更多