循环遍历列表映射以在一个资源块中为多个域创建 DNS 记录

Posted

技术标签:

【中文标题】循环遍历列表映射以在一个资源块中为多个域创建 DNS 记录【英文标题】:Loop through map of lists to create DNS records for multiple domains in one resource block 【发布时间】:2021-12-23 19:13:49 【问题描述】:

我有几个域,我想创建尽可能多的 DRY 子域。这是原始结构:

variable "domain1" 
  type = list(string)
  default = ["www", "www2"]


variable "domain2" 
  type = list(string)
  default = ["www3", "www1"]


resource "aws_route53_record" "domain1" 
  for_each = toset(var.domain1)
  
  type = "A"
  name = "$each.key.domain1.com"
  zone_id = ""


resource "aws_route53_record" "domain2" 
  for_each = toset(var.domain2)
  
  type = "A"
  name = "$each.key.domain2.com"
  zone_id = ""

我想组合成一个变量和一个资源块:

variable "subdomains" 
  type = map(list(string))
  default = 
    "domain1.com" = ["www", "www2"]
    "domain2.com" = ["www3", "www1"]
  


resource "aws_route53_record" "domain1" 
  for_each = var.subdomains // make magic happen here...
  
  type = "A"
  name = "$each.subdomain_part.$each.domain_part" // ...and here
  zone_id = ""

有没有办法做到这一点?

【问题讨论】:

如果您有两个不同的域domain1.comdomain2.com,我假设它们也有两个不同的zone_id,对吧?因此,我认为要概括这一点,您需要某种方式来了解或动态生成区域 ID,以实现完整的工作解决方案。 ?????? 不过,这很容易。只是使用相同变量循环通过 aws_route53_zone 数据资源 【参考方案1】:

您可以按如下方式展平您的var.subdomains

locals 
    subdomains_flat = flatten([for domain, subdomains in var.subdomains:
                        [ for subdomain in subdomains:
                            
                                domain_part = domain
                                subdomain_part = subdomain
                            
                        ]
                      ])

然后:

resource "aws_route53_record" "domain1" 
  for_each = for idx, val in local.subdomains_flat: idx => val 
  
  type = "A"
  name = "$each.value.subdomain_part.$each.value.domain_part" 
  zone_id = ""

【讨论】:

这行得通,但会造成相当混乱的状态,因为索引用于资源名称。是否可以对其进行调整,以便在资源名称中使用子域? @aardbol 索引必须是唯一的,不能保证子域将是唯一的,而不是 subdomains_flat 数组,您可以构建适合您需要的自定义地图以获得更好看的索引【参考方案2】:

跟进the comment关于混乱状态的信息,我不会说混乱......但肯定有一些缺点,该答案中的索引是数字,计划显示资源结束:

  # aws_route53_record.domain1["0"] will be created
  + resource "aws_route53_record" "domain1" 

  # aws_route53_record.domain1["1"] will be created
  + resource "aws_route53_record" "domain1" 

当我们在列表中添加或删除子域时,这可能会产生问题,顺序可能会发生变化,这将导致资源被破坏和重新创建,这对 route53 记录不理想...


这是另一种在资源名称中创建不同索引的方法。 我们仍然使用 flatten 来提取子域,但在这种情况下,我会立即连接,该局部变量已准备好供 aws_route53_record 资源使用。

provider "aws" 
  region = "us-east-2"


variable "subdomains" 
  type = map(list(string))
  default = 
    "domain1.com" = ["www", "www2"]
    "domain2.com" = ["www3", "www1"]
  


locals 
  records = flatten([for d, subs in var.subdomains: [for s in subs: "$s.$d"]])


resource "aws_route53_record" "domain1" 
  for_each = toset(local.records)

  type    = "A"
  name    = each.value
  zone_id = "us-east-1"

一个 terraform 计划如下所示:

Terraform will perform the following actions:

  # aws_route53_record.domain1["www.domain1.com"] will be created
  + resource "aws_route53_record" "domain1" 
      + allow_overwrite = (known after apply)
      + fqdn            = (known after apply)
      + id              = (known after apply)
      + name            = "www.domain1.com"
      + type            = "A"
      + zone_id         = "us-east-1"
    

  # aws_route53_record.domain1["www1.domain2.com"] will be created
  + resource "aws_route53_record" "domain1" 
      + allow_overwrite = (known after apply)
      + fqdn            = (known after apply)
      + id              = (known after apply)
      + name            = "www1.domain2.com"
      + type            = "A"
      + zone_id         = "us-east-1"
    
    ...

【讨论】:

以上是关于循环遍历列表映射以在一个资源块中为多个域创建 DNS 记录的主要内容,如果未能解决你的问题,请参考以下文章

循环遍历 pandas 数据框列中的列表元素以在新列中返回列表

循环遍历列表以从 SQL 查询创建多个数据帧

遍历列表以在 Flutter 中呈现多个小部件?

循环遍历多个 panda 数据帧以在 Python 中获取多个数据帧输出

映射多个列表以在python中创建(键,值)对[关闭]

循环遍历列表中的字符串