Terraform - 用于表达理解

Terraform - For expression Understanding

我试图理解 TF 中的“for”表达式,当它们使用一对临时符号(如 k、v)时。我的目标是理解结构,以便我可以将这些知识放入 PowerPoint 文件中并向其他人解释。我会尽力用通俗易懂的英语解释我认为正在发生的事情,但希望您能提供意见,看看我的理解是否正确。我正在学习TF,所以请多多包涵

下面是代码 - 从别人那里继承而来。

变量声明

variable "private_dns_zones" {
  type = map(object({
    dns_zone_name       = string
    resource_group_name = string
    tags                = map(string)
    vnet_links = list(object({
      zone_to_vnet_link_name    = string
      vnet_name                 = string
      networking_resource_group = string
      zone_to_vnet_link_exists  = bool
      vnet_link_rg_name         = string
    }))
    zone_exists          = bool
    registration_enabled = bool
  }))
  description = "Map containing Private DNS Zone Objects"
  default     = {}
}

MAIN - 切断以限制此

的范围
locals {
  rgs_map = {
    for i, n in var.private_dns_zones : "${i}" => {
      name = n.resource_group_name
    }
  }
  private_dns_zones = {
    for dz_k, dz_v in var.private_dns_zones :
    dz_k => dz_v if(coalesce(dz_v.zone_exists, false) == false && dz_v.dns_zone_name != null)
  }

  zone_to_vnet_links_distinct = distinct(flatten([
    for dz_k, dz_v in var.private_dns_zones : [
      for vnet in coalesce(dz_v.vnet_links, []) : {
        dns_zone_key              = dz_k #This would be 'zone1'?
        dns_zone_name             = dz_v.dns_zone_name
        zone_to_vnet_link_name    = vnet.zone_to_vnet_link_name
        vnet_name                 = vnet.vnet_name
        networking_resource_group = vnet.networking_resource_group
        vnet_link_rg_name         = vnet.vnet_link_rg_name
        registration_enabled      = dz_v.registration_enabled
      } if(coalesce(vnet.zone_to_vnet_link_exists, false) == false && vnet.vnet_name != null)
    ] if(dz_v.zone_exists == false && dz_v.dns_zone_name != null)
  ]))

  zone_to_vnet_links = {
    for vnet_link in local.zone_to_vnet_links_distinct :
    "${vnet_link.dns_zone_key}_${vnet_link.zone_to_vnet_link_name}" => vnet_link
  }
}

TFVARS

private_dns_zones = {
  zone1 = {
    dns_zone_name       = "privatelink.vaultcore.azure.net"
    resource_group_name = "Terraform1"
    tags = {
      iac    = "Terraform"
      syntax = "zone1"
    }
    zone_exists = false
    vnet_links = [
      {
        zone_to_vnet_link_name    = "vaultcore-vnet-eastus2-01"
        vnet_name                 = "vnet-eastus2-01"
        networking_resource_group = "Terraform1"
        zone_to_vnet_link_exists  = false
        vnet_link_rg_name         = "Terraform1"
      }
    ]
    registration_enabled = false
  }
}

"一个 'for' 表达式可以选择声明一对临时符号,以便也使用每个项目的键或索引"

因此,对于上面看到的当地人 rgs_map: for i, n in var.private_dns_zones : "${i} => {name = n.resource_group_name}

我的解读: 我指的是键或属性名称。那么,这意味着在 tfvars 文件中看到的“zone1”?

对于 zone1,遍历对象并创建一个使用 'zone1' 作为其索引的新对象(如 {} 括号所示),并为每个索引创建一个具有 'name' 的参数将值设置为 tfvars 文件中 resource_group_name 的值? 这个解释正确吗?

表示: 这个准确吗??

rgs_map = {
   zone1 = {
      name = value of resource_group_name in tfvars file
   }
}

下一个 当地人 private_dns_zones 对于 dz_k、dz_v : dz_k又是指'zone1'?

解读: zone1 => dz_v (dz_v 是指整个对象吗?这个不清楚。) 如果 zone_exists 为 false 并且 dns_zone_name 不为空,则创建一个新的本地对象??

表示: 这个准确吗??

private_dns_zones = {
     zone1 = {
       name = dns_zone_name
       resource_group_name = resource_group_name
       etc.
}
}

谢谢。只是想确认一下我对这些的理解是正确的。

要事第一:

TFVARS.tfvars 文件是可选的。我们拥有它们的原因是为了存储输入。如果我们删除它们,Terraform 将在您执行 plan.

时要求我们输入

variables 是接受和存储我们使用 .tfvar 文件或从控制台输入的输入的数据结构。在您的情况下,TFVARS 文件中 private_dns_zones 的结构为 variable "private_dns_zones".

提供了输入

for 表达式:

它们的行为根据迭代的内容而有所不同。例如: 在遍历列表时将变量作为迭代器:

[for item in ["abc", "bcd", "cde"] : upper(s)]

在这种情况下 item 的值将是 "abc""bcd" 和“cde”`。

在遍历列表时拥有索引和迭代器:

[for index, item in ["abc", "bcd", "cde"] : upper(s)]

item的值将是"abc""bcd"和"cde",同时index的值将是012.

遍历 map:

{ for key, value in var.private_dns_zones : "${key}" => {name = n.resource_group_name} }

mapobjects 的情况下,我们没有索引。我们有键和值。值 key 将是 zone1value 的值将是整个对象:

{
    dns_zone_name       = "privatelink.vaultcore.azure.net"
    resource_group_name = "Terraform1"
    tags = {
      iac    = "Terraform"
      syntax = "zone1"
    }
    zone_exists = false
    vnet_links = [
      {
        zone_to_vnet_link_name    = "vaultcore-vnet-eastus2-01"
        vnet_name                 = "vnet-eastus2-01"
        networking_resource_group = "Terraform1"
        zone_to_vnet_link_exists  = false
        vnet_link_rg_name         = "Terraform1"
      }
    ]
    registration_enabled = false
}

for zone1, loop through the object and create a new object (as depicted by the {} brackets) that uses 'zone1' as its index, and create one argument per index that has 'name' with the value set to the value of the resource_group_name in the tfvars file? Is this explanation correct?

不,不完全是。 for 表达式将产生一个对象,但对象没有索引,它们有键和值。更准确地说,这个 for expression 创建一个对象,其键是 var.private_dns_zones 中的键,值是每个键 (zone1) 映射到的 resource_group_names

所以:

rgs_map = {
  for i, n in var.private_dns_zones : "${i}" => {
    name = n.resource_group_name
  }
}

计算结果为:

rgs_map = {
  "zone1" = {
    "name" = "Terraform1"
  }
}

对于第二个for表达式,思路是一样的。

  private_dns_zones = {
    for dz_k, dz_v in var.private_dns_zones :
    dz_k => dz_v if(coalesce(dz_v.zone_exists, false) == false && dz_v.dns_zone_name != null)
  }

这使用 coalesce 函数来实现关于对象中包含的内容的附加逻辑,但除此之外,想法是相似的。其输出为:

private_dns_zones = {
  "zone1" = {
    "dns_zone_name" = "privatelink.vaultcore.azure.net"
    "registration_enabled" = false
    "resource_group_name" = "Terraform1"
    "tags" = {
      "iac" = "Terraform"
      "syntax" = "zone1"
    }
    "vnet_links" = [
      {
        "networking_resource_group" = "Terraform1"
        "vnet_link_rg_name" = "Terraform1"
        "vnet_name" = "vnet-eastus2-01"
        "zone_to_vnet_link_exists" = false
        "zone_to_vnet_link_name" = "vaultcore-vnet-eastus2-01"
      },
    ]
    "zone_exists" = false
  }
}

nterpretation: zone1 => dz_v (does dz_v refer to the whole object? Not clear on this.) create a new local object if zone_exists is false and the dns_zone_name is not null??

这有点正确。无论如何都会创建该对象,但它只包含有关 zone_exists 为假且 dns_zone_name 不为空的区域的数据。请记住,您可以有多个区域。如果 zone_exists 的区域没有 false 而 dns_zone_name 的区域不为空,那么 private_dns_zones 将是一个空对象:private_dns_zones = {}.

调试 Terraform 代码的一些建议:

您可以使用 output 来查看表达式的计算结果:

output "private_dns_zones" {
  value = local.private_dns_zones
}

apply 之后,private_dns_zones 的值将显示在您的终端中。

您可以使用 terraform console 命令启动新的 REPL 并动态评估 terraform 命令。