使用 route 53 记录遍历 terraform 中的对象地图

Iterating through map of objects in terraform with route 53 records

我正在尝试弄清楚如何使用 for / for_each 使用 Terraform 0.12.26

从 Terraform 中读取其他值

dns.tfvars

mx = {
  "mywebsite.org." = {
    ttl = "3600"
    records = [
      "home.mywebsite.org.",
      "faq.mywebsite.org."
    ]
  }
  "myotherwebsite.org." = {
    ttl = "3600"
    records = [
      "home.myotherwebsite.org."
    ]
  }
}

variables.tf

variable "mx" {
  type = map(object({
    ttl     = string
    records = set(string)
  }))
}

mx.tf

locals {
  mx_records = flatten([
    for mx_key, mx in var.mx : [
      for record in mx.records : {
        mx_key = mx_key
        record = record
        ttl    = mx.ttl
    }]
  ])
}

resource "aws_route53_record" "mx_records" {
  for_each = { for mx in local.mx_records : mx.mx_key => mx... }
  zone_id  = aws_route53_zone.zone.zone_id
  name     = each.key
  type     = "MX"
  ttl      = each.value.ttl

  records = [
    each.value.record
  ]
}

在mx.tf中,我可以注释掉第二个值,faq.mywebsite.org,代码完美运行。我无法弄清楚如何设置我的 for 循环和 for each 语句以使其“循环”通过第二个值。我收到的第一个错误如下:

Error: Duplicate object key

  on mx.tf line 13, in resource "aws_route53_record" "mx_records":
  13:   for_each = { for mx in local.mx_records : mx.mx_key => mx }
    |----------------
    | mx.mx_key is "mywebsite.org."

Two different items produced the key "mywebsite.org." in this 'for'
expression. If duplicates are expected, use the ellipsis (...) after the value
expression to enable grouping by key.

据我所知,我没有两个重复的值来帮助形成密钥,因此我不必使用省略号,但我还是尝试使用省略号以查看它是否适用。在值表达式后添加省略号后,出现此错误:

Error: Unsupported attribute

  on mx.tf line 20, in resource "aws_route53_record" "mx_records":
  20:     each.value.record
    |----------------
    | each.value is tuple with 2 elements

This value does not have any attributes.

如有任何关于此问题的建议,我们将不胜感激。

更新

Error: [ERR]: Error building changeset: InvalidChangeBatch: [Tried to create resource record set [name='mywebsiteorg.', type='MX'] but it already exists]
    status code: 400, request id: dadd6490-efac-47ac-be5d-ab8dad0f4a6c

正在尝试创建记录,但由于列表中的第一条记录,它已经创建。

我想你可以构建一个对象映射,键是 mx_records 列表的索引(注意 idx 是索引):

resource "aws_route53_record" "mx_records" {

  for_each = { for idx, mx in local.mx_records : idx => mx }

  zone_id  = aws_route53_zone.zone.zone_id

  name     = each.value.mx_key
  type     = "MX"
  ttl      = each.value.ttl

  records = [
    each.value.record
  ]
}

上面的 for_each 表达式将你的 local.mx_records 从 list(objects) 更改为 map(objects),其中映射键是 idx,值是原始对象。

更新:

我在 Route53 验证过,不能重复验证码。因此可以尝试使用原始 mx 变量:

resource "aws_route53_record" "mx_records" {

  for_each = { for idx, mx in var.mx : idx => mx }

  zone_id  = aws_route53_zone.zone.zone_id

  name     = each.key
  type     = "MX"
  ttl      = each.value.ttl

  records = each.value.records
}

此外,如果你想避免flatten函数和for循环局部变量,你可以访问映射中的对象:

resource "aws_route53_record" "mx_records" {
  for_each = var.mx
  zone_id  = aws_route53_zone.zone.zone_id
  name     = each.key
  type     = "MX"
  ttl      = each.value["ttl"]
  records = each.value["records"]
}