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.