DISCO
DISCO

Reputation: 357

Terraform is it possible to parse nested map with different keys?

I have a map like this:

root = {
      nat = {
        pr = {
          dev = [{
            value: "10.10.10.10",
            description: "test1"
          },
          ],
        },
        pr2 = {
          dev = [{
            value: "10.10.10.11",
            description: "test2"
          }],
          prod = [],
        }
      },
      cc = {
        pr = {
          jej = [{
            value: "10.10.10.10",
            description: "test"
          }]
        }
      },
      smt = {
        st = [{
          value = "10.10.10.10",
          description = "test"
        }],
        s2 = [{
          value = "10.10.10.10",
          description = "tt"
        }]
      }
    }

Which can be modified in future by adding new nested maps. That map will be in module. I will paste the path(key) in input of module like "root.nat" and will expect in output the array of objects, thats will be all arrays of objects in "root.nat", sample of output:

[{
value = "10.10.10.10",
description = "test1"
},
{
value = "10.10.10.11",
description = "test2"
},
]

The problem is actually, that I cannot know how many nested maps I will have when inputing the path(key). And I can't iterate using for, cause I don't know exact fields. Is it actually possible?

Upvotes: 0

Views: 900

Answers (2)

Martin Atkins
Martin Atkins

Reputation: 74249

Terraform isn't designed for this sort of general computation. This particular problem requires unbounded recursion and that in particular isn't available in the Terraform language: Terraform always expects to be dealing with fixed data structures whose shape is known statically as part of their type.

If possible I would suggest using something outside of Terraform to preprocess this data structure into a flat map from dot-separated string key to a list of objects:

{
  "root.nat" = [
    {
      value       = "10.10.10.11",
      description = "test2"
    },
    # etc
  ]
  # etc
}

If you cannot avoid doing this transformation inside Terraform -- for example, if the arbitrary data structure you showed is being loaded dynamically from some other service rather than fixed in your configuration, so that it's not possible to pre-generate the flattened equivalent -- then you could use my Terraform provider apparentlymart/javascript as an escape hatch to the JavaScript programming language, and implement your flattening algorithm in JavaScript rather than in the Terraform language.

Since JavaScript is a general-purpose language, you can write a recursive algorithm to re-arrange your data structure into a flat map of lists of objects with dot-separated keys, and then look up those keys in Terraform code using the index operator as normal.

Upvotes: 1

Leo
Leo

Reputation: 538

Check my answer for this This Question.

Basically, you can create as many for loops inside each other as you believe it will be necessary.

As long you check for null before proceeding to the next loop the code won't fail.

So in cases like this:

pr2 = {
  dev = [{
    value: "10.10.10.11",
    description: "test2"
  }],
  prod = [],

prod would not be part of the final array.

Additionally, you can always add try functions in your verification if null to find out if you are in the right "level" of the loop.

Upvotes: 0

Related Questions