azure-devops - Terraform - 如何在对象列表中展平列表

标签 azure-devops terraform terraform-provider-azure infrastructure-as-code

我正在尝试在这些区域中设置我的 DNS 区域和记录,但无法将我正在寻找的结构化集合传递到将生成所有区域和记录的 tf 文件中。我有一个 DNS 对象列表,每个对象都有多个记录对象列表。我正在尝试创建仅记录的列表(a,cname,txt,...)。我正在尝试合并和扁平化,但我只是不确定如何获得我需要的东西。我不断尝试不同的合并和展平模式,但在不同的配置中不断出现错误。

错误:

Error: Invalid 'for' expression. Extra characters after the end of the 'for' expression.
Error: Missing attribute value. Expected an attribute value, introduced by an equals sign ("=").
Error: Invalid 'for' expression. Key expression is required when building an object.
Error: Missing key/value separator. Expected an equals sign ("=") to mark the beginning of the attribute value.

变量定义:

variable "dns_target_child_zones" {
  type = list(object({
    name      = string
    a_records = list(object({
      name        = string
      ttl         = number
      ip_address  = string
    }))
    cname_records = list(object({
      name        = string
      ttl         = number
      record      = string
    }))
    mx_records = list(object({
      name        = string
      ttl         = number
      record      = list(object({
        preference  = number
        exchange    = string
      }))
    }))
    txt_records = list(object({
      name        = string
      ttl         = number
      record      = list(object({
        value  = string
      }))
    }))
  }))
}

本地文件:

locals {
  a_records = flatten ([

  ])
  cname_records = flatten ([

  ])
  mx_records = flatten ([

  ])
  txt_records = flatten ([

  ])        
}

我试图生成的输出结构,以便我可以执行类似 count = length(locals.a_records) 的操作

[
 {
   name                = 
   zone_name           = 
   ttl                 = 
   records             = 
 },
 {
   name                = 
   zone_name           = 
   ttl                 = 
   records             = 
 }
 ...
]

最佳答案

以下是您可以为 a_records 创建的本地对象的示例(注意:我包含了 ip_address 属性,但您的记录未出现在 a_records 变量对象中):

  a_records = flatten([
    for v in var.dns_target_child_zones : [
      for record in v.a_records : {
        name       = record.name
        zone_name  = v.name
        ttl        = record.ttl
        ip_address = record.ip_address
      }
    ]
  ])

这将产生如下输出:

  + a_records = [
  + {
      + ip_address = "ip1"
      + name       = "a1"
      + ttl        = 10
      + zone_name  = "dns1"
    },
  + {
      + ip_address = "ip2"
      + name       = "a2"
      + ttl        = 10
      + zone_name  = "dns1"
    },
  ]

我使用默认值和输出来测试预期结果。这是我的完整测试,您可以运行 terraform plan 来显示输出

variable "dns_target_child_zones" {
  type = list(object({
    name = string
    a_records = list(object({
      name       = string
      ttl        = number
      ip_address = string
    }))
    cname_records = list(object({
      name   = string
      ttl    = number
      record = string
    }))
    mx_records = list(object({
      name = string
      ttl  = number
      record = list(object({
        preference = number
        exchange   = string
      }))
    }))
    txt_records = list(object({
      name = string
      ttl  = number
      record = list(object({
        value = string
      }))
    }))
  }))
  default = [{
    name = "dns1",
    a_records = [{
      name       = "a1",
      ttl        = 10
      ip_address = "ip1"
      },
      {
        name       = "a2",
        ttl        = 10
        ip_address = "ip2"
      }
    ],
    cname_records = [{
      name   = "cname1",
      ttl    = 10
      record = "rec1"
    }],
    mx_records = [{
      name = "mx1",
      ttl  = 10,
      record = [{
        preference = 1,
        exchange   = "exchange1"
        }, {
        preference = 2,
        exchange   = "exchange2"
      }]
    }],
    txt_records = [{
      name = "txt1",
      ttl  = 10,
      record = [{
        value = "val1"
      }]
    }]
  }]
}


locals {
    a_records = flatten([
        for v in var.dns_target_child_zones: [
            for record in v.a_records: {
                name       = record.name
                zone_name  = v.name
                ttl        = record.ttl
                ip_address = record.ip_address
            }
        ]
    ])
}

output "a_records" {
    value = local.a_records
}

为了进一步嵌套提取,例如使用 mx_records,您可以在本地添加另一个 for 循环,如下所示

  mx_records = flatten([
    for v in var.dns_target_child_zones : [
      for mx in v.mx_records : [
        for r in mx.record : {
          name       = mx.name
          zone_name  = v.name
          ttl        = mx.ttl
          preference = r.preference
          exchange   = r.exchange
        }
      ]
    ]
  ])

上面本地输出这个结果

  + mx_records = [
      + {
          + exchange   = "exchange1"
          + name       = "mx1"
          + preference = 1
          + ttl        = 10
          + zone_name  = "dns1"
        },
      + {
          + exchange   = "exchange2"
          + name       = "mx1"
          + preference = 2
          + ttl        = 10
          + zone_name  = "dns1"
        },
    ]

关于azure-devops - Terraform - 如何在对象列表中展平列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73571891/

相关文章:

terraform - 空的 "azurerm_subscription"数据 block 究竟是如何获取其数据源参数的?

azure - 无效或未知 key : network_security_group_id

Azure Devops 更改部署文件夹

azure - 使用现有资源在 Azure 中的 terraform 中创建资源并创建新资源

azure-devops - Azure DevOps 管道触发问题消息不会消失

azure - AKS 中的节点池未缩减至 0 个节点?

azure - 调用外部API :s randomly slow after moving integration test to a docker container

amazon-cognito - 如何使用 terraform 修复认知用户池域破坏,以便可以重新创建用户池?

amazon-web-services - Terraform 按标签查找 s3 存储桶

amazon-web-services - Terraform for_each - every.key 在哪里定义?