使用 for_each 创建的资源中带有 for_each 的动态块 [英] Dynamic block with for_each inside a resource created with a for_each

查看:26
本文介绍了使用 for_each 创建的资源中带有 for_each 的动态块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 Terraform 0.12+ 及其新的 for_each 在 Azure 中构建多个 vnet,但遇到了一些麻烦.我希望新功能能够让我创建一个接收复杂变量的通用网络模块,但我可能已经达到了它的极限,或者只是没有正确地思考它.基本上我的变量是像

I am trying to build multiple vnets in Azure using Terraform 0.12+ and its new for_each and running into some trouble. I was hoping that the new capabilities would allow me to create a generic network module that takes in a complex variable but I perhaps have reached its limit or am just not thinking it through correctly.. Essentially I my variable is built like

variable "networks" {
  type = list(object({ name = string, newbits = number, netnum = number, subnets = list(object({ name = string, newbits = number, netnum = number}))}))
}

您可以看到它是一个网络数组,其中包含该网络的子网子数组.这样做可以轻松记录网络,而无需额外的 terraform 资源要求,因此我们的网络团队可以轻松调整/扩展,而无需担心了解 HCL.

You can see that its an array of networks with a subarray of the subnets for that network. Doing it this way would make it easy to document the network without the extra lines of the terraform resource requirements so our network team can easily adjust/expand without needing to worry about knowing the HCL.

我可以使用计数及其索引执行构建多个 vnet 资源的必要功能,但我想使用 for_each,因为它允许索引键而不是可能随时间变化的计数(需要重新部署我们做不到).

I can perform the necessary functions of building the multiple vnet resources using count and its index, but I would like to use the for_each as it allows for indexing off of the key rather than a count which could change over time (requiring redeployment which we cannot do).

网络对象

networks = [
    {
        # x.x.1.0/24
        name        = "DMZ",
        newbits     = "8",
        netnum      = "1",
        subnets      = [
            {
                # x.x.1.0/25
                name        = "DMZ"
                newbits     = "9",
                netnum      = "2"
            }
        ]
    },
    {
        # x.x.33.0/24
        name        = "Intermediary"
        newbits     = "8",
        netnum      = "33",
        subnets          = [
            {
                # x.x.33.0/25
                name        = "subnet1"
                newbits     = "9",
                netnum      = "66"
            },
            {
                # x.x.33.128/25
                name        = "subnet2"
                newbits     = "9",
                netnum      = "67"
            }
        ]
    }
]

我已经尝试并通过将对象更改为映射然后使用 each.key 和 each.value(为 each.value 执行 cidrsubnet)成功地使用 for_each 构建了 vnet,但问题在于制作子网.

I have tried and successfully built the vnets with a for_each by changing the object into a map and then using the each.key and each.value (doing a cidrsubnet for the each.value) but the problem lies in making the subnets.

locals {
    vnets = {
        for vnet in var.networks:
        vnet.name => cidrsubnet(var.root_cidr, vnet.newbits, vnet.netnum)
    }
}

由于地图不包括那些子网,我只是把头撞在墙上.有没有人有什么建议?还是在我不需要的时候,我真的让它变得过于复杂?

Since the map does not include those subnets it I am just banging my head against the wall. Does anyone have any suggestions? Or am I really making this overly complex when I dont need to be?

有效的资源创建,但没有子网

The resource creation that works, but no subnets

resource "azurerm_virtual_network" "vnets" {
  for_each            = local.vnets
  name                = each.key
  address_space       = [each.value]
  location            = azurerm_resource_group.network.location
  resource_group_name = azurerm_resource_group.network.name
}

我希望我可以使用动态块,并可能过滤它以匹配网络资源中的 each.key.之后我也尝试过使用它自己的子网资源,但就是想不通.

I was hoping I could use a dynamic block and perhaps filtering it to match the each.key inside of the network resource. I also tried doing it with its own subnet resource after but just cant figure it out.

这是我希望的全部资源

resource "azurerm_virtual_network" "vnets" {
  for_each            = local.vnets
  name                = "99999-Nucleus-${each.key}"
  address_space       = [each.value]
  location            = azurerm_resource_group.network.location
  resource_group_name = azurerm_resource_group.network.name

  dynamic "subnet" {
      for_each = [for vnet in var.networks:
      [for s in vnet.subnets: {
      name   = s.name
      prefix = cidrsubnet(var.root_cidr, s.newbits, s.netnum)
    }] if var.networks.name == each.key]

    content {
      name           = subnet.value.name
      address_prefix = subnet.value.prefix
    }
  }
}

推荐答案

在这里构建这个中间的 local.vnets 映射让这个问题更难解决,因为它抛弃了所有其他的这些对象中的信息,因此很难使用 resource "azurerm_virtual_network" "vnets" 块中的其他信息.

Constructing this intermediate local.vnets map here is making this problem a little harder to solve, because it's throwing away all of the other information in those objects and thus making it hard to use that other information inside the resource "azurerm_virtual_network" "vnets" block.

相反,如果我们对原始 var.networks 值使用重复,那么我们可以直接从 each.valuesubnets 列表>:

Instead, if we use repetition over the original var.networks value then we can have the subnets list available directly from inside each.value:

resource "azurerm_virtual_network" "vnets" {
  for_each = { for n in var.networks : n.name => n }

  location            = azurerm_resource_group.network.location
  resource_group_name = azurerm_resource_group.network.name

  name = "99999-Nucleus-${each.key}"
  address_space = [cidrsubnet(var.root_cidr, each.value.newbits, each.value.netnum)]

  dynamic "subnet" {
    for_each = each.value.subnets
    content {
      name           = subnet.value.name
      address_prefix = cidrsubnet(var.root_cidr, subnet.value.newbits, subnet.value.netnum)
    }
  }
}

这篇关于使用 for_each 创建的资源中带有 for_each 的动态块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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