在 terraform 中,如何输出 aws_route53_record 别名值?

In terraform, how do I output an aws_route53_record alias value?

Terraform v0.12.x

我正在创建一个 AWS Route53 记录,就像这样,它的创建没有任何问题。

data "aws_route53_zone" "zone" {
  name         = "my.domain.com."
  private_zone = true
}

resource "aws_route53_record" "record" {
  zone_id = data.aws_route53_zone.zone.zone_id
  name    = "${var.record_name}.${data.aws_route53_zone.zone.name}"
  type    = "A"
  alias {
    name                   = var.alias_record
    zone_id                = var.alias_zone_id
    evaluate_target_health = false
  }
}

现在我想输出别名的值,我试过了

output "alias_name" {
  value = aws_route53_record.record.alias.name
}

output "alias_name" {
  value = aws_route53_record.record.alias["name"]
}

但是报错

Block type "alias" is represented by a set of objects, and set elements do not
have addressable keys. To find elements matching specific criteria, use a
"for" expression with an "if" clause.

正确的语法是什么?

alias 是一组对象并设置 are:

a collection of unique values that do not have any secondary identifiers or ordering.

所以你不能索引它们。因此,在您的情况下,您可以使用输出别名值:

output "alias_name" {
  value = aws_route53_record.record.alias.*.name
}

# or

output "alias_name2" {
  value = aws_route53_record.record.alias[*].name
}

此处返回的错误消息 Terraform 是一个通用消息,它 returns 适用于表示为一组对象的所有块类型,因此它为您提供了一些关于 select 的一般建议根据其值或嵌套值设置元素。例如:

output "example" {
  # Select the first element from the
  # set whose name is "foo".
  value = [
    for a in aws_route53_record.record.alias : a
    if a.name == "foo"
  ][0]
}

该建议实际上并不适合您在此处遇到的特定问题,因为您不是在“查找符合特定条件的元素”,而只是尝试 select 您知道自己写的那个元素,因为无论如何,您只静态定义了一个 alias 块,因此您知道它会一直存在并且永远是正确的。

为此,一种选择是使用 the tolist function 将集合显式转换为列表。文档警告生成的元素不会以任何特定顺序排列,但是当无论如何只有一个元素时,该元素只能有一个排序,因此这是安全的:

output "example" {
  # Select the first element from the
  # set whose name is "foo".
  value = tolist(aws_route53_record.record.alias)[0].name
}

如果底层 API 认为对象是无序的并且没有特定的唯一标识符,则提供程序通常使用特定块类型的集合表示。不幸的是,结果使用起来不太方便,但是使用这种对底层行为的准确建模可以避免以下问题:如果远程 API 开始以不同的(任意)顺序返回项目,则配置一开始可能有效,但后来行为不当.

这个 alias 块的集合选择有点奇怪,因为它被定义为无论如何只允许零个或一个块;我怀疑这是供应商现在为了向后兼容而保留的历史设计怪癖。

结合 Marcin 和 Martin 的回答(感谢他们),这就是我最终使用的内容

output "alias_name" {
  value =  tolist(aws_route53_record.record.alias.*.name)[0]
}

Marcin 的回答给出了

alias_name = [
  "my-record.domain.com",
]

虽然马丁的回答给出了

alias_name = {
  "evaluate_target_health" = false
  "name" = "my-record.domain.com"
  "zone_id" = "Z1234ABCDE"
}

但是结合我上面的两个答案给出

alias_name = my-record.domain.com