JUL 26 2018    MARTIN ATKINS

This is the fifth post of the series highlighting new features in Terraform 0.12.

As part of the lead up to the release of Terraform 0.12, we are publishing a series of feature preview blog posts. The post this week is on the improvements to conditional operators and introducing conditionally omitted arguments.

Terraform has supported basic conditionals for two years, but conditionals have had major known limitations. In Terraform 0.12, these limitations have been lifted and conditionals work as expected in all cases. Terraform 0.12 also introduces the null value for conditionally omitting a value.

Conditional Operator Improvements

The conditional operator ... ? ... : ... was introduced to solve some common issues in configurations. The original implementation prior to Terraform 0.12 has known limitations due to the fundamentals of Terraform. While the conditional operator helped improve configurations, the limitations were unexpected, unintuitive, and often held back Terraform in many ways.

In particular, prior to v0.12 the conditional operator works only for primitive types (not lists or maps) and will always evaluate both value expressions even though only one is ever returned. Both of these limitations are lifted in Terraform 0.12.

The example below shows this new flexibility for Terraform 0.12 and later:

# Configuration for Terraform 0.12

locals {
  first_id = length(azurerm_virtual_machine.example) > 0 ? azurerm_virtual_machine.example[0].id : ""

  buckets = (var.env == "dev" ? [var.build_bucket, var.qa_bucket] : [var.prod_bucket])
}

In previous versions of Terraform, the above example would fail. The first local first_id would error even if the list was non-empty because Terraform evaluated both return values. The second local buckets would fail because Terraform didn't support lists and maps as return values.

The example above is also much more readable thanks to the previously covered improvement in Terraform 0.12: First-Class Expressions.

Conditionally Omitted Arguments

Terraform v0.12 now allows assigning the special value null to an argument to mark it as "unset". This can be combined with other language features so that a module can allow its caller to conditionally override a value while retaining the default behavior if the value is not defined.

In versions prior to Terraform 0.12, the only way to get the default behavior for an argument was to not set it at all. If the value came from a parameter (variable, local, etc.) then there was no way to revert to the default behavior except to modify the configuration source. This limited the configurability of modules in a big way.

The example below shows null being used in Terraform 0.12 and later:

# Configuration for Terraform 0.12

variable "override_private_ip" {
  type    = string
  default = null
}

resource "aws_instance" "example" {
  # ... (other aws_instance arguments) ...

  private_ip = var.override_private_ip
}

Previously there was no way to assign an expression to an argument while retaining any default behavior associated with that argument. By using the new null value, the aws_instance resource can dynamically assign a private IP address when no override is provided, but set an explicit IP address if the calling module provides a value for override_private_ip.

Upgrade Guide

The improvements to the conditional operator and the introduction of null do not introduce any breaking changes.

Next

This was part 5 of the blog post series previewing Terraform 0.12.

These improvements to the conditional operator and the introduction of conditionally omitted arguments will be released in Terraform 0.12, coming later this summer. To learn more about how to upgrade to Terraform 0.12, read the upgrade instructions which will be continuously updated as we get closer to releasing Terraform 0.12. If you have any feedback or concerns about these changes, please communicate with the Terraform team via the public mailing list.