github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/website/content/docs/job-specification/hcl2/functions/collection/setproduct.mdx (about)

     1  ---
     2  layout: docs
     3  page_title: setproduct - Functions - Configuration Language
     4  description: |-
     5    The setproduct function finds all of the possible combinations of elements
     6    from all of the given sets by computing the cartesian product.
     7  ---
     8  
     9  # `setproduct` Function
    10  
    11  The `setproduct` function finds all of the possible combinations of elements
    12  from all of the given sets by computing the
    13  [Cartesian product](https://en.wikipedia.org/wiki/Cartesian_product).
    14  
    15  ```hcl
    16  setproduct(sets...)
    17  ```
    18  
    19  This function is particularly useful for finding the exhaustive set of all
    20  combinations of members of multiple sets, such as per-application-per-environment
    21  resources.
    22  
    23  ```shell-session
    24  > setproduct(["development", "staging", "production"], ["app1", "app2"])
    25  [
    26    [
    27      "development",
    28      "app1",
    29    ],
    30    [
    31      "development",
    32      "app2",
    33    ],
    34    [
    35      "staging",
    36      "app1",
    37    ],
    38    [
    39      "staging",
    40      "app2",
    41    ],
    42    [
    43      "production",
    44      "app1",
    45    ],
    46    [
    47      "production",
    48      "app2",
    49    ],
    50  ]
    51  ```
    52  
    53  You must past at least two arguments to this function.
    54  
    55  Although defined primarily for sets, this function can also work with lists.
    56  If all of the given arguments are lists then the result is a list, preserving
    57  the ordering of the given lists. Otherwise the result is a set. In either case,
    58  the result's element type is a list of values corresponding to each given
    59  argument in turn.
    60  
    61  ## Examples
    62  
    63  There is an example of the common usage of this function above. There are some
    64  other situations that are less common when hand-writing but may arise in
    65  reusable folder situations.
    66  
    67  If any of the arguments is empty then the result is always empty itself,
    68  similar to how multiplying any number by zero gives zero:
    69  
    70  ```shell-session
    71  > setproduct(["development", "staging", "production"], [])
    72  []
    73  ```
    74  
    75  Similarly, if all of the arguments have only one element then the result has
    76  only one element, which is the first element of each argument:
    77  
    78  ```shell-session
    79  > setproduct(["a"], ["b"])
    80  [
    81    [
    82      "a",
    83      "b",
    84    ],
    85  ]
    86  ```
    87  
    88  Each argument must have a consistent type for all of its elements. If not,
    89  Nomad will attempt to convert to the most general type, or produce an
    90  error if such a conversion is impossible. For example, mixing both strings and
    91  numbers results in the numbers being converted to strings so that the result
    92  elements all have a consistent type:
    93  
    94  ```shell-session
    95  > setproduct(["staging", "production"], ["a", 2])
    96  [
    97    [
    98      "staging",
    99      "a",
   100    ],
   101    [
   102      "staging",
   103      "2",
   104    ],
   105    [
   106      "production",
   107      "a",
   108    ],
   109    [
   110      "production",
   111      "2",
   112    ],
   113  ]
   114  ```
   115  
   116  <!---
   117  
   118  ## TODO: Revamp this section
   119  
   120  ## Finding combinations for `for_each`
   121  
   122  The
   123  [resource `for_each`](https://www.terraform.io/docs/configuration/resources.html#for_each-multiple-resource-instances-defined-by-a-map-or-set-of-strings)
   124  and
   125  [`dynamic` block](/docs/job-specification/hcl2/expressions/#dynamic-blocks)
   126  language features both require a collection value that has one element for
   127  each repetition.
   128  
   129  Sometimes your input data comes in separate values that cannot be directly
   130  used in a `for_each` argument, and `setproduct` can be a useful helper function
   131  for the situation where you want to find all unique combinations of elements in
   132  a number of different collections.
   133  
   134  For example, consider a folder that declares variables like the following:
   135  
   136  ```hcl
   137  variable "networks" {
   138    type = map(object({
   139      base_cidr_block = string
   140    }))
   141  }
   142  
   143  variable "subnets" {
   144    type = map(object({
   145      number = number
   146    }))
   147  }
   148  ```
   149  
   150  If the goal is to create each of the defined subnets per each of the defined
   151  networks, creating the top-level networks can directly use `var.networks`
   152  because it's already in a form where the resulting instances match one-to-one
   153  with map elements:
   154  
   155  ```hcl
   156  resource "aws_vpc" "example" {
   157    for_each = var.networks
   158  
   159    cidr_block = each.value.base_cidr_block
   160  }
   161  ```
   162  
   163  However, in order to declare all of the _subnets_ with a single `resource`
   164  block, we must first produce a collection whose elements represent all of
   165  the combinations of networks and subnets, so that each element itself
   166  represents a subnet:
   167  
   168  ```hcl
   169  locals {
   170    # setproduct works with sets and lists, but our variables are both maps
   171    # so we'll need to convert them first.
   172    networks = [
   173      for key, network in var.networks : {
   174        key        = key
   175        cidr_block = network.cidr_block
   176      }
   177    ]
   178    subnets = [
   179      for key, subnet in var.subnets : {
   180        key    = key
   181        number = subnet.number
   182      }
   183    ]
   184  
   185    network_subnets = [
   186      # in pair, element zero is a network and element one is a subnet,
   187      # in all unique combinations.
   188      for pair in setproduct(local.networks, local.subnets) : {
   189        network_key = pair[0].key
   190        subnet_key  = pair[1].key
   191        network_id  = aws_vpc.example[pair[0].key].id
   192  
   193        # The cidr_block is derived from the corresponding network. See the
   194        # cidrsubnet function for more information on how this calculation works.
   195        cidr_block = cidrsubnet(pair[0].cidr_block, 4, pair[1].number)
   196      }
   197    ]
   198  }
   199  
   200  resource "aws_subnet" "example" {
   201    # local.network_subnets is a list, so we must now project it into a map
   202    # where each key is unique. We'll combine the network and subnet keys to
   203    # produce a single unique key per instance.
   204    for_each = {
   205      for subnet in local.network_subnets : "${subnet.network_key}.${subnet.subnet_key}" => subnet
   206    }
   207  
   208    vpc_id            = each.value.network_id
   209    availability_zone = each.value.subnet_key
   210    cidr_block        = each.value_cidr_block
   211  }
   212  ```
   213  
   214  The above results in one subnet instance per combination of network and subnet
   215  elements in the input variables.
   216  
   217  -->
   218  
   219  ## Related Functions
   220  
   221  - [`contains`](/docs/job-specification/hcl2/functions/collection/contains) tests whether a given list or set contains
   222    a given element value.
   223  - [`flatten`](/docs/job-specification/hcl2/functions/collection/flatten) is useful for flattening hierarchical data
   224    into a single list, for situations where the relationships between two
   225    object types are defined explicitly.
   226  - [`setintersection`](/docs/job-specification/hcl2/functions/collection/setintersection) computes the _intersection_ of
   227    multiple sets.
   228  - [`setunion`](/docs/job-specification/hcl2/functions/collection/setunion) computes the _union_ of multiple
   229    sets.