Terraform for_each with YAML locals for Genesys Queues

How do I map a YAML variable file to a for_each block for creating queues?

We are trying to move away from hardcoding queue names in our Terraform scripts. I have a queues.yaml file that lists our WEM queues and their descriptions. The goal is to read this file and create a genesyscloud_routing_queue resource for each entry using for_each.

Here is the setup:

locals {
 queue_data = yamldecode(file("${path.module}/queues.yaml"))
}

resource "genesyscloud_routing_queue" "main" {
 for_each = local.queue_data

 name = each.value.name
 description = each.value.description
 enabled = true
}

The queues.yaml looks like this:

support_us:
 name: "US Support"
 description: "General US support queue"

sales_eu:
 name: "EU Sales"
 description: "European sales team"

When I run terraform plan, I get this error:

Error: Incorrect attribute value type

 on main.tf line 5, in resource "genesyscloud_routing_queue" "main":
 5: for_each = local.queue_data

Inappropriate value for attribute "for_each": map of object required.

I thought yamldecode would return a map. It seems the structure is not what Terraform expects for for_each. I’ve tried wrapping it in a toset or casting it, but the types don’t match up with the object structure needed for the resource arguments.

Is there a specific way to format the locals or the YAML so that for_each accepts the map of objects? We’ve been stuck on this type mismatch for a day.

The yamldecode function is your friend here, but you’ve got to make sure the output is a map, not a list. for_each needs a map or set to work properly. If your YAML looks like a simple list of objects, you’ll hit a wall because Terraform doesn’t know which key to use for the unique identifier.

Here’s how I structure my queues.yaml to make this painless:

queue_data:
 tech_support:
 name: "Tech Support"
 description: "Level 1 technical assistance"
 max_wait_time: 120
 sales_inbound:
 name: "Sales Inbound"
 description: "New lead intake"
 max_wait_time: 60

Notice the keys? tech_support and sales_inbound. Those are what for_each will iterate over. In your Terraform file, you’d do something like this:

locals {
 # Load the file and extract the map
 queues = yaml(file("${path.module}/queues.yaml"))["queue_data"]
}

resource "genesyscloud_routing_queue" "queue" {
 for_each = local.queues

 name = each.value.name
 description = each.value.description
 email {
 enabled = true
 address = "support-${each.key}@example.com" # Using the key here is handy
 }
}

If your YAML is already a list, like [{name: "A"}, {name: "B"}], you can convert it to a map using tomap and a helper function, but it’s usually easier to just write the YAML as a map from the start. Saves you from writing complex for expressions in HCL just to generate keys.

One thing to watch out for with state drift. If you remove a key from the YAML file, Terraform will try to destroy that queue. Make sure you’re comfortable with that behavior or use lifecycle { prevent_destroy = true } if you’re paranoid about accidental deletions. I usually keep a backup of the state file before running apply on queue changes. Just in case.