【问题标题】:Combine two maps to create a third map in Terraform 0.12在 Terraform 0.12 中合并两张地图以创建第三张地图
【发布时间】:2019-11-09 00:51:52
【问题描述】:

我需要在 Terraform 0.12 中对输入数据进行一些复杂的合并。我不知道这是否可能,但也许我只是做错了什么。

我有两个变量:

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"]
}

然后我想在这样的模板中组合这些来源:

#!/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}

merged 将包含组合数据。

模板语言似乎只支持简单的for循环,所以在那里进行合并似乎是不可能的。

所以,我假设数据处理需要在 DSL 中进行。但是,我需要这样做:

  • 遍历 ebs_block_devices 列表,跟踪索引(如 Python 中的 enumerate() 或 Ruby 中的 each.with_index
  • 从mount_points列表中获取对应的元素
  • 将这些添加到结果地图中。

具体来说,我的问题是似乎没有任何等效于 Python 的 enumerate 函数,这使我无法跟踪索引。如果有,我想我可以这样做:

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

目前在 Terraform 中是否可以进行像我在这里尝试进行的数据转换?如果不可能,首选的替代实现是什么?

【问题讨论】:

  • 我认为mount_point 需要成为地图才能在此处使用merge 功能。事实上,我注意到这两种类型都是list 作为原语,所以可能会遍历一个列表,然后通过索引访问第一个变量的元素映射和第二个变量的元素。这对您有用,但缺点是您需要创建两个变量的长度相等的保护措施。
  • @MattSchuchard,不,我在 Python 中测试过,如果 Terraform 有 enumerate(),则代码可以工作,请参阅 this Gist。您提出的正是我想要做的,除了似乎没有枚举就无法访问索引。
  • 您是否尝试将这些卷挂载为user_data 的一部分?你不能做类似sanjeevnandam.com/blog/ec2-mount-ebs-volume-during-launch-time 的事情吗?可能您必须使用循环模板,如medium.com/ovni/terraform-templating-and-loops-9a88c0786c5c 中所述
  • 谢谢@aderubaru,但问题实际上是关于如何合并数据。我可以看到在不合并数据的情况下执行此操作的方法,但我认为我想做的事情应该是可能的。我提出了一个功能请求。

标签: terraform terraform0.12+


【解决方案1】:

事实证明这实际上是可能的:


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]})
  ]
}

感谢 HashiCorp 的支持。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-10-31
    • 2017-12-25
    • 1970-01-01
    • 2020-11-07
    • 1970-01-01
    • 2020-08-11
    • 2023-03-06
    • 2020-04-23
    相关资源
    最近更新 更多