Terraform:在模块中使用 for_each

时间:2021-01-08 21:10:19

标签: azure terraform terraform-provider-azure

我正在使用 terraform 版本 0.14.3。 我有一个用于创建 Azure 网络接口卡的模块,如下所示:

resource "azurerm_network_interface" "nic" {

  name                = var.nic_name
  location            = var.location
  resource_group_name = var.rg_name

  ip_configuration {
    name                          = var.ipconfig_name
    subnet_id                     = var.subnet_id
    private_ip_address_allocation = "Dynamic"
  }
}

其输出定义为:

output "nic_id" {
     value = azurerm_network_interface.nic.id 
}

我在这个父模块中调用这个模块:

module "NIC" {
  source = "./NIC"
  for_each = var.nics

  nic_name      = each.value.nic_name
  location      = "eastus2"
  rg_name       = "abc-test-rg"
  ipconfig_name = each.value.ipconfig_name
  subnet_id     = <subnet_id>
}

output "nic_ids" {
  value = [for k in module.NIC.nic_id : k.id]
} 

NIC 值定义如下:

nics = {
  nic1 = {
    nic_name      = "abc-nic-1"
    ipconfig_name = "nic-1-ipconfig"
  }
}

我想循环显示 NIC 输出 ID,并希望它们显示出来。 当我运行上面的代码时,我在 terraform plan 中遇到以下错误:

Error: Unsupported attribute

  on main.tf line 15, in output "nic_ids":
  15:   value = [for k in module.NIC.nic_id : k.id]
    |----------------
    | module.NIC is object with 1 attribute "nic1"

This object does not have an attribute named "nic_id".

我该如何解决?

1 个答案:

答案 0 :(得分:4)

您的 module "NIC" 块设置了 for_each,因此模块中其他地方的 module.NIC 符号是从实例键到输出对象的映射,而不仅仅是单个输出对象单例模块。

Terraform 的错误消息试图通过以下消息引起人们的注意:

  • module.NIC is object with 1 attribute "nic1"

请注意,此处的 nic1 是您的 var.nics 中的一个键,不是模块中定义的输出值之一。

假设您在此处显示的 nic_id 输出是该模块中唯一定义的输出,则 module.NIC 值的形状将如下所示:

{
  nic1 = {
    nic_id = "eni-e5aa89a3"
  }
}

听起来您更想生成这样的值:

{
  nic1 = "eni-e5aa89a3"
}

如果是这样,获得该结果的合适表达式如下:

output "nic_ids" {
  value = { for k, nic in module.NIC : k => nic.nic_id }
} 

上面的意思是:为 NIC 模块的每个实例生成一个具有一个元素的映射,其键是模块实例键,其值是 nic_id 输出值。

或者,如果哪个 id 属于哪个实例无关紧要,那么您可以生成一组无序的 id,如下所示:

output "nic_ids" {
  value = toset([for nic in module.NIC : nic.nic_id])
} 

在这种情况下,for 表达式只定义了一个局部符号 nic,它代表模块实例对象,因为它对实例键没有任何作用。这里的 toset 表示 ID 没有按任何特定顺序排列:这不是绝对必要的,但我认为确保依赖该值的任何其他 Terraform 代码不会无意中取决于当前 id 的任意顺序,如果您在 var.nics 中添加或删除元素,这些顺序可能会在未来发生变化。