In the documentation or in their bug database, both authors seem to prefer to write out the expression this way:
var.a != "" ? var.a : "default-a"
The value is explicitly tested to be not equal to empty string, then binary choice is made accordingly.
However, does this work too?
var.a ? var.a : "default-a"
I have not found it explicitly stated either way.
Handling of type conversions like these is always a tradeoff in language design, and different languages make different compromises here.
For Terraform's language in particular, the philosophy is "explicit is better than implicit": the idea is that ideally someone who is unfamiliar with a configuration and possibly unfamiliar even with Terraform itself can read a Terraform configuration and make a good guess as to what it means, without needing to have memorized a lot of implicit conversion rules.
With that said, Terraform does have an automatic conversion from string to boolean, but not such that an empty string converts to false. Instead, the string values "true"
and "false"
map to true
and false
respectively, and any other string will produce a conversion error.
The allowance of converting those particular string values is mainly motivated by backward compatibility: prior to Terraform 0.12, there was no boolean type and thus strings containing those values were the only way to represent booleans.
When testing whether a string is empty, Terraform requires that to be written out explicitly as var.string == ""
or var.string != ""
so that the intent is explicit and clear to the reader.
(I am one of the authors of the documentation linked from the question and the author of the comment linked from the question. At the time of writing, I work on Terraform at HashiCorp.)
Pre Terraform 0.12, Terraform has some slightly interesting handling of booleans and integers using type coercion under the covers as it technically only supports strings, lists and maps.
So if you do something like this:
variable "foo" {
default = "true"
}
output "truthiness" {
value = "${var.foo ? var.foo : "default-foo" }"
}
then you can expect the following output:
$ terraform apply
Using temporary credentials from master-read-only profile...
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
Outputs:
truthiness = true
$ TF_VAR_foo=false terraform apply
Using temporary credentials from master-read-only profile...
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
Outputs:
truthiness = default-foo
This even works with 0
and 1
:
$ TF_VAR_foo=1 terraform apply
Using temporary credentials from master-read-only profile...
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
Outputs:
truthiness = 1
$ TF_VAR_foo=0 terraform apply
Using temporary credentials from master-read-only profile...
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
Outputs:
truthiness = default-foo
However, if you try to use a string that Terraform is unable to type coerce to a boolean then it just fails to parse and will error:
$ TF_VAR_foo="" terraform apply
Using temporary credentials from master-read-only profile...
Error: output.truthiness: __builtin_StringToBool: strconv.ParseBool: parsing "": invalid syntax in:
${var.foo ? var.foo : "default-foo" }
$ TF_VAR_foo="bar" terraform apply
Using temporary credentials from master-read-only profile...
Error: output.truthiness: __builtin_StringToBool: strconv.ParseBool: parsing "bar": invalid syntax in:
${var.foo ? var.foo : "default-foo" }
$ TF_VAR_foo=2 terraform apply
Using temporary credentials from master-read-only profile...
Error: output.truthiness: __builtin_StringToBool: strconv.ParseBool: parsing "2": invalid syntax in:
${var.foo ? var.foo : "default-foo" }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With