terraform中是否有AND/OR条件运算符?

48

在Terraform中是否有使用类似以下代码的方法?

count = "${var.I_am_true}"&&"${var.I_am_false}"


我记得上次查看时好像没有。但你可以在他们的问题跟踪页面找到一些信息:https://github.com/hashicorp/terraform/issues - Kristo Mägi
1
有关Terraform 0.11(2018年)的信息,请参见我下面的答案。 - NicoKowe
5个回答

129

在实际版本(0.12.X)中,这更为合适。

支持的运算符有:

相等:== 和 !=
数值比较:>、<、>=、<=
布尔逻辑:&&、||、一元 !

https://www.terraform.io/docs/configuration/interpolation.html#conditionals

条件一和条件二:

count = var.condition_one && var.condition_two ? 1 : 0

条件一且非条件二:

count = var.condition_one && !var.condition_two ? 1 : 0

条件一 OR 条件二:

count = var.condition_one || var.condition_two ? 1 : 0

12
这应该是当前tf版本所接受的答案。 - dimisjim
你能告诉我为什么 Terraform 会继续检查第二个参数 if var.x != null && var.x.internal_value,它一直在第二个条件上失败,但如果第一个条件是 false,因为我的参数确实是 null - 它会在 var.x.internal_value 上失败,但为什么它还会继续执行? - Ricky Levi
1
@RickyLevi 我相信这是因为这个原因:https://developer.hashicorp.com/terraform/language/expressions/operators#logical-operatorsTerraform中的逻辑运算符不会短路。 - Gooseman

29

deniszh的回答非常接近,但我想澄清一下,并清理一下语法。

在Terraform中,布尔值true转换为1,而布尔值false则转换为0。因此,如果您有两个布尔变量var.foovar.bar,可以使用简单的乘法表示AND

count = "${var.foo * var.bar}"
在上面的代码中,只有在var.foovar.bar都为true时,count才会为1,因为1 * 1等于1。在其他情况下(1 * 0、0 * 1、0 * 0),你得到的是0。
要表示OR,你可以利用函数signum(x),它将返回1,如果你传入的x是正数,返回0,如果x是0,返回-1,如果x是负数。考虑到这一点,下面是OR:
count = "${signum(var.foo + var.bar)}"
在上面的代码中,如果var.foo或者var.bartrue,那么count将会是1,只有当它们都为false时,count才会是0(signum(1 + 1) = 1signum(1 + 0) = 1signum(0 + 1) = 1signum(0 + 0) = 0)。
请注意,使用上述技术时,必须确保将变量设置为布尔值而不是字符串。你需要这样做:
variable "foo" {
  # Proper boolean usage
  default = true
}

不是这个:

variable "foo" {
  # THIS WILL NOT WORK!
  default = "true"
}

要了解有关如何执行各种Terraform条件语句的更多信息,请查看Terraform技巧和诀窍:循环,if语句和注意事项Terraform:实战


13

Terraform 0.8 新增了一流支持条件逻辑,而不再像以前那样使用 hacky 的解决方法。

现在你可以使用经典的三元语法来实现以下操作:

variable "env" { default = "development" }

resource "aws_instance" "production_server" {
  count = "${var.env == "production" ? 1 : 0}"
  ...
}
现在只有当env设置为"production"时,才会创建production_server EC2实例。
您也可以在其他地方使用它,比如像这样设置变量/参数:
variable "env" { default = "development" }
variable "production_variable" { default = "foo" }
variable "development_variable" { default = "bar" }

output "example" {
  value = "${var.env == "production" ? var.production_variable : var.development_variable}"
}

需要注意的一件事是,Terraform在选择三元运算语句使用的值之前实际上会先评估两侧的值,而不是仅惰性地评估逻辑将触发的三元运算符侧。

这意味着你不能像我最近尝试解决aws_route53_zone数据源问题时所做的那样:

variable "vpc"    {}
variable "domain" {}

variable "private_zone"  { default = "true" }

data "aws_vpc" "vpc" {
  filter {
    name   =   "tag-key"
    values = [ "Name" ]
  }
  filter {
    name   =   "tag-value"
    values = [ "${var.vpc}" ]
  }
}

data "aws_route53_zone" "private_zone" {
  count        = "${var.private_zone == "true" ? 1 : 0}"
  name         = "${var.domain}"
  vpc_id       = "${data.aws_vpc.vpc.id}"
  private_zone = "true"
}

data "aws_route53_zone" "public_zone" {
  count        = "${var.private_zone == "true" ? 0 : 1}"
  name         = "${var.domain}"
  private_zone = "false"
}

output "zone_id" {
  value = "${var.private_zone == "true" ? data.aws_route53_zone.private_zone.zone_id : data.aws_route53_zone.public_zone.zone_id}"
}
在上面的示例中,这将在计划上失败,因为 public_zone 设置为 true 或 false 取决于是否定义了 data.aws_route53_zone.private_zone.zone_iddata.aws_route53_zone.public_zone.zone_id

5
所有答案都足够了,但还有另一种情况。
例如,您拥有多个环境,如:
- 主分支 - 开发环境 - 部署环境
您需要根据这些环境设置 OBJECT_ENABLE 键的值。您可以按以下方式执行此操作:
OBJECT_ENABLE = var.app_env == "master" || var.app_env == "dev" ? "true" : "false"

根据上述条件,OBJECT_ENABLE 键的值如下:
对于 masterOBJECT_ENABLEtrue 对于 devOBJECT_ENABLEtrue 对于 stagingOBJECT_ENABLEfalse

4
在Terraform中没有定义二进制类型。但是你可以尝试使用简单数学
例如:
或等效
 count = signum(${var.I_am_true} + ${var.I_am_false})

AND等效

 count = ${var.I_am_true} * ${var.I_am_false}

如果I_am_true == 1且I_am_false == 0,两者都可以工作。

尽管如此,我没有尝试过两种方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接