Answers: <p>Following the documentation a <code>map</code> is a collection of key/values with a constraint:</p>
  <blockquote>
  <p>&quot;...accepts any element type as long as every element is the same type&quot; <a href="https://www.terraform.io/docs/configuration/types.html#map-" rel="nofollow noreferrer">source</a></p>
  </blockquote>
  <p>So the input map you have declared, is already an invalid map for Terraform 0.12 (at least)</p>
  <p>Below the example of the error produced:</p>
  <pre><code>variable &quot;cidrs&quot; {
    description = &quot;&quot;
    type        = map
    default = [
      [&quot;1.1.1.1&quot;],
      [&quot;2.2.2.2&quot;, &quot;3.3.3.3&quot;],
      {
        C = [&quot;4.4.4.4&quot;]
        D = [&quot;5.5.5.5&quot;]
      }]
  }
  </code></pre>
  <p>When validating an error is raised:</p>
  <pre><code>$&gt; terraform validate
  
  Error: Invalid default value for variable
  
    on vars.tf line 65, in variable &quot;cidrs&quot;:
    65:   default = [
    66:     [&quot;1.1.1.1&quot;],
    67:     [&quot;2.2.2.2&quot;, &quot;3.3.3.3&quot;],
    68:     {
    69:       C = [&quot;4.4.4.4&quot;]
    70:       D = [&quot;5.5.5.5&quot;]
    71:     }]
  
  This default value is not compatible with the variable's type constraint: map
  of any single type required.
  </code></pre>
  <p>Been that said, if we can generalize A and B as &quot;values which are lists&quot; and Group1 as &quot;values which are maps&quot; and the input is a fixed type ordered we can use a <em><a href="https://www.terraform.io/docs/configuration/types.html#tuple-" rel="nofollow noreferrer">tuple</a></em> or  an <em><a href="https://www.terraform.io/docs/configuration/types.html#object-" rel="nofollow noreferrer">object</a></em>, this can be solve in a more readable (and maintainable) way. If so, let us know so we can extend this answer.</p>
  
Answers: CC BY-SA 4.0
Answers: 2020-08-03T22:44:21.240Z
Answers: 2020-08-06T16:08:01.087Z
Answers: 2020-08-06T16:08:01.087Z
Answers: Rafael Aguilar
Body: <p>I want to take a map such as this that is passed in as a variable</p>
  <pre><code>cidrs = {
    A = [1.1.1.1]
    B = [2.2.2.2, 3.3.3.3]
    Group1 = {
      C = [4.4.4.4]
      D = [5.5.5.5]
    }
  }
  </code></pre>
  <p>and then within the locals section i want to sanitize it to the following</p>
  <pre><code>cidrs_sanitized = {
    A = [1.1.1.1]
    B = [2.2.2.2, 3.3.3.3]
    Group1 = [4.4.4.4, 5.5.5.5]
    C = [4.4.4.4]
    D = [5.5.5.5]
  }
  </code></pre>
  <p>I have tried various methods of looping</p>
  <p>everything i've tried so far has led to me trying to get each set of values as seperate variables and then merge them together example:</p>
  <pre><code>single = { A = [1.1.1.1], B = [2.2.2.2, 3.3.3.3] }
  groups = { Group1 = [4.4.4.4, 5.5.5.5] }
  grouped = { C = [4.4.4.4], D = [5.5.5.5] }
  cidrs_sanitized = merge(single, groups, grouped)
  </code></pre>
  <p>and here's some of the stuff i've tried but failed to succeed with</p>
  <pre><code>groups = flatten([ for range, value in var.cidrs: tomap({ range = values(value) }) if !can(element(value, 0)) ])
  single = flatten([ for range, value in var.cidrs: tomap({ range = value }) if can(element(value, 0)) ])
  </code></pre>
  <p>and</p>
  <pre><code>groups = {
    for range, value in var.ranges :
      range =&gt; can(values(value)) ? values(value) : null
  }
  grouped = flatten([for range in var.ranges : [
    for cidr_key, cidr in range : {
      cidr_key =&gt; cidr
    } if length(cidr) &gt; 0
  ] if can(values(range)) ])
  </code></pre>
  <p>The merge always fails as it tells me the output are tuples and i can't figure out how to get terraform to show me the values of the locals grouped, groups and single when calling it as a module</p>
  <p>Any help or points in the right direction would be appreciated, thanks.</p>
  
