github.com/muratcelep/terraform@v1.1.0-beta2-not-internal-4/website/docs/language/expressions/for.html.md (about) 1 --- 2 layout: "language" 3 page_title: "For Expressions - Configuration Language" 4 description: "For expressions transform complex input values into complex output values. Learn how to filter inputs and how to group results." 5 --- 6 7 # `for` Expressions 8 9 A _`for` expression_ creates a complex type value by transforming 10 another complex type value. Each element in the input value 11 can correspond to either one or zero values in the result, and an arbitrary 12 expression can be used to transform each input element into an output element. 13 14 For example, if `var.list` were a list of strings, then the following expression 15 would produce a tuple of strings with all-uppercase letters: 16 17 ```hcl 18 [for s in var.list : upper(s)] 19 ``` 20 21 This `for` expression iterates over each element of `var.list`, and then 22 evaluates the expression `upper(s)` with `s` set to each respective element. 23 It then builds a new tuple value with all of the results of executing that 24 expression in the same order. 25 26 ## Input Types 27 28 A `for` expression's input (given after the `in` keyword) can be a list, 29 a set, a tuple, a map, or an object. 30 31 The above example showed a `for` expression with only a single temporary 32 symbol `s`, but a `for` expression can optionally declare a pair of temporary 33 symbols in order to use the key or index of each item too: 34 35 ```hcl 36 [for k, v in var.map : length(k) + length(v)] 37 ``` 38 39 For a map or object type, like above, the `k` symbol refers to the key or 40 attribute name of the current element. You can also use the two-symbol form 41 with lists and tuples, in which case the additional symbol is the index 42 of each element starting from zero, which conventionally has the symbol name 43 `i` or `idx` unless it's helpful to choose a more specific name: 44 45 ```hcl 46 [for i, v in var.list : "${i} is ${v}"] 47 ``` 48 49 The index or key symbol is always optional. If you specify only a single 50 symbol after the `for` keyword then that symbol will always represent the 51 _value_ of each element of the input collection. 52 53 ## Result Types 54 55 The type of brackets around the `for` expression decide what type of result 56 it produces. 57 58 The above example uses `[` and `]`, which produces a tuple. If you use `{` and 59 `}` instead, the result is an object and you must provide two result 60 expressions that are separated by the `=>` symbol: 61 62 ```hcl 63 {for s in var.list : s => upper(s)} 64 ``` 65 66 This expression produces an object whose attributes are the original elements 67 from `var.list` and their corresponding values are the uppercase versions. 68 For example, the resulting value might be as follows: 69 70 ```hcl 71 { 72 foo = "FOO" 73 bar = "BAR" 74 baz = "BAZ" 75 } 76 ``` 77 78 A `for` expression alone can only produce either an object value or a tuple 79 value, but Terraform's automatic type conversion rules mean that you can 80 typically use the results in locations where lists, maps, and sets are expected. 81 82 ## Filtering Elements 83 84 A `for` expression can also include an optional `if` clause to filter elements 85 from the source collection, producing a value with fewer elements than 86 the source value: 87 88 ``` 89 [for s in var.list : upper(s) if s != ""] 90 ``` 91 92 One common reason for filtering collections in `for` expressions is to split 93 a single source collection into two separate collections based on some 94 criteria. For example, if the input `var.users` is a map of objects where the 95 objects each have an attribute `is_admin` then you may wish to produce separate 96 maps with admin vs non-admin objects: 97 98 ```hcl 99 variable "users" { 100 type = map(object({ 101 is_admin = bool 102 })) 103 } 104 105 locals { 106 admin_users = { 107 for name, user in var.users : name => user 108 if user.is_admin 109 } 110 regular_users = { 111 for name, user in var.users : name => user 112 if !user.is_admin 113 } 114 } 115 ``` 116 117 ## Element Ordering 118 119 Because `for` expressions can convert from unordered types (maps, objects, sets) 120 to ordered types (lists, tuples), Terraform must choose an implied ordering 121 for the elements of an unordered collection. 122 123 For maps and objects, Terraform sorts the elements by key or attribute name, 124 using lexical sorting. 125 126 For sets of strings, Terraform sorts the elements by their value, using 127 lexical sorting. 128 129 For sets of other types, Terraform uses an arbitrary ordering that may change 130 in future versions of Terraform. For that reason, we recommend converting the 131 result of such an expression to itself be a set so that it's clear elsewhere 132 in the configuration that the result is unordered. You can use 133 [the `toset` function](/docs/language/functions/toset.html) 134 to concisely convert a `for` expression result to be of a set type. 135 136 ```hcl 137 toset([for e in var.set : e.example]) 138 ``` 139 140 ## Grouping Results 141 142 If the result type is an object (using `{` and `}` delimiters) then normally 143 the given key expression must be unique across all elements in the result, 144 or Terraform will return an error. 145 146 Sometimes the resulting keys are _not_ unique, and so to support that situation 147 Terraform supports a special _grouping mode_ which changes the result to support 148 multiple elements per key. 149 150 To activate grouping mode, add the symbol `...` after the value expression. 151 For example: 152 153 ```hcl 154 variable "users" { 155 type = map(object({ 156 role = string 157 })) 158 } 159 160 locals { 161 users_by_role = { 162 for name, user in var.users : user.role => name... 163 } 164 } 165 ``` 166 167 The above represents a situation where a module expects a map describing 168 various users who each have a single "role", where the map keys are usernames. 169 The usernames are guaranteed unique because they are map keys in the input, 170 but many users may all share a single role name. 171 172 The `local.users_by_role` expression inverts the input map so that the keys 173 are the role names and the values are usernames, but the expression is in 174 grouping mode (due to the `...` after `name`) and so the result will be a 175 map of lists of strings, such as the following: 176 177 ```hcl 178 { 179 "admin": [ 180 "ps", 181 ], 182 "maintainer": [ 183 "am", 184 "jb", 185 "kl", 186 "ma", 187 ], 188 "viewer": [ 189 "st", 190 "zq", 191 ], 192 } 193 ``` 194 195 Due to [the element ordering rules](#element-ordering), Terraform will sort 196 the users lexically by username as part of evaluating the `for` expression, 197 and so the usernames associated with each role will be lexically sorted 198 after grouping. 199 200 ## Repeated Configuration Blocks 201 202 The `for` expressions mechanism is for constructing collection values from 203 other collection values within expressions, which you can then assign to 204 individual resource arguments that expect complex values. 205 206 Some resource types also define _nested block types_, which typically represent 207 separate objects that belong to the containing resource in some way. You can't 208 dynamically generate nested blocks using `for` expressions, but you _can_ 209 generate nested blocks for a resource dynamically using 210 [`dynamic` blocks](dynamic-blocks.html).