如何在Terraform的azurerm_firewall资源中实现ip_configuration可选配置
问题:将azurerm_firewall的ip_configuration改造为可选配置
我想将ip_configuration设置为可选配置,把如下代码:
resource "azurerm_firewall" "example" { name = "testfirewall" location = azurerm_resource_group.example.location resource_group_name = azurerm_resource_group.example.name ip_configuration { name = "configuration" subnet_id = azurerm_subnet.example.id public_ip_address_id = azurerm_public_ip.example.id } }
改造为可通过如下变量接收可选配置值的形式:
variable "ip_configuration" { type = object({ name = string // IP配置的名称 subnet_id = string // 和IP配置绑定的子网引用 public_ip_address_id = string // 和防火墙绑定的公网IP地址ID }) description = "(可选)文档中定义的ip_configuration块" default = null }
我尝试过dynamic块、lookup函数、try表达式等方案,都没有成功,已经花费数日调试仍未解决,恳请大家帮忙指点。
补充:已实现的可用方案
我目前找到了一个可用的实现方案,如果有更简洁的优化方案欢迎提出,感谢所有回复的朋友。由于subnet_id仅允许出现在第一个ip_configuration块中,因此我对变量的key使用了数字编号的处理逻辑,我的实现代码如下:
resource "azurerm_firewall" "example" { name = "testfirewall" location = azurerm_resource_group.example.location resource_group_name = azurerm_resource_group.example.name dynamic "ip_configuration" { for_each = var.ip_configuration iterator = ip content { name = ip.value["name"] subnet_id = ip.key == "0" ? ip.value["subnet_id"] : null public_ip_address_id = ip.value["public_ip_address_id"] } } } variable "ip_configuration" { type = map description = <<-EOT (可选)ip_configuration块为嵌套map结构,键名为0、1、2、3这类连续数字字符串,参数说明如下: name = string // IP配置的名称 public_ip_address_id = string // 和防火墙绑定的公网IP地址ID subnet_id = string // 和IP配置绑定的子网引用,防火墙使用的子网必须命名为AzureFirewallSubnet,掩码最小为/26 注意:仅键为"0"的配置项需要填写subnet_id属性 示例格式: { "0" = { name = "first_pip_configuration" public_ip_address_id = azurerm_public_ip.firstpip.id subnet_id = azurerm_subnet.example.id }, "1" = { name = "second_pip_configuration" public_ip_address_id = azurerm_public_ip.secondpip.id }, "2" = { name = "third_pip_configuration" public_ip_address_id = azurerm_public_ip.thirdpip.id } } EOT default = {} }
优化方案
你现有的实现已经可以满足需求,这里提供两个更易用的优化方向:
1. 变量强类型校验优化
你当前使用type = map没有类型约束,容易出现传参错误,可以替换为map(object)做强类型校验(Terraform 0.14+支持optional属性标记):
variable "ip_configuration" { type = map(object({ name = string public_ip_address_id = string subnet_id = optional(string) })) description = <<-EOT (可选)Azure防火墙的IP配置集合,要求如下: - 键名必须为从0开始的连续数字字符串 - 仅键为"0"的配置项需要传入subnet_id,其余配置项请勿传入该参数 - subnet对应的子网名称必须为AzureFirewallSubnet,掩码最小为/26 EOT default = {} }
传参时如果参数结构不符合要求,Terraform会直接在plan阶段报错,避免运行时错误。
2. 免数字键的简化调用方案
如果你不想让调用方手动写0、1、2的键,可以把变量改成列表类型,自动按索引判断第一个元素:
variable "ip_configuration" { type = list(object({ name = string public_ip_address_id = string subnet_id = optional(string) })) description = "(可选)Azure防火墙的IP配置列表,仅第一个元素需要配置subnet_id" default = [] } resource "azurerm_firewall" "example" { name = "testfirewall" location = azurerm_resource_group.example.location resource_group_name = azurerm_resource_group.example.name dynamic "ip_configuration" { for_each = var.ip_configuration content { name = ip_configuration.value.name subnet_id = ip_configuration.key == 0 ? ip_configuration.value.subnet_id : null public_ip_address_id = ip_configuration.value.public_ip_address_id } } }
调用时直接传列表即可,不需要手动写数字键,更易用:
ip_configuration = [ { name = "first_pip_configuration" public_ip_address_id = azurerm_public_ip.firstpip.id subnet_id = azurerm_subnet.example.id }, { name = "second_pip_configuration" public_ip_address_id = azurerm_public_ip.secondpip.id } ]
内容的提问来源于stack exchange,提问作者MorNando
相关产品推荐
相关产品推荐

