Terraform: For Loop
Description:
The for
loop in terraform is used to transform one “complex object” into another “complex object”. Here are some examples. The main thing to pay attention to is the output of the loop:
- If you see
[ for b in blah ]
you know that the output will be alist
object by the[
and]
characters. Note that you can cast to a set by using thetoset()
function if passing to something else that requires a set. - If you see
{ for b in blah }
you know that the output will be amap
object by the{
and}
characters.
To Resolve:
-
Take one list, and loop through it to produce another list making transformations on each object. The example in the link shows for example transoforming a list of string to uppercase:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
terraform { required_version = "~>1.1.0" } variable "users" { description = "(Optional) List of users." type = list default = ["jim", "bob", "alice"] } locals { for_loop_users = [for s in var.users : upper(s)] } output "for_loop_users" { value = local.for_loop_users }
- Output
1 2 3 4 5 6
Changes to Outputs: + for_loop_users = [ + "JIM", + "BOB", + "ALICE", ]
-
Same thing, but lets filter to get rid of
alice
:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
terraform { required_version = "~>1.1.0" } variable "users" { description = "(Optional) List of users." type = list default = ["jim", "bob", "alice"] } locals { for_loop_users = [for s in var.users : upper(s) if s != "alice"] } output "for_loop_users" { value = local.for_loop_users }
- Output
1 2 3 4 5
Changes to Outputs: + for_loop_users = [ + "JIM", + "BOB" ]
-
Reading a little bit lower on that page, I thought I would test with their example where you have a map object coming in:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
terraform { required_version = "~>1.1.0" } variable "users" { description = "(Optional) List of users." type = map(object({ is_admin = bool })) default = { "Jim" = { is_admin = true } "Bob" = { is_admin = true } } } locals { admin_users = { for name, user in var.users : name => user if user.is_admin } regular_users = { for name, user in var.users : name => user if !user.is_admin } } output "display_admin_users" { value = local.admin_users } output "display_regular_users" { value = local.regular_users }
- Output
1 2 3 4 5 6 7 8 9 10
Changes to Outputs: + display_admin_users = { + Bob = { + is_admin = true } + Jim = { + is_admin = true } } + display_regular_users = {}
- Now try tweaking
true
andfalse
is_admin
values for either “Bob”/”Jim” or both and see how the outputs change.
-
Here is one that takes a list of map objects and creates child map objects using the name property from each object:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
terraform { required_version = "~>1.1.0" } variable "file_shares" { description = "(Optional) List of file shares." type = list default = [ { name = "smbfileshare1", quota = 50 }, { name = "smbfileshare2", quota = 50 } ] } locals { for_loop_shares = { for shares in var.file_shares : shares.name => shares } } output "for_loop_shares" { value = local.for_loop_shares }
- Output
1 2 3 4 5 6 7 8 9 10 11
Changes to Outputs: + for_loop_shares = { + smbfileshare1 = { + name = "smbfileshare1" + quota = 50 } + smbfileshare2 = { + name = "smbfileshare2" + quota = 50 } }
- And if you only wanted to get the quotas, try something like:
1 2 3 4 5
output "for_loop_quota" { value = { for k, v in local.for_loop_shares : k => v.quota } }
- Which will give you:
1 2 3 4 5
Changes to Outputs: + for_loop_quota = { + smbfileshare1 = 50 + smbfileshare2 = 50 }
- If you would just prefer a list in the output for some reason, do the same but target a list:
1 2 3 4 5
output "for_loop_quota" { value = [ for k in local.for_loop_shares : k.quota ] }
- Which will give you:
1 2 3 4 5
Changes to Outputs: + for_loop_quota = [ + 50, + 50, ]
Comments