Tags: <terraform>
Title: Terraform: Sanitize a map that may be a map of strings or map of maps or combo of both
UserDisplayName: Cyber Axe
ThreadText: # Terraform: Sanitize a map that may be a map of strings or map of maps or combo of both
  
  (Asked by: username_0 on 2020-07-29)
  
  I want to take a map such as this that is passed in as a variable
  
  ```
  cidrs = {
    A = [1.1.1.1]
    B = [2.2.2.2, 3.3.3.3]
    Group1 = {
      C = [4.4.4.4]
      D = [5.5.5.5]
    }
  }
  
  ```
  
  and then within the locals section i want to sanitize it to the following
  
  ```
  cidrs_sanitized = {
    A = [1.1.1.1]
    B = [2.2.2.2, 3.3.3.3]
    Group1 = [4.4.4.4, 5.5.5.5]
    C = [4.4.4.4]
    D = [5.5.5.5]
  }
  
  ```
  
  I have tried various methods of looping
  
  everything i've tried so far has led to me trying to get each set of values as seperate variables and then merge them together example:
  
  ```
  single = { A = [1.1.1.1], B = [2.2.2.2, 3.3.3.3] }
  groups = { Group1 = [4.4.4.4, 5.5.5.5] }
  grouped = { C = [4.4.4.4], D = [5.5.5.5] }
  cidrs_sanitized = merge(single, groups, grouped)
  
  ```
  
  and here's some of the stuff i've tried but failed to succeed with
  
  ```
  groups = flatten([ for range, value in var.cidrs: tomap({ range = values(value) }) if !can(element(value, 0)) ])
  single = flatten([ for range, value in var.cidrs: tomap({ range = value }) if can(element(value, 0)) ])
  
  ```
  
  and
  
  ```
  groups = {
    for range, value in var.ranges :
      range => can(values(value)) ? values(value) : null
  }
  grouped = flatten([for range in var.ranges : [
    for cidr_key, cidr in range : {
      cidr_key => cidr
    } if length(cidr) > 0
  ] if can(values(range)) ])
  
  ```
  
  The merge always fails as it tells me the output are tuples and i can't figure out how to get terraform to show me the values of the locals grouped, groups and single when calling it as a module
  
  Any help or points in the right direction would be appreciated, thanks.
  
  **Tags:** terraform
  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2020-08-03. Score: 1
  
  Following the documentation a `map` is a collection of key/values with a constraint:
  
  > "...accepts any element type as long as every element is the same type" [source](https://www.terraform.io/docs/configuration/types.html#map-)
  
  So the input map you have declared, is already an invalid map for Terraform 0.12 (at least)
  
  Below the example of the error produced:
  
  ```
  variable "cidrs" {
    description = ""
    type        = map
    default = [
      ["1.1.1.1"],
      ["2.2.2.2", "3.3.3.3"],
      {
        C = ["4.4.4.4"]
        D = ["5.5.5.5"]
      }]
  }
  
  ```
  
  When validating an error is raised:
  
  ```
  $> terraform validate
  
  Error: Invalid default value for variable
  
    on vars.tf line 65, in variable "cidrs":
    65:   default = [
    66:     ["1.1.1.1"],
    67:     ["2.2.2.2", "3.3.3.3"],
    68:     {
    69:       C = ["4.4.4.4"]
    70:       D = ["5.5.5.5"]
    71:     }]
  
  This default value is not compatible with the variable's type constraint: map
  of any single type required.
  
  ```
  
  Been that said, if we can generalize A and B as "values which are lists" and Group1 as "values which are maps" and the input is a fixed type ordered we can use a *[tuple](https://www.terraform.io/docs/configuration/types.html#tuple-)* or an *[object](https://www.terraform.io/docs/configuration/types.html#object-)*, this can be solve in a more readable (and maintainable) way. If so, let us know so we can extend this answer.
  
  
  ---
  
  