Reputation: 63
I am trying to create some simple logic when calling applicationg gateway module.
When creating WAF v2 application gateway I want to specify more attributes that simple application gateway can't handle and they won't be described.
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 }"
............
Calling module:
module "GWdemo" {
source = "./...."
sku-name = "WAF_v2"
sku-tier = "WAF_v2"
sku-capacity = 1
waf-configuration = [
{
enabled = true
firewall_mode = "Detection"
}
Am I thinking right that if waf-configuration map is specified it should specify following settings is applied and if not than null?
Upvotes: 0
Views: 7316
Reputation: 74694
When working with Terraform we often want to reframe problems involving a conditional test into problems involving a collection that may or may not contain elements, because the Terraform language features are oriented around transforming collections into configuration on an element-by-element basis.
In your case, you have a variable that is already a list, so it could work to just ensure that its default value is an empty list rather than null
, and thus that you can just generate one waf_configuration
block per element:
variable "waf_configuration" {
type = list(object({
enabled = bool
firewall_mode = string
}))
default = []
}
Then you can use a dynamic
block to generate one waf_configuration
block per element of that list:
dynamic "waf_configuration" {
for_each = var.waf_configuration
content {
enabled = waf_configuration.value.enabled
firewall_mode = waf_configuration.value.firewall_mode
}
}
Although it doesn't seem to apply to this particular example, another common pattern is a variable that can be set to enable something or left unset to disable it. For example, if your module was designed to take only a single optional WAF configuration, you might define the variable like this:
variable "waf_configuration" {
type = object({
enabled = bool
firewall_mode = string
})
default = null
}
As noted above, the best way to work with something like that in Terraform is to recast it as a list that might be empty. Because it's a common situation, there is a shorthand for it via splat expressions:
dynamic "waf_configuration" {
for_each = var.waf_configuration[*]
content {
enabled = waf_configuration.value.enabled
firewall_mode = waf_configuration.value.firewall_mode
}
}
When we apply the [*]
operator to a value of a non-list/non-set type, Terraform will test to see if the value is null
. If it is null then the result will be an empty list, while if it is not null then the result will be a single-element list containing that one value.
After converting to a list we can then use it in the for_each
argument to dynamic
in the usual way, accessing the attributes from that possible single element inside the content
block. We don't need to repeat the conditionals for each argument because the content
block contents are evaluated only when the list is non-empty.
Upvotes: 3
Reputation: 3347
I would encourage you to upgrade to Terraform v0.12.x and this should get a much easier to do. I would leverage the new dynamic block syntax to make the block optional based on whatever condition you need to use.
Here is a rough example, but should get you going in the correct direction.
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 }"
}
}
Upvotes: 1