繁体   English   中英

如何将terraform中两个for_each循环的输出作为输入传递给其他tf资源

[英]How to pass output of two for_each loops in terraform as an input to other tf resource

我正在尝试创建一些 Azure 资源,例如 VNET、子网和 NSG。 我正在使用 for_each 元参数来创建多个子网和 NSG。 但是,我无法弄清楚如何使用“azurerm_subnet_network_security_group_association”将它们关联起来。 我正在将子网 ID 和 NSG ID 的输出创建为映射,但我无法弄清楚如何在子网 ID 和 NSG ID 之间创建关联。 例如:我创建了一个名为“public_subnet”的子网,我想将“public_nsg”关联到公共子网,同样也关联到私有子网。 现在,我只想让任务仅由名称驱动。

子模块 main.tf:

resource "azurerm_virtual_network" "vnet" {
  name                = format("%s-%s-vnet", var.owner_custom, var.purpose_custom)
  location            = var.location
  resource_group_name = format("rg-%s-%s", var.owner_custom, var.purpose_custom)
  address_space       = var.address_space

}


resource "azurerm_subnet" "subnet" {
  for_each = var.subnets
  name = each.value["name"]
  address_prefixes = each.value["address_space"]
  resource_group_name = format("rg-%s-%s", var.owner_custom, var.purpose_custom)
  virtual_network_name = azurerm_virtual_network.vnet.name
}


resource "azurerm_network_security_group" "nsg" {
  for_each = var.nsg
  name = each.value["name"]
  location = var.location
  resource_group_name = format("rg-%s-%s", var.owner_custom, var.purpose_custom)
}


resource "azurerm_subnet_network_security_group_association" "nsg_association" {
  subnet_id = #need help here
  network_security_group_id = #need help here
}

子模块变量.tf:

variable "owner_custom" {
    description = "Short name of owner"
}

variable "purpose_custom" {
    description = "Custom purpose"
}
variable "location" {
  description = "Location where resource is to be created"
  
}
variable "address_space" {
  type = list
  description = "VNET CIDR Range"
}

variable "subnets" {
  description = "A map to create multiple subnets"
  type = map(object({
    name = string
    address_space = list(string)
  })) 
}

variable "nsg" {
  description = "A map of NSGs"
  type = map(object({
    name = string
  }))
  
}

子模块 output.tf:

output "vnet_id" {
    value = azurerm_virtual_network.vnet.id
}

output "subnet_id" {
    value = tomap({
        for k, s in azurerm_subnet.subnet : k => s.id
    })
  
}

output "nsg_id" {
    value = tomap({
        for k,s in azurerm_network_security_group.nsg: k => s.id
    })
  
}

变量:

#Referenced common across modules
owner_custom = "raghav"
purpose_custom = "demo"

#Referenced in resource-group module
owner = "test@test.com"
purpose = "test"
location = "australiaeast"
org = "org"

#Referenced in network module
address_space = ["10.10.0.0/21"]

subnets = {
    subnet1 = {
        name = "public_subnet"
        address_space = ["10.10.1.0/26"]
        }

    subnet2 = {
        name = "private_subnet"
        address_space = ["10.10.1.64/26"]
        }

    subnet3 = {
        name = "privatelink_subnet"
        address_space = ["10.10.1.128/26"]
        }
    
    subnet4 = {
        name = "AzureFirewallSubnet"
        address_space = ["10.10.1.192/26"]
        }
}

nsg = {
    public_nsg = {
        name = "public_nsg"
        }

    private_nsg = {
        name = "private_nsg"
        }
    }

根据您的描述,您的规则似乎是您希望将第一个下划线之前的名称部分用作一种隐含的相关键,这意味着:

  • public_subnetpublic_nsg相关联
  • private_subnetprivate_nsg相关联
  • privatelink_subnet不与任何东西相关联
  • AzureFirewallSubnet不与任何东西相关联

此处的主要任务是使用一些 Terraform 语言表达式来表达该规则,以便创建从子网到安全组的查找表。

我通常会从派生一些新的数据结构开始,这些数据结构捕获我们将用于匹配的键,以便我们可以在解决方案的其余部分中使用这些结构来简洁地查找这些结果:

locals {
  subnet_types = tomap({
    for k, s in var.subnets : k => split("_", s.name)[0]
  })
  nsg_types = tomap({
    for k, s in var.nsg : split("_", s.name)[0] => k
  })
}

这使用split函数查找所有由下划线分隔的部分,然后[0]选择第一部分。 因此,这应该产生以下映射:

local.subnet_types = {
  subnet1 = "public"
  subnet2 = "private"
  subnet3 = "privatelink"
  subnet4 = "AzureFirewallSubnet"
}
local.nsg_types = {
  public  = "public_nsg"
  private = "private_nsg
}

请注意, local.subnet_ids 中的值与local.subnet_ids中的键local.nsg_types ,因此提供了足够的信息来将其简化为直接从子网键到 NSG 键的映射:

locals {
  subnet_nsgs = {
    for k, ty in local.subnet_ids :
    k => try(local.nsg_types[ty], null)
  }
}

这用于try处理没有为特定“类型”关键字定义 NSG 的情况。 因此,其结果应该是:

local.subnet_nsgs = {
  subnet1 = "public_nsg"
  subnet2 = "private_nsg"
  subnet3 = null
  subnet4 = null
}

这现在具有决定要声明哪些安全组关联所需的所有信息,但是我们需要再进行一次转换来过滤掉null元素(因为我们根本不想为这些声明关联)并拉入我们需要填充资源参数的其他数据:

resource "azurerm_subnet_network_security_group_association" "nsg_association" {
  for_each = {
    for subnet_key, nsg_key in local.subnet_nsgs : subnet_key => {
      subnet_id = azurerm_subnet.subnet[subnet_key].id
      nsg_id    = azurerm_network_security_group.nsg[nsg_key].id
    }
    if nsg_key != null
  }

  subnet_id                 = each.value.subnet_id
  network_security_group_id = each.value.nsg_id
}

最后一个for表达式将子网和 NSG密钥交换为远程系统用来跟踪它们的 ID,这是我们需要的资源参数,还包括子句if nsg_key != null以过滤掉那些没有关联的 NSG。

完成所有这些操作后,您应该最终得到两个与以下地址以及相应的子网和 NSG ID 的关联:

  • azurerm_subnet_network_security_group_association.nsg_association["subnet1"]
  • azurerm_subnet_network_security_group_association.nsg_association["subnet2"]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM