Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is an non-empty string truthy in terraform?

Tags:

terraform

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.

like image 729
Anthony Kong Avatar asked Jul 10 '19 09:07

Anthony Kong


2 Answers

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.)

like image 68
Martin Atkins Avatar answered Oct 24 '22 06:10

Martin Atkins


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" }
like image 41
ydaetskcoR Avatar answered Oct 24 '22 05:10

ydaetskcoR