【问题标题】:Terraform conditional specifying certain textTerraform 有条件地指定某些文本
【发布时间】:2020-08-20 15:21:12
【问题描述】:

在 Terraform 中,我试图提出一个条件,即搜索特定键以稍后执行操作。下面是我定义的地图变量的示例。我想做的是让 Terraform “过滤”某些键并执行某些操作。任何如何实现这一点的建议都会有所帮助。

variable "volumes" {
 type = map(object({
    size              = string
    availability_zone = string
  }))
  default = {
    "Primary" = {
      size              = "200"
      availability_zone = "us-west-2a"
    }
    "PrimarySecondary" = {
      size              = "100"
      availability_zone = "us-west-2a"
    }
    "Worker1" = {
      size              = "200"
      availability_zone = "us-west-2b"
    }
    "Worker1Secondary" = {
      size              = "100"
      availability_zone = "us-west-2b"
    }
    "Worker2" = {
      size              = "200"
      availability_zone = "us-west-2c"
    }
    "Worker2Secondary" = {
      size              = "100"
      availability_zone = "us-west-2c"
    }
  }
}

resource "aws_ebs_volume" "partition" {
  for_each          = var.volumes
  availability_zone = each.value.availability_zone
  size              = each.value.size

  tags = {
    Name = each.key
  }
}

resource "aws_volume_attachment" "ebs_att" {
  for_each    = aws_ebs_volume.partition
  device_name = each.key == ("Primary" || "Worker1" || "Worker2") ? "/dev/sdf" : "/dev/sdg"
  volume_id   = each.value.id
  instance_id = aws_instance.private[each.key].id
}

错误

Error: Invalid operand

  on vpc.tf line 49, in resource "aws_volume_attachment" "ebs_att":
  49:   device_name = each.key == ("Primary" || "Worker1" || "Worker2") ? "/dev/sdf" : "/dev/sdg"

Unsuitable value for right operand: a bool is required.

【问题讨论】:

  • 您想要达到的具体结果是什么?你能给出一个示例输出吗?或者解释一下您打算如何以更广泛的方式使用它?
  • 是的。我会编辑这个问题。我正在将卷附加到 ebs 卷。对于我正在创建的分区,我需要指定一个特定的设备名称。这些设备名称取决于我拥有的卷的大小。因此,在 Terraform 中,我试图弄清楚如何过滤掉特定的键,以便为分区获取适当的设备名称。我希望这是有道理的。我会补充这个问题。
  • 我希望这个问题的答案将涉及使用if 子句的for expression,以生成一个过滤掉一些元素的新地图。如果你能准确地展示你想要的结果(即什么规则决定了一个特定的元素是否应该包含在结果中),那么写一个真实的例子会更容易。
  • 哦,嘿...您在我写该评论时更新了问题。谢谢!

标签: conditional-statements terraform


【解决方案1】:

这里的表达式 "Primary" || "Worker1" || "Worker2" 被 Terraform 拒绝,因为 || 是布尔 OR 运算符,它只能用于布尔值,不能用于字符串。

您的意图似乎是说“如果each.key 是这些值之一”,在这种情况下,一种方法是使用the contains function:

  device_name = contains(["Primary", "Worker1", "Worker2"], each.key) ? "/dev/sdf" : "/dev/sdg"

我会考虑的另一种选择是使用显示每个键的设备名称的地图创建一个本地值,如下所示:

locals {
  volume_device_names = {
    Primary = "/dev/sdf"
    Worker1 = "/dev/sdf"
    Worker2 = "/dev/sdf"
    PrimarySecondary = "/dev/sdg"
    Worker1Secondary = "/dev/sdg"
    Worker2Secondary = "/dev/sdg"
  }
}

那么你的条件表达式就可以变成地图查找了:

  device_name = local.volume_device_names[each.key]

这有一些不同的权衡,根据您的需要,这可能是也可能不是优势:

  • 如果调用者在变量值中指定了一个意外的键名,那么第一个示例将默认为/dev/sdg,而第二个示例将产生映射查找错误。如果您的有效键集是固定集,那么在调用者不小心打错字时返回错误可能会有所帮助。
  • 在第一个示例中,为音量键选择设备名称的规则内嵌在aws_ebs_volume_attachment 资源配置中,这意味着我们可以查看该资源名称并直接了解它将如何选择一个。但是,这意味着规则与variable "volumes" 的定义“相距甚远”(从阅读模块的人的角度来看),这可能会让人更难看出该映射的键在决定设备如何获取时很重要随附的。将其分解为 locals 块意味着它可以与 variable "volumes" 块相邻放置,以便阅读该变量定义的人更容易找到。

还有一些其他变体可以在这两者之间做出不同的妥协,但是这个答案已经足够长了,所以除非你有具体的问题,否则我会将这些作为练习。

【讨论】:

  • 谢谢@Martin。这绝对有帮助。我刚刚收到一个错误,如何指定这些卷需要附加到的实例。我将创建一个新问题。如果您能提出建议,不胜感激。
猜你喜欢
  • 1970-01-01
  • 2013-04-27
  • 1970-01-01
  • 2021-05-14
  • 2021-09-01
  • 1970-01-01
  • 2016-10-11
  • 1970-01-01
  • 2020-08-11
相关资源
最近更新 更多