Combine two maps to create a third map in Terraform 0.12

Viewed 8091

I have a requirement to do some complicated merging of input data in Terraform 0.12. I can't figure out if it's possible, but maybe I'm just doing something wrong.

I have two variables:

variable "ebs_block_device" {
  description = "Additional EBS block devices to attach to the instance"
  type        = list(map(string))
  default     = [
    {
      device_name = "/dev/sdg"
      volume_size = 5
      volume_type = "gp2"
      delete_on_termination = false
    },
    {
      device_name = "/dev/sdh"
      volume_size = 5
      volume_type = "gp2"
      delete_on_termination = false
    }
  ]
}

variable "mount_point" {
  description = "Mount point to use"
  type = list(string)
  default = ["/data", "/home"]
}

I want to then combine these sources inside a template like this:

#!/usr/bin/env bash
%{for e in merged ~}
mkfs -t xfs ${e.device_name}
mkdir -p ${e.mount_point}
mount ${e.device_name} ${e.mount_point}
%{endfor}

Where merged would contain the combined data.

It seems that only simple for loops are supported in the template language, so doing the merge in there seems to be out of the question.

So, I assume the data munging needs to happen in the DSL. But, I would need to do this:

  • iterate over the list of ebs_block_devices, tracking the index (like enumerate() in Python, or each.with_index in Ruby)
  • get the corresponding element from the list of mount_points
  • add these to a resultant map.

My problem, specifically, is that there doesn't seem to be any equivalent of Python's enumerate function, and this prevents me tracking the index. If there was, I imagine I could do something like this:

merged = [for index, x in enumerate(var.ebs_block_device): {
  merge(x, {mount_point => var.mount_point[index]})
}]

Is such a data transformation as I am trying to do here currently possible in Terraform? And if not possible, what is the preferred alternative implementation?

1 Answers

It turns out this is in fact possible like this:


variable "ebs_block_device" {
  description = "Additional EBS block devices to attach to the instance"
  type        = list(map(string))
  default     = [
    {
      device_name = "/dev/sdg"
      volume_size = 5
      volume_type = "gp2"
      delete_on_termination = false
    },
    {
      device_name = "/dev/sdh"
      volume_size = 5
      volume_type = "gp2"
      delete_on_termination = false
    }
  ]
}

variable "mount_point" {
  description = "Mount point to use"
  type = list(string)
  default = ["/data", "/home"]
}

output "merged" {
  value = [
    for index, x in var.ebs_block_device:
    merge(x, {"mount_point" = var.mount_point[index]})
  ]
}

With thanks to HashiCorp support.

Related