【问题标题】:Terraform: Referencing resources created in for_each in another resourceTerraform:在另一个资源中引用在 for_each 中创建的资源
【发布时间】:2020-12-17 19:47:42
【问题描述】:

当我有一个托管区域时,我很容易创建该区域,然后通过按名称引用托管区域的名称在委派帐户中为该区域创建 NS 记录。

现在我需要创建多个托管区域并将名称服务器记录传递回父帐户,但我不确定是否可以(或如何)引用多个资源。读到这里可能没有多大意义,所以下面的代码就是我所掌握的。

我现在有一个for_each 循环,它将遍历字符串列表并为每个字符串创建一个托管区域,然后我想在另一个帐户中创建相应的 NS 记录,请注意我正在使用单独的提供程序@ 987654323@ 连接到管理帐户,这适用于单个托管区域。

我不知道如何引用托管区域,是否有一些语法或我的方法错误?

resource "aws_route53_zone" "public_hosted_zone" {
  for_each = local.aws_zones
  name     = "${each.value}.${var.domain}"
}

resource "aws_route53_record" "ns_records" {
  for_each        = local.aws_zones
  provider        = aws.management_account
  allow_overwrite = true
  name            = "${each.value}.${var.domain}"
  ttl             = 30
  type            = "NS"
  zone_id         = data.aws_ssm_parameter.public_hosted_zone_id.value

  records = [
    aws_route53_zone.public_hosted_zone.name_servers[0], # Here is my old code which works for a single hosted zone but I cannot work out how to reference multiples created above
    aws_route53_zone.public_hosted_zone.name_servers[1],
    aws_route53_zone.public_hosted_zone.name_servers[2],
    aws_route53_zone.public_hosted_zone.name_servers[3]
  ]
}

【问题讨论】:

  • records = aws_route53_zone.public_hosted_zone.name_servers 应该在 TF >= 0.12 中工作
  • 一个很小的调整(第一次构建失败)records = aws_route53_zone.public_hosted_zone[each.key].name_servers 你能告诉我这是怎么工作的吗?当我查看计划输出 terraform 是先创建托管区域然后是 route53 记录时,它如何将两者联系起来并使用 route53 记录 for_each 中的 each.key 正确引用在 aws_route53_zone 中创建的资源?
  • local.aws_zones的形式是什么?
  • 看起来像这样["dev", "test", "qa"]
  • 你想在这里实现什么?看起来您正在尝试将区域的 NS 记录设置为该区域已经存在的名称服务器。首先,这不是您为 route53 区域设置名称服务器的方式,其次,您实际上不需要在此处执行任何操作,因为您会在创建区域后查看您的区域记录。

标签: amazon-web-services foreach terraform amazon-route53


【解决方案1】:

由于您的 local.aws_zones 设置为 ["dev", "test", "qa"],因此您的 aws_route53_zone.public_hosted_zone 将是一个带有键 "dev"、"test"、"qa" 的映射。

因此,要在您的aws_route53_record 中使用它,您可以尝试:

resource "aws_route53_record" "ns_records" {
  for_each        = local.aws_zones

  # other attributes

  records = aws_route53_zone.public_hosted_zone[each.key].name_servers
}

【讨论】:

    【解决方案2】:

    在这种情况下,您的意图似乎是说“local.aws_zones 中的每个条目有一个区域,然后每个区域有一个 NS 记录集”。

    在这种情况下,写下来的一种简洁方法是使用一个资源作为下一个资源的for_each,如下所示:

    resource "aws_route53_zone" "public_hosted_zone" {
      for_each = local.aws_zones
    
      name = "${each.value}.${var.domain}"
    }
    
    resource "aws_route53_record" "ns_records" {
      provider = aws.management_account
      for_each = aws_route53_zone.public_hosted_zone
    
      allow_overwrite = true
      name            = each.value.name
      ttl             = 30
      type            = "NS"
      zone_id         = data.aws_ssm_parameter.public_hosted_zone_id.value
      records         = each.value.name_servers
    }
    

    通过在resource "aws_route53_zone" "public_hosted_zone" 中使用for_each,您可以使aws_route53_zone.public_hosted_zone 成为从区域键到区域对象的映射,它本身与for_each 的预期兼容,因此您可以将该映射向下传递到另一个资源。

    这种方法的一个重要优点是resource "aws_route53_record" "ns_records"块中的each.value直接是对应的区域对象,因此我们可以编写each.value.name从区域中获取派生的name参数,而无需复制再次使用该表达式,我们可以编写 each.value.name_servers 来获取每个区域的导出名称服务器集。这样就避免了编写更复杂的表达式来通过 each.key 查找区域,因为 Terraform 已经完成了必要的查找来填充 each.value

    【讨论】:

    • 这是一个很棒的提示,我不知道您可以使用创建的一组资源来驱动另一组资源的for_each,所以我一直循环遍历原始地图( local.aws_zones)
    猜你喜欢
    • 1970-01-01
    • 2019-12-16
    • 2020-12-09
    • 2021-04-15
    • 1970-01-01
    • 2022-07-28
    • 2021-12-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多