Home > other >  terraform `map` alternative when duplicated keys should raise error
terraform `map` alternative when duplicated keys should raise error

Time:10-28

Given that:

As described also in https://github.com/hashicorp/terraform/issues/28727, if we have duplicated keys in a map, we get NO error:

quoting below from github issue

locals {
  local_dbs = {
    db1 = { a = "1a" }
    db1 = { a = "2a" }    // notice the key here is the same as the previous (e.g. a mistake)
    db3 = { a = "3a" }
  }
}

output locals_map_out {
  value = local.local_dbs
}

The above produces these outputs

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

Outputs:

locals_map_out = {
  "db1" = {
    "a" = "2a"
  }
  "db3" = {
    "a" = "3a"
  }
}

Notice the loss of the 1st db1 map entry. There was no error and no warning. It just silently replaced the 1st map entry with the 2nd.

end of quoting from github issue

My question is:

What would be a good (similar looking, elegant, few lines of code) alternative to using the map that would raise an error case duplicated "keys"?

Ex. A list of maps validation code?

locals {
  local_dbs = [
    {db1 = { a = "1a" }},
    {db1 = { a = "2a" }},   // notice the key here is the same as the previous (e.g. a mistake)
    {db3 = { a = "3a" }},
  ]

  // code that raises error?
}

output locals_map_out {
  value = local.local_dbs
}

Thank you.

CodePudding user response:

There are no custom errors or exceptions in TF, but one way to check for duplicates, would be to get a list of unique keys, and then try to access the last element. If all keys are really unique, the operation will succeed. If not, it errors out:

locals {
  local_dbs = [
    {db1 = { a = "1a" }},
    {db1 = { a = "2a" }},   // notice the key here is the same as the previous (e.g. a mistake)
    {db3 = { a = "3a" }},
  ]

  check_duplicatates = distinct([for v in local.local_dbs: keys(v)])[length(local.local_dbs)-1]
}

update

With output as @MarkoE suggested:

output "check_duplicatates" {
  value = local.local_dbs
  #sensitive = true
  precondition {
    condition     = length(distinct([for v in local.local_dbs: keys(v)])) == length(local.local_dbs)
    error_message = "Keys in local.local_dbs are NOT unique."
  }
}
  • Related