Home > Software engineering >  Terraform: How do I use for_each over a comma-delimited string in a dynamic block?
Terraform: How do I use for_each over a comma-delimited string in a dynamic block?

Time:02-02

I am writing an Azure Function app module which is causing me some trouble. I want to add multiple ip_restriction blocks using a for_each, iterating over a comma-delimited string, but I'm missing out on something here.

Given the following block (with random IP CIDR blocks)

resource "azurerm_windows_function_app" "this" {
...
    dynamic "ip_restriction" {
      for_each         = split(",", "1.2.3.4/28,2.3.4.5/28")
      content {
        ip_address = {          

          ip_address    = ip_restriction.value
        }
      }
    }  
...

I get the following error:

Inappropriate value for attribute "ip_address": string required

I get the error twice which tells me that the iterator has tried, and failed twice to retrieve the value using '.value'

I've read https://developer.hashicorp.com/terraform/language/expressions/dynamic-blocks (of course) and tried various things for a few hours now without being able to figure out why 'value' seems empty.

How do I retrieve the distinct CIDR address if .value isn't the right thing to do?

CodePudding user response:

The for_each meta-argument accepts a map or a set of strings. What you are currently providing is a list of strings. If you are not hardcoding the values as in your example, you could create a local variable:

locals {
  ip_addresses = split(",", "1.2.3.4/28,2.3.4.5/28")
}

Then, in the dynamic block, you can use that local variable and cast it to a set with toset [1]:

resource "azurerm_windows_function_app" "this" {
...
    dynamic "ip_restriction" {
      for_each         = toset(local.ip_addresses)
      content {
          ip_address    = ip_restriction.value
        }
    }  
...

If you do not want to do that, you can do the conversion like this:

resource "azurerm_windows_function_app" "this" {
...
    dynamic "ip_restriction" {
      for_each         = toset(split(",", "1.2.3.4/28,2.3.4.5/28"))
      content {
        ip_address    = ip_restriction.value
        }
    }  
...

[1] https://developer.hashicorp.com/terraform/language/functions/toset

CodePudding user response:

Dammit... A collegue of mine found the error, it was sitting approx. 40 inches from the keyboard :o)

It was a syntax beef, I had wrapped the "ip_address" block in an "ip_address" block

The correct code is:

    dynamic "ip_restriction" {
      for_each  = split(",", var.ip_restriction_allow_ip_range)

      content {
        ip_address  = ip_restriction.value
        name        = "github_largerunner"
      }
    } 
  • Related