Terraform 0.8 makes configuration decisions explicit
Conditionals give Terraform modules direct value selection. The new console and version requirements make those expressions easier to inspect and distribute.
Reusable infrastructure configuration needs to describe where deployments differ. Terraform 0.8 gives that problem a direct expression with conditional values. An environment can select a subnet or decide whether a counted resource exists without representing the decision indirectly through another function. The December 13 release notes put conditionals alongside an interactive console and configuration-level version requirements. Together they change how a module author writes a decision and communicates the language support it needs.
The interesting limit is that the language still selects values inside a declarative configuration. A conditional does not turn the file into a program that issues infrastructure operations in sequence. Terraform retains the resource declaration, and the expression supplies an attribute value. That distinction matters when a compact expression changes something as substantial as whether an infrastructure resource exists.
I like the generality of Terraform's configuration language over provider APIs. The benefit is greatest when a module can express its differences plainly. A direct conditional gives a reader less machinery to reconstruct when the intended policy is simply that production and development use different values.
Selecting a value inside interpolation
The 0.8 interpolation documentation defines the conditional form as CONDITION ? TRUEVAL : FALSEVAL. Its condition and both result expressions can use interpolation syntax, including function calls. Both result branches must return the same type. The documented operators include equality, numeric comparisons and Boolean operations.
For a small example, a configuration can expose a label that changes with an environment input. This uses the string interpolation syntax documented for this release.
variable "environment" {
default = "development"
}
output "deployment_label" {
value = "${var.environment == "production" ? "customer-facing" : "internal"}"
}
Both outcomes are strings. The conditional states the selection without requiring the reader to know the behaviour of a function used as a substitute for branching. It also keeps the decision next to the value it controls. Changing the environment input changes the selected label, while the output declaration remains the same.
The release notes give a more consequential example with count, using a comparison against an environment name to select one or zero. The interpolation documentation likewise describes conditionally including a resource through its count. This is a resource declaration with a computed multiplicity. The expression controls whether there is an instance to manage.
That is a useful way to describe an optional component, but the count deserves the same attention as any other resource input. A change in the selected value can change which instances belong in the configuration. Calling the expression a conditional should not obscure that consequence. Its small textual size says nothing about the importance of the resulting plan.
Type consistency also helps keep a module interface understandable. If the selection chooses a subnet identifier, both branches need to supply the same kind of value. The documented requirement that branch types match provides a language rule for that expectation. A module consumer should be able to reason about the attribute independently of which deployment selects it.
Trying an expression without applying infrastructure
Terraform's new console supplies a direct place to inspect those expressions. The console documentation shipped with 0.8.0 describes an interactive command that works even when no configuration or state file exists. Basic arithmetic and supported interpolation functions are enough to start a session. Loading a configuration directory also makes its configuration and state available.
An operator can therefore separate a question about expression evaluation from a question about provider behaviour. A function result or mathematical expression can be checked in the console before it is embedded in a resource attribute. This does not prove that a provider will accept the resulting value. It resolves the narrower question of what Terraform's expression evaluator produces.
The command also accepts newline-separated expressions through standard input. According to its documentation, only the final result is printed unless an earlier expression fails. A minimal documented use looks like this.
echo "1 + 5" | terraform console
This prints 6. For a configuration author, the same facility provides a small feedback loop while working on interpolation. There is no need to invent a disposable resource merely to observe an expression result. The console can also read existing state, which makes it useful for inspecting values already associated with managed infrastructure.
Remote state has a specific workflow in this version. The console documentation instructs users to run terraform remote pull first so that the remote state is available locally. It also says the console cannot modify state. Those details define what the command can establish. Inspecting a pulled value is different from performing an infrastructure operation or writing a changed state back.
I find this separation useful because configuration errors often begin as uncertainty about a value. The console allows that uncertainty to be addressed at the expression level. Questions about resource changes still belong to the plan and the provider, where the relevant infrastructure semantics exist.
Declaring the language requirement
A reusable module that adopts conditional expressions needs consumers to run a compatible Terraform binary. The new terraform configuration block provides required_version for that purpose. The version requirement documentation says Terraform shows an error and exits when its version fails the configured constraints.
terraform {
required_version = ">= 0.8.0"
}
This example declares a minimum language version. It does not claim compatibility testing with every future release. The constraint communicates the configuration's requirement, while the choice of how broadly to permit versions remains a maintenance decision for its author.
Constraints can also combine comparisons in a comma-separated list. The documentation supports exact equality and exclusions as well as lower and upper bounds. This lets an author describe a known compatibility interval when a minimum alone is insufficient.
The requirement applies across the complete module tree. A module can therefore declare its own minimum, and the consuming configuration must satisfy that requirement along with the others it uses. This gives a module author a way to make the dependency on new syntax machine-readable. A README instruction alone cannot make Terraform reject an unsuitable executable at the start of an operation.
The version block has another restriction worth understanding. It cannot contain interpolations because Terraform loads it before interpolation is available. A configuration cannot compute its required Terraform version using the same expression system whose availability it is checking. Literal constraints make the requirement available early enough to serve its purpose.
This restriction also discourages hiding the language requirement inside deployment policy. An environment selection might control a resource attribute, but the Terraform binary must understand the module before it can evaluate that selection. The required version describes the configuration as a whole, including expressions that a particular deployment might not select.
Existing expressions can change meaning
The release also changes expression rules that affect existing files. Its compatibility notes say mathematical operators now use standard precedence, with multiplication, division and modulo ahead of addition and subtraction. Parentheses can force a different order. The interpolation documentation demonstrates that 2 * 4 + 3 * 3 computes to 17, while 2 * (4 + 3) * 3 computes to 42.
This is a language change with operational consequences wherever arithmetic feeds infrastructure attributes. A file can retain its text while an expression produces a different result under revised evaluation rules. The version requirement and console are relevant here for separate reasons. One declares the accepted executable versions, and the other makes an expression's evaluated result observable.
Escaping also changes. The release notes say escape sequences inside interpolations need one level of escaping where earlier behaviour required double escaping. Inline template_file content must escape template variables using doubled dollar signs, while templates read from files are unchanged. These are documented compatibility changes, so adopting 0.8 involves more than adding conditional expressions to new modules.
For inline templates, the distinction is between Terraform's interpolation and the template's own interpolation. The documentation shows $${hello} surviving the first stage so that the template data source can use hello from its vars map. Without that distinction, a reader can mistake a template variable for an input that Terraform should resolve immediately.
Terraform 0.8 makes more configuration policy expressible in the language itself. A module can state a value selection and declare the Terraform version needed to interpret it. The console supplies a way to examine that interpretation, including existing arithmetic and escaping rules that this release changes. These additions give module authors more precise tools for explaining what their configuration requires and what its expressions actually return.