【问题标题】:for_each throws an error after it has been "moved"for_each 被“移动”后抛出错误
【发布时间】:2021-06-13 11:31:46
【问题描述】:

所以,我之前在每个资源中都使用了 for_each。 现在我已将其移至模块中。

module "architect" {  
  source = "./modules/architect"
  for_each = toset(var.vm_names)
  vm_name = each.value
  vm_key = each.key
}

我还在 /modules/architect/variables.tf 中定义了 vm_name 和 vm_key:

variable "vm_name" {
  type = string
}

variable "vm_key" {
  type = string
}

我正在尝试在每个 VM 上设置一个公共 IP 地址。 当我在每个资源中都有 for_each(注释掉)时,这很好用。

resource "azurerm_public_ip" "pubip" {
    #for_each = toset(var.vm_names)
  name                = "${var.vm_name}-PublicIp"
  resource_group_name = azurerm_resource_group.rsg.name
  location            = azurerm_resource_group.rsg.location
  allocation_method   = "Dynamic"

}

resource "azurerm_network_interface" "main" {
    #for_each = toset(var.vm_names)
  name                = "${var.vm_name}-nic"
  location            = azurerm_resource_group.rsg.location
  resource_group_name = azurerm_resource_group.rsg.name


  ip_configuration {
    name                          = "testconfiguration1"
    subnet_id                     = azurerm_subnet.subnet.id
    private_ip_address_allocation = "Dynamic"
    public_ip_address_id          = azurerm_public_ip.pubip[var.vm_key].id
  }

这里抛出的错误是:

Error: Invalid index

  on modules\architect\main.tf line 109, in resource "azurerm_network_interface" "main":
 109:     public_ip_address_id          = azurerm_public_ip.pubip[var.vm_key].id
    |----------------
    | azurerm_public_ip.pubip is object with 16 attributes
    | var.vm_key is "OSL-SPLK-HF01"

The given key does not identify an element in this collection value.

这是第 109 行的块,其中最后一行是数字 109:

  ip_configuration {
    name                          = "testconfiguration1"
    subnet_id                     = azurerm_subnet.subnet.id
    private_ip_address_allocation = "Dynamic"
    public_ip_address_id          = azurerm_public_ip.pubip[var.vm_key].id

我收到此错误的原因是什么?

我之前在那里使用过 each.key。

【问题讨论】:

  • var.vm_names的结构是什么?你有什么例子可以展示吗?
  • 抱歉,忘记了。 variable "vm_names" { type = list(string) default = [ "OSL-SPLK-SH01", "OSL-SPLK-CM", "OSL-SPLK-IDX01", "OSL-SPLK-IDX02", "OSL-SPLK-DS", "OSL-SPLK-HF01"] }
  • 我明白了。因此,您将 var.vm_names 传递到模块中。 var.vm_key 呢? var.vm_names 绝对不是 var.vm_key,因此会出现错误。
  • 但我也在传递 var.vm_key 吗?像,我有这个: vm_key = each.key 然后将它分配给变量文件?
  • 他们现在拥有它,模块中的 `vm_key` 将只是来自vm_names 的值。在没有模块的代码中,它们显然是不同的变量。

标签: terraform


【解决方案1】:

当您有一个完全没有设置for_eachresource 块时,在其他表达式中引用它只会返回一个对象而不是对象映射。

因此,一旦您将for_each 分解为调用模块块而不是每个单独的资源,就不再正确地尝试访问您的资源的各个实例,就像您在表达式azurerm_public_ip.pubip[var.vm_key].id 中所做的那样。相反,您应该直接引用资源现在表示的单个对象:

   public_ip_address_id          = azurerm_public_ip.pubip.id

请注意,在每个特定模块实例的命名空间内只有一个azurerm_public_ip.pubip,因此您可以直接引用它。因为for_each 现在位于模块调用本身而不是单个资源上,Terraform 将分配这些资源地址,如下所示:

module.architect["OSL-SPLK-HF01"].azurerm_public_ip.pubip

...而当您在根目录中拥有带有自己的 for_each 参数的资源时,Terraform 会这样处理它们:

module.architect.azurerm_public_ip.pubip["OSL-SPLK-HF01"]

索引现在存在于 calling 模块而不是 calling 模块中,因此架构师模块本身并不知道它正在与 for_each 一起使用,但是调用者中对该模块输出的任何引用都需要包含一个键,就像您之前对资源实例所做的那样:

# the "foo" output value associated with the "OSL-SPLK-HF01"
# instance of the module.
module.architect["OSL-SPLK-HF01"].foo

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-12-13
    • 2020-04-19
    • 2021-10-22
    • 1970-01-01
    • 2013-05-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多