Terraform 使用 for_each 引用另一个模块的输出 [英] Terraform referencing output from another module with for_each

查看:15
本文介绍了Terraform 使用 for_each 引用另一个模块的输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在引用另一个模块中的一个模块的输出时遇到问题.第一个模块中的资源是使用 for_each 部署的.第二个模块中的资源正在尝试引用第一个模块中的资源

I am having trouble referencing an output from a module in another module. The resources in the first module was deployed using for_each. The resources in the second module is trying to reference the resources from first module

创建了 2 个模块

  1. 安全组
  2. 虚拟机

目的是将安全组分配给虚拟机

The intention is to assign the Security Group to the VM

以下是安全组的模块


variable "configserver" {
  type = map(object({
    name              = string
    location          = string
    subnet            = string
    availability_zone = string
    vm_size           = string
    hdd_size          = string
  }))
}


module "configserver_nsg" {
  for_each = var.configserver

  source              = "../../../terraform/modules/azure-network-security-group"
  resource_group_name = var.resource_group_name
  tags                = var.tags
  location = each.value.location
  nsg_name = "${each.value.name}-nsg"

  security_rules = [
    {
      name              = "Office",
      priority          = "100"
      direction         = "Inbound"
      access            = "Allow"
      protocol          = "TCP"
      source_port_range = "*"
      destination_port_ranges = [
        "22"]
      source_address_prefix = "192.168.1.100"
      destination_address_prefixes = [
        module.configserver_vm[each.key].private_ip
      ]
    },
    

    {
      name                       = "Deny-All-Others"
      priority                   = 4096
      direction                  = "Inbound"
      access                     = "Deny"
      protocol                   = "*"
      source_port_range          = "*"
      destination_port_range     = "*"
      source_address_prefix      = "*"
      destination_address_prefix = "*"
    }

  ]
}

// Value


configserver = {
  config1 = {
    name              = "config1"
    location          = "eastus"
    subnet            = "services"
    availability_zone = 1
    vm_size           = "Standard_F2s_v2"
    hdd_size          = 30
  }
}

安全组模块源有一个输出文件,输出 nsg 的 id

The security group module source has an output file which outputs the id of the nsg

output "nsg_id" {
  description = "The ID of the newly created Network Security Group"
  value       = azurerm_network_security_group.nsg.id
}

一般来说,如果没有for_each,我可以像这样访问nsg_id

Generally, if there isn't a for_each, I could access the nsg_id like this

module.configserver_nsg.id

到目前为止这很好,现在问题是我无法从另一个模块访问 nsg_id

So far this is good, now the issue is that I am not able to access the nsg_id from another module

module "configserver_vm" {
  for_each = var.configserver

  source         = "../../../terraform/modules/azure-linux-vm"
  resource_group = module.resource_group.name
  ssh_public_key = var.ssh_public_key
  tags           = var.tags
  vm_name            = each.value.name
  location           = each.value.location
  subnet_id          = each.value.subnet
  availability-zones = each.value.availability_zone
  vm_size            = each.value.vm_size
  hdd-size           = each.value.hdd_size
  nsg_id             = module.configserver_nsg[each.key].nsg_id
}

根据我的研究,一些帖子(这里这里这里说我应该能够使用 each.key 然而

Based on my research these, a number of posts (here, here, here say I should be able to loop through the map using each.key however

nsg_id             = module.configserver_nsg[each.key].nsg_id

这会产生错误

Error: Cycle: module.configserver_nsg (close), module.configserver_vm.var.nsg_id (expand), module.configserver_vm.azurerm_network_interface_security_group_association.this, module.configserver_vm (close), module.configserver_nsg.var.security_rules (expand), module.configserver_nsg.azurerm_network_security_group.nsg, module.configserver_nsg.output.nsg_id (expand)

还有其他方法可以引用该值吗?

Is there any other way to reference the value?

推荐答案

我看到的第一个问题是您使用错误的方式从模块 configserver_nsg 引用 NSG id 的内容,应该是这样的:

As I see the first problem is that you use the wrong way to quote the things from the module configserver_nsg for the NSG id, it should be like this:

nsg_id             = module.configserver_nsg[each.value.name].nsg_id

@Matt 已经提到了第二个问题.这是两个模块之间的循环依赖.造成循环依赖的东西是 NSG 规则,似乎 NSG 规则需要 VM 私有 IP 地址.据我所知,如果不进行更改,就无法解决循环依赖问题.因此,我建议您进行更改,将 NSG 规则与模块 configserver_nsg 分开,并使用资源 azurerm_network_security_rule 而不是这两个模块之后.

And the second problem has been said by @Matt. It's a cyclical dependency between the two modules. The thing that makes the cyclical dependency is the NSG rule, it seems the NSG rule needs the VM private IP address. According to my knowledge, you cannot solve the cyclical dependency if you do not make a change. So I recommend you make a change that separates the NSG rule from the module configserver_nsg and use the resource azurerm_network_security_rule instead after the two modules.

最后,它看起来像这样:

And finally, it seems like this:

variable "configserver" {
  type = map(object({
    name              = string
    location          = string
    subnet            = string
    availability_zone = string
    vm_size           = string
    hdd_size          = string
  }))
}


module "configserver_nsg" {
  for_each = var.configserver

  source              = "../../../terraform/modules/azure-network-security-group"
  resource_group_name = var.resource_group_name
  tags                = var.tags
  location = each.value.location
  nsg_name = "${each.value.name}-nsg"

  security_rules = [
    {
      
    },
    

    {
      name                       = "Deny-All-Others"
      priority                   = 4096
      direction                  = "Inbound"
      access                     = "Deny"
      protocol                   = "*"
      source_port_range          = "*"
      destination_port_range     = "*"
      source_address_prefix      = "*"
      destination_address_prefix = "*"
    }

  ]
}

// Value


configserver = {
  config1 = {
    name              = "config1"
    location          = "eastus"
    subnet            = "services"
    availability_zone = 1
    vm_size           = "Standard_F2s_v2"
    hdd_size          = 30
  }
}

module "configserver_vm" {
  for_each = var.configserver

  source         = "../../../terraform/modules/azure-linux-vm"
  resource_group = module.resource_group.name
  ssh_public_key = var.ssh_public_key
  tags           = var.tags
  vm_name            = each.value.name
  location           = each.value.location
  subnet_id          = each.value.subnet
  availability-zones = each.value.availability_zone
  vm_size            = each.value.vm_size
  hdd-size           = each.value.hdd_size
  nsg_id             = module.configserver_nsg[each.value.name].nsg_id
}

resource "azurerm_network_security_rule" "configserver_nsg" {
  for_each = var.configserver
  name              = "Office",
  priority          = "100"
  direction         = "Inbound"
  access            = "Allow"
  protocol          = "TCP"
  source_port_range = "*"
  destination_port_ranges = ["22"]
  source_address_prefix = "192.168.1.100"
  destination_address_prefixes = [
    module.configserver_vm[each.key].private_ip
  ]
  resource_group_name         = var.resource_group_name
  network_security_group_name = "${each.value.name}-nsg"
}

这篇关于Terraform 使用 for_each 引用另一个模块的输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