terraform understanding for_each vs for
Maybe one of the most often used construct in terraform are the for_each and for loop. Just to clarify these 2 constructs. In Terraform, for and for_each sound almost identical, but they serve entirely different purposes.
Here is the golden rule to tell them apart:
for_eachis a meta-argument used to duplicate resources or modules (it creates multiple infrastructure objects).foris a looping expression used to transform values within a resource attribute (it outputs a new list or map).
| Feature | for_each (Meta-argument) | for (Expression) |
| What it does | Multiplies resources/modules. | Transforms data structures. |
| Where it lives | Directly inside a resource or module block. | Inside an attribute assignment (e.g., tags = ...). |
| Accepted Inputs | set of strings, or a map. (Lists not allowed directly). | list, set, tuple, map. |
| Output | Multiple cloud resources. | A single list or map value. |
1. The for_each Meta-argument
Use for_each when you want to spin up multiple copies of the same resource based on a collection. When using for_each, Terraform gives you access to an each object:
each.key: The map key (or set value).each.value: The map value (or set value).
Example with a Map
Maps are the best fit for for_each because they allow you to pass complex configuration data for each individual resource.
Example with a List (Requires toset())
for_each does not accept a standard list because list indices can change, which causes Terraform to destroy and recreate resources unpredictably. If you have a list of strings, you must convert it to a set using toset().
2. The for Expression
Use for when you need to manipulate, filter, or transform data inside an attribute. It is always wrapped in brackets: [...] to output a list, or {...} to output a map.
Example with a List (Outputting a List)
Let's say you have a list of environment names, and you want to convert them all to uppercase to format them as tags.
1. The Map Constructor: { for ... : key => value }
When you wrap a for loop in curly braces { } and use the => operator, you are telling Terraform: "Take this data and output a Map."
2. The List Constructor: [ for ... : value ]
If you want to pull just the values (or just the keys) out of a map and turn them into a List, you must switch from curly braces { } to square brackets [ ], and drop the => operator.
(Note: In your snippet, you used curly braces without an arrow. In Terraform, writing { for name, role in var.roles : upper(role) } will actually throw a syntax error. To get a list/set, you must use square brackets).
Comments