terraform - 使用 for_each 创建的资源中带有 for_each 的动态块
问题描述
我正在尝试使用 Terraform 0.12+ 及其新的 for_each 在 Azure 中构建多个 vnet,但遇到了一些麻烦。我希望新功能能够让我创建一个接收复杂变量的通用网络模块,但我可能已经达到了它的极限,或者我只是没有正确地思考它。基本上我的变量是这样构建的
variable "networks" {
type = list(object({ name = string, newbits = number, netnum = number, subnets = list(object({ name = string, newbits = number, netnum = number}))}))
}
您可以看到它是一个网络数组,其中包含该网络的子网子数组。这样做可以轻松记录网络,而无需额外的 terraform 资源要求,因此我们的网络团队可以轻松调整/扩展,而无需担心了解 HCL。
我可以使用计数及其索引执行构建多个 vnet 资源的必要功能,但我想使用 for_each 因为它允许索引键而不是可能随时间变化的计数(需要重新部署,我们不能做)。
网络对象
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,但问题在于制作子网。
locals {
vnets = {
for vnet in var.networks:
vnet.name => cidrsubnet(var.root_cidr, vnet.newbits, vnet.netnum)
}
}
由于地图不包括那些子网,所以我只是把头撞在墙上。有没有人有什么建议?或者当我不需要的时候,我真的让这个过于复杂吗?
有效的资源创建,但没有子网
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。之后我也尝试过用自己的子网资源来做,但就是想不通。
这是我希望能起作用的全部资源
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"
块内的其他信息。
相反,如果我们对原始var.networks
值使用重复,那么我们可以subnets
直接从内部获得列表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)
}
}
}
推荐阅读
- android-studio - AS IDE 字体不可用
- angular - 带有选项卡的角度材质对话框 - 如果在对话框加载时切换选项卡,选项卡的内容不可见
- ruby-on-rails - 有没有一种简单的方法可以将 ActiveRecord 对象转换为 ActiveModel 对象?
- perl - Perl 模块 WWW:RobotRules 不会安装
- php - 如果使用自定义代码应用优惠券,它将不计入 woocommerce 的使用量
- akka.net - 不尊重 maxNrOfRetries 的 SupervisorStrategy 策略
- python - 如何在 python 中创建具有特殊平均度的有向无标度网络?
- python - 错误: /var/cache/apt/archives/ 中没有足够的可用空间。在虚拟框中使用 Ubuntu 时
- ruby-on-rails - 使用 Rails 6 进行敏捷 Web 开发,但使用 RSpac 和 FactoryBot:为什么这些请求测试会失败?
- java - 如何在 flink 流处理中使用过滤器在键控流上添加处理功能?