github.com/rstandt/terraform@v0.12.32-0.20230710220336-b1063613405c/website/docs/configuration/functions/flatten.html.md (about)

     1  ---
     2  layout: "functions"
     3  page_title: "flatten - Functions - Configuration Language"
     4  sidebar_current: "docs-funcs-collection-flatten"
     5  description: |-
     6    The flatten function eliminates nested lists from a list.
     7  ---
     8  
     9  # `flatten` Function
    10  
    11  -> **Note:** This page is about Terraform 0.12 and later. For Terraform 0.11 and
    12  earlier, see
    13  [0.11 Configuration Language: Interpolation Syntax](../../configuration-0-11/interpolation.html).
    14  
    15  `flatten` takes a list and replaces any elements that are lists with a
    16  flattened sequence of the list contents.
    17  
    18  ## Examples
    19  
    20  ```
    21  > flatten([["a", "b"], [], ["c"]])
    22  ["a", "b", "c"]
    23  ```
    24  
    25  If any of the nested lists also contain directly-nested lists, these too are
    26  flattened recursively:
    27  
    28  ```
    29  > flatten([[["a", "b"], []], ["c"]])
    30  ["a", "b", "c"]
    31  ```
    32  
    33  Indirectly-nested lists, such as those in maps, are _not_ flattened.
    34  
    35  ## Flattening nested structures for `for_each`
    36  
    37  The
    38  [resource `for_each`](/docs/configuration/resources.html#for_each-multiple-resource-instances-defined-by-a-map-or-set-of-strings)
    39  and
    40  [`dynamic` block](/docs/configuration/expressions.html#dynamic-blocks)
    41  language features both require a collection value that has one element for
    42  each repetition.
    43  
    44  Sometimes your input data structure isn't naturally in a suitable shape for
    45  use in a `for_each` argument, and `flatten` can be a useful helper function
    46  when reducing a nested data structure into a flat one.
    47  
    48  For example, consider a module that declares a variable like the following:
    49  
    50  ```hcl
    51  variable "networks" {
    52    type = map(object({
    53      cidr_block = string
    54      subnets = map(object({
    55        cidr_block = string
    56      })
    57    })
    58  }
    59  ```
    60  
    61  The above is a reasonable way to model objects that naturally form a tree,
    62  such as top-level networks and their subnets. The repetition for the top-level
    63  networks can use this variable directly, because it's already in a form
    64  where the resulting instances match one-to-one with map elements:
    65  
    66  ```hcl
    67  resource "aws_vpc" "example" {
    68    for_each = var.networks
    69  
    70    cidr_block = each.value.cidr_block
    71  }
    72  ```
    73  
    74  However, in order to declare all of the _subnets_ with a single `resource`
    75  block, we must first flatten the structure to produce a collection where each
    76  top-level element represents a single subnet:
    77  
    78  ```hcl
    79  locals {
    80    # flatten ensures that this local value is a flat list of objects, rather
    81    # than a list of lists of objects.
    82    network_subnets = flatten([
    83      for network_key, network in var.networks : [
    84        for subnet_key, subnet in network.subnets : {
    85          network_key = network_key
    86          subnet_key  = subnet_key
    87          network_id  = aws_vpc.example[network_key].id
    88          cidr_block  = subnet.cidr_block
    89        }
    90      ]
    91    ])
    92  }
    93  
    94  resource "aws_subnet" "example" {
    95    # local.network_subnets is a list, so we must now project it into a map
    96    # where each key is unique. We'll combine the network and subnet keys to
    97    # produce a single unique key per instance.
    98    for_each = {
    99      for subnet in local.network_subnets : "${subnet.network_key}.${subnet.subnet_key}" => subnet
   100    }
   101  
   102    vpc_id            = each.value.network_id
   103    availability_zone = each.value.subnet_key
   104    cidr_block        = each.value_cidr_block
   105  }
   106  ```
   107  
   108  The above results in one subnet instance per subnet object, while retaining
   109  the associations between the subnets and their containing networks.
   110  
   111  ## Related Functions
   112  
   113  * [`setproduct`](./setproduct.html) finds all of the combinations of multiple
   114    lists or sets of values, which can also be useful when preparing collections
   115    for use with `for_each` constructs.