Reputation: 1543
Is there a way to use something like this in Terraform?
count = "${var.I_am_true}"&&"${var.I_am_false}"
Upvotes: 54
Views: 139285
Reputation: 1282
All the answers are enough but there is another case too.
For example, you have multiple
environments like;
master
dev
staging
and you need to set value of OBJECT_ENABLE
key based on these environments. You can do this like following:
OBJECT_ENABLE = var.app_env == "master" || var.app_env == "dev" ? "true" : "false"
According to the above condition value of the OBJECT_ENABLE
key will be the following;
for master
: OBJECT_ENABLE is true
for dev
: OBJECT_ENABLE is true
for staging
: OBJECT_ENABLE is false
Upvotes: 6
Reputation: 3445
This is more appropriate in the actual version (0.12.X)
The supported operators are:
Equality: == and !=
Numerical comparison: >, <, >=, <=
Boolean logic: &&, ||, unary !
https://www.terraform.io/docs/configuration/interpolation.html#conditionals
condition_one and condition two:
count = var.condition_one && var.condition_two ? 1 : 0
condition_one and NOT condition_two:
count = var.condition_one && !var.condition_two ? 1 : 0
condition_one OR condition_two:
count = var.condition_one || var.condition_two ? 1 : 0
Upvotes: 141
Reputation: 56997
Terraform 0.8 added first class support for conditional logic rather than the previous hacky workarounds.
This uses the classic ternary syntax so now you can do something like this:
variable "env" { default = "development" }
resource "aws_instance" "production_server" {
count = "${var.env == "production" ? 1 : 0}"
...
}
Now this will only create the production_server
EC2 instance when env
is set to "production"
.
You can also use it in other places too such as setting a variable/parameter like this:
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}"
}
One thing to be aware of is that Terraform actually evaluates both sides before then choosing the value used in the ternary statement rather than lazily evaluating just the side of the ternary that the logic will trigger.
This means you can't do something like this recent example of me trying to hack around an issue with the aws_route53_zone
data source:
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}"
}
In the above example this will fail on the plan because either data.aws_route53_zone.private_zone.zone_id
or data.aws_route53_zone.public_zone.zone_id
is not defined depending on whether public_zone
is set to true or false.
Upvotes: 13
Reputation: 9391
The answer by deniszh is pretty close, but I thought I'd clarify it a bit and clean up the syntax.
In Terraform, a boolean true
is converted to a 1
and a boolean false
is converted to a 0
. So if you have two boolean variables, var.foo
and var.bar
, you can represent AND
using simple multiplication:
count = "${var.foo * var.bar}"
In the code above, count
will be 1 only if var.foo
AND var.bar
are both true
, as 1 * 1 is 1. In all other cases (1 * 0, 0 * 1, 0 * 0), you get 0.
To represent OR, you can take advantage of the function signum(x), which returns 1 if the x
you pass in is a positive number, 0 if x
is 0, and -1 if x
is a negative number. Taking this into account, here is OR:
count = "${signum(var.foo + var.bar)}"
In the code above, count
will be 1 if either var.foo
OR var.bar
is true
and 0 only if both are false
(signum(1 + 1) = 1
, signum(1 + 0) = 1
, signum(0 + 1) = 1
, signum(0 + 0) = 0
).
Note that to use the techniques above, you must take care to set the variables to a boolean and NOT a string. You want this:
variable "foo" {
# Proper boolean usage
default = true
}
NOT this:
variable "foo" {
# THIS WILL NOT WORK!
default = "true"
}
For more info on how to do a variety of Terraform conditionals, check out Terraform tips & tricks: loops, if-statements, and gotchas and Terraform: Up & Running.
Upvotes: 32
Reputation: 794
There's no binary type defined in Terraform. But you can try to use simple math
E.g.
OR equivalent
count = signum(${var.I_am_true} + ${var.I_am_false})
AND equivalent
count = ${var.I_am_true} * ${var.I_am_false}
Both will work if I_am_true == 1 and I_am_false == 0.
Didn't try both, though.
Upvotes: 4