diff --git a/website/docs/configuration/expressions.html.md b/website/docs/configuration/expressions.html.md index 040e2f732..1d0e1bdc4 100644 --- a/website/docs/configuration/expressions.html.md +++ b/website/docs/configuration/expressions.html.md @@ -578,6 +578,17 @@ together results that have a common key: {for s in var.list : substr(s, 0, 1) => s... if s != ""} ``` +For expressions are particularly useful when combined with other language +features to combine collections together in various ways. For example, +the following two patterns are commonly used when constructing map values +to use with [resource `for_each`](./resources.html#for_each-multiple-resource-instances-defined-by-a-map-or-set-of-strings): + +* Transform a multi-level nested structure into a flat list by + [using nested `for` expressions with the `flatten` function](./functions/flatten.html#flattening-nested-structures-for-for_each). +* Produce an exhaustive list of combinations of elements from two or more + collections by + [using the `setproduct` function inside a `for` expression](./functions/setproduct.html#finding-combinations-for-for_each). + ## Splat Expressions A _splat expression_ provides a more concise way to express a common diff --git a/website/docs/configuration/resources.html.md b/website/docs/configuration/resources.html.md index c2116a196..981772d10 100644 --- a/website/docs/configuration/resources.html.md +++ b/website/docs/configuration/resources.html.md @@ -376,6 +376,27 @@ This object has two attributes: - `each.value` — The map value corresponding to this instance. (If a set was provided, this is the same as `each.key`.) +#### Using Expressions in `for_each` + +The `for_each` meta-argument accepts map or set [expressions](./expressions.html). +However, unlike most resource arguments, the `for_each` value must be known +_before_ Terraform performs any remote resource actions. This means `for_each` +can't refer to any resource attributes that aren't known until after a +configuration is applied (such as a unique ID generated by the remote API when +an object is created). + +The `for_each` value must be a map or set with one element per desired +resource instance. If you need to declare resource instances based on a nested +data structure or combinations of elements from multiple data structures you +can use Terraform expressions and functions to derive a suitable value. +For example: + +* Transform a multi-level nested structure into a flat list by + [using nested `for` expressions with the `flatten` function](./functions/flatten.html#flattening-nested-structures-for-for_each). +* Produce an exhaustive list of combinations of elements from two or more + collections by + [using the `setproduct` function inside a `for` expression](./functions/setproduct.html#finding-combinations-for-for_each). + #### Referring to Instances When `for_each` is set, Terraform distinguishes between the resource block itself @@ -396,16 +417,19 @@ as a whole. #### Using Sets The Terraform language doesn't have a literal syntax for -[sets](./types.html#collection-types), but you can use the `toset` function to -convert a list of strings to a set: +[set values](./types.html#collection-types), but you can use the `toset` +function to explicitly convert a list of strings to a set: ```hcl -variable "subnet_ids" { - type = list(string) +locals { + subnet_ids = toset([ + "subnet-abcdef", + "subnet-012345", + ]) } resource "aws_instance" "server" { - for_each = toset(var.subnet_ids) + for_each = local.subnet_ids ami = "ami-a1b2c3d4" instance_type = "t2.micro" @@ -417,24 +441,26 @@ resource "aws_instance" "server" { } ``` -#### Using Expressions in `for_each` +Conversion from list to set discards the ordering of the items in the list and +removes any duplicate elements. `toset(["b", "a", "b"])` will produce a set +containing only `"a"` and `"b"` in no particular order; the second `"b"` is +discarded. -The `for_each` meta-argument accepts map or set [expressions](./expressions.html). -However, unlike most resource arguments, the `for_each` value must be known -_before_ Terraform performs any remote resource actions. This means `for_each` -can't refer to any resource attributes that aren't known until after a -configuration is applied (such as a unique ID generated by the remote API when -an object is created). +If you are writing a module with an [input variable](./variables.html) that +will be used as a set of strings for `for_each`, you can set its type to +`set(string)` to avoid the need for an explicit type conversion: -The `for_each` value must be a map or set with one element per desired -resource instance. If you need to declare resource instances based on a nested -data structure or combinations of elements from multiple data structures you -can use Terraform expressions and functions to derive a suitable value. -For some common examples of such situations, see the -[`flatten`](/docs/configuration/functions/flatten.html) -and -[`setproduct`](/docs/configuration/functions/setproduct.html) -functions. +``` +variable "subnet_ids" { + type = set(string) +} + +resource "aws_instance" "server" { + for_each = var.subnet_ids + + # (and the other arguments as above) +} +``` ### `provider`: Selecting a Non-default Provider Configuration