【问题标题】:Use a map of lists of maps in resource creation在资源创建中使用地图列表的地图
【发布时间】:2020-12-08 15:31:08
【问题描述】:

我希望能够使用 TF Vars 中定义的以下格式创建多个 R53 记录:

custom_zone_records = {
  "demo.a.com" = [
    {"*.b" = {type: "CNAME", records: ["d.com"]}},
    {"*.c" = {type: "CNAME", records: ["d.com"]}}
  ]
}

以记录为例,应该创建R53记录:

Name: *.b.demo.a.com
Type: CNAME
Records: ["d.com"]

输入变量定义为:

variable "custom_zone_records" {
  description = "A map of maps for custom zone records"
  type = map(list(map(object({
    type = string
    records: list(string)
  }))))
}

我尝试使用 for_each 在资源创建中更改数组,并尝试使用本地文件进行格式化,但没有成功。

除了让数组更明确之外,还有更好的格式化或处理方法吗?

谢谢。

编辑:

如果我不使用该变量,我将不得不编写以下代码(作为我想要实现的示例)

resource "aws_route53_record" "demo_a" {
  zone_id = "ZONE_ID"
  name    = "*.b.demo.a.com"
  type    = "CNAME"
  records = ["d.com"]
  ttl     = 60
}

resource "aws_route53_record" "demo_a" {
  zone_id = "ZONE_ID"
  name    = "*.c.demo.a.com"
  type    = "CNAME"
  records = ["d.com"]
  ttl     = 60
}

【问题讨论】:

  • 到目前为止一切顺利,您在将变量传递到 aws_route53_record 方面尝试了什么?你到底卡在哪里了?
  • 得到了添加for_each(循环通过顶层区域,例如demo.a.com)然后尝试添加查找,循环通过值。在那一点上有点卡住了——我们如何(如果可能)循环遍历资源,这个问题很现实。
  • 如果您在没有变量的情况下手动创建 N 个资源,它们会是什么样子?给定的例子有多少?如果您需要循环两次(一次用于不同的域,一次用于不同的记录),您可以创建一个循环数据的本地,创建多个嵌套数组,然后将所有内容包装在 flatten 调用中,以便您可以然后 for_each在展开的本地上。
  • 我已编辑问题以显示手动创建我想要创建的记录。我想你不能给我一点代码,作为一个例子好吗?我想我朝我走的方向走错了树

标签: terraform terraform0.12+


【解决方案1】:

一种方法(假设我正确理解了这个问题)是创建一个辅助局部变量,它将custom_zone_records“展开”到更多for_each-友好列表中。

在下面的例子中,它被称为helper_list

locals {
  custom_zone_records = {
    "demo.a.com" = [
      {"*.b" = {type: "CNAME", records: ["d.com"]}},
      {"*.c" = {type: "CNAME", records: ["d.com"]}}
    ],
    "demo1.a.com" = [
      {"*.b1" = {type: "CNAME", records: ["d1.com"]}},
      {"*.c1" = {type: "CNAME", records: ["d1.com"]}}
    ]    
  }
  
  helper_list = flatten([for k, v in local.custom_zone_records: 
            [for v1 in v: 
              merge({name = join("", [keys(v1)[0], ".", k])}, values(v1)[0])
           ]
      ])
  
}

helper_list 的格式为:

helper_list = [                     
  {                          
    "name" = "*.b.demo.a.com"
    "records" = [   
      "d.com",               
    ]               
    "type" = "CNAME"         
  },             
  {                          
    "name" = "*.c.demo.a.com"
    "records" = [   
      "d.com",
    ]               
    "type" = "CNAME"
  },
  {
    "name" = "*.b1.demo1.a.com"
    "records" = [
      "d1.com",
    ]
    "type" = "CNAME"
  },
  {
    "name" = "*.c1.demo1.a.com"
    "records" = [
      "d1.com",
    ]
    "type" = "CNAME"
  },
]

这样for_each的用法会更简单,可能是(以下我没有验证,所以把它当作伪代码):

resource "aws_route53_record" "demo" {

  for_each = toset(local.helper_list)

  zone_id = "ZONE_ID"

  name    = each.value.name
  type    = each.value.type
  records = each.value.records

  ttl     = 60
}

【讨论】:

  • 非常感谢。不得不将 toset 更改为 for_each = { for record in local.helper_list : record.name => record },因为它抱怨记录类型错误,但感谢您救了我拔出更多的头发!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-07-10
  • 2015-09-27
  • 2020-11-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多