Terraform - transform values of a map

If you're developer, you might wonder about control structures in terraforms declarative language. This applies to me from time to time, as after quite some years in writing code, switching the way of thinking is not always intuitive.

I recently had an issue where I needed to transform the values of a map in terraform without knowing the values before (which is a very basic task). The actual use case is to create a set of kubernetes manifests that contain base64 encoded values (just like a secret).

As it didn't matter if I knew the values before and all values had the same transform rule, the only real solution for this is to use a loop instead of writing these transformations by hand for every field.

The source & destination objects would look like:

{
  key1 = value1
  key2 = value2
}
source object
{
  key1 = dmFsdWUx
  key2 = dmFsdWUy
}
destination object

The code to achieve this is the following:

variable "configmaps" {
  type = map(object({
    data = map(string)
  }))
  default     = {}
  nullable    = true
  description = "Predefined configmaps."
}

resource "kubernetes_manifest" "repository" {
  for_each = var.configmaps

  manifest = {
    apiVersion = "v1"
    kind       = "ConfigMap"
    metadata = {
      name      = "${local.resource_name_prefix}-config-${each.key}"
      namespace = var.resource_namespace
    }
    data = {
      for k,v in each.value.data : k => base64encode(v)
    }
  }
}
resource definition

The relevant part is the for loop within the data{} section. We are iterating over the data field and base64 encode the value - the result will be assigned to a new map using the same key. If required, you can also alter the key (like prefix it or anything you might need).

The object we're iterating itself represents a map of strings which is not a required constraint in general but quit useful in my special use case where I can state that values need to be strings for the application use case.

So, actually quite simple if you get the syntax.