Alex Harvey
Alex Harvey

Reputation: 15472

Combine two maps to create a third map in Terraform 0.12

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:

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?

Upvotes: 6

Views: 10189

Answers (1)

Alex Harvey
Alex Harvey

Reputation: 15472

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.

Upvotes: 4

Related Questions