模块中的 Terraform 条件

Terraform conditions in a module

我正在尝试在调用 applicationg 网关模块时创建一些简单的逻辑。

在创建WAF v2应用网关时,我想指定更多简单应用网关无法处理的属性,不再描述。

resource "azurerm_application_gateway" {
  name                = var.appgatewayname
  resource_group_name = data.azurerm_resource_group.rg.name
  location            = data.azurerm_resource_group.rg.location

......................

  waf_configuration {
    enabled                  = "${length(var.waf_configuration) > 0 ? lookup(var.waf_configuration, "enabled", "") : null }"
    firewall_mode            = "${length(var.waf_configuration) > 0 ? lookup(var.waf_configuration, "firewall_mode", "") : null }"
............

调用模块:

module "GWdemo" {
  source      = "./...."

  sku-name     = "WAF_v2"
  sku-tier     = "WAF_v2"
  sku-capacity = 1
  waf-configuration = [
    {
      enabled                  = true
      firewall_mode            = "Detection"
}

如果指定了 waf-configuration map,我认为是否正确,它应该指定应用以下设置,如果不是 null?

我鼓励您升级到 Terraform v0。12.x 这应该会更容易做到。我会利用新的动态块语法根据您需要使用的任何条件使块可选。

这是一个粗略的示例,但应该能让您朝着正确的方向前进。

dynamic "waf-configuration " {
  for_each = length(var.waf_configuration) > 0 ? [] : [1]
  content {
    enabled       = "${length(var.waf_configuration) > 0 ? lookup(var.waf_configuration, "enabled", "") : null }"
    firewall_mode = "${length(var.waf_configuration) > 0 ? lookup(var.waf_configuration, "firewall_mode", "") : null }"
  }
}

在使用 Terraform 时,我们经常希望将涉及条件测试的问题重新构建为涉及可能包含或可能不包含元素的集合的问题,因为 Terraform 语言功能的目标是将集合转换为逐个元素的配置元素基础。

在你的例子中,你有一个已经是列表的变量,所以它可以确保它的默认值是一个空列表而不是 null,因此你可以只生成一个waf_configuration 每个元素块:

variable "waf_configuration" {
  type = list(object({
    enabled       = bool
    firewall_mode = string
  }))
  default = []
}

然后您可以使用 dynamic block 为该列表的每个元素生成一个 waf_configuration 块:

  dynamic "waf_configuration" {
    for_each = var.waf_configuration
    content {
      enabled       = waf_configuration.value.enabled
      firewall_mode = waf_configuration.value.firewall_mode
    }
  }

虽然它似乎不适用于这个特定的例子,但另一个常见的模式是一个变量,可以设置为启用某些东西或不设置以禁用它。例如,如果您的模块设计为仅采用 单个 可选 WAF 配置,您可以像这样定义变量:

variable "waf_configuration" {
  type = object({
    enabled       = bool
    firewall_mode = string
  })
  default = null
}

如上所述,在 Terraform 中处理类似内容的最佳方法是将其重铸为一个可能为空的列表。因为这是常见的情况,所以有一个 shorthand 通过 splat expressions:

  dynamic "waf_configuration" {
    for_each = var.waf_configuration[*]
    content {
      enabled       = waf_configuration.value.enabled
      firewall_mode = waf_configuration.value.firewall_mode
    }
  }

当我们将 [*] 运算符应用于 non-list/non-set 类型的值时,Terraform 将测试该值是否为 null。如果它 is null 那么结果将是一个空列表,而如果它是 not null 那么结果将是一个单元素列表包含那一个值。

转换为列表后,我们可以用通常的方式在 dynamicfor_each 参数中使用它,访问 content 块内可能的单个元素的属性.我们不需要为每个参数重复条件,因为 content 块内容仅在列表非空时才被评估。