HashiCorp Terraform 0.12 Preview: Generalized Splat Operator
This is the fourth 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 new generalized splat operator.
Terraform has always supported a special syntax to obtain a list of attribute values from a set of resources created using the count
argument, known as a "splat expression." In Terraform 0.12, we've generalized this to work with any list values and call it the "splat operator."
» Splat Operator
In Terraform 0.11 and earlier, the value of an attribute for a set of resources created with count
could be obtained using something called a "splat expression." The example below shows this in use:
# Configuration for Terraform 0.11 and earlier
output "instance_names" {
value = google_compute_instance.main.*.name
}
The splat expression was previously a special-case operation only for attributes on resources with count
and didn't work for any other list values. For Terraform 0.12, we've generalized the operation to work for any list value and are calling the syntax the "splat operator."
The example below shows the splat operator in use for an arbitrary list value on a single resource that doesn't have count
set.
# Configuration for Terraform 0.12
output "instance_ip_addrs" {
value = google_compute_instance.example.network_interface.*.address
}
In the above example, the specific single-count resource google_compute_instance.example
is specified, and the splat operator is used to flatten the list of network interface addresses into a single list.
» Full Splat Operator
The splat syntax in Terraform 0.11 and earlier has a limitation that it only allows accessing named attributes of the items in the given list. This led to common and confusing expressions like google_compute_instance.main.*.name[count.index]
as a way to access the name of an instance identified by a specific index. Terraform 0.12 now allows that to be expressed more intuitively as google_compute_instance.main[count.index].name
, with the old form retained for backward compatibility.
A new variant of the splat operator known as the "full splat operator", is supported in 0.12 as a way to conveniently access both attributes and indexes within a given list:
# Configuration for Terraform 0.12
output "instance_net_ip_addrs" {
value = google_compute_instance.example.network_interface[*].access_config[0].assigned_nat_ip
}
Placing the asterisk symbol inside indexing brackets rather than using it as an attribute name activates the full splat behavior, causing access_config[0]
to be interpreted as part of the access into each of the network interfaces. Replicating this behavior in Terraform 0.11 and earlier required function calls and unintuitive syntax.
We recommend using the full splat syntax for all new configurations since its behavior is generally more intuitive. The older syntax is retained for backwards compatibility but is not recommended.
» Upgrade Guide
Terraform 0.12 continues to support the previous splat operator usage in most cases, but does introduce two important breaking changes.
First, the handling of resources with count
set has been slightly changed in Terraform 0.12. Referencing the resource without an index now results in a list of all of the instances, rather than behaving as an alias for the first instance. For any resource where count
is set — even if it is set to 1 — the first instance must be accessed by indexing with [0]
, such as aws_instance.example[0].id
.
The example below will behave differently in Terraform 0.12:
# Configuration for Terraform 0.11 and prior
resource "aws_instance" "web" {
count = 1
...
}
output "id" {
value = "${aws_instance.web.id}" # Value is the ID of index 0
}
The example converted to Terraform 0.12:
# Configuration for Terraform 0.12
resource "aws_instance" "web" {
count = 1
...
}
output "id" {
value = "${aws_instance.web[0].id}"
}
In most cases, Terraform 0.12 will error due to this change. If the expected value is not a list, then an error will be shown. As always, please review plan output to verify Terraform is behaving as expected and to catch any configuration changes necessary.
The second breaking change is the removal of some legacy backward-compatibility behavior for splat expressions. Early versions of Terraform required splat expressions to appear interpolated into a list constructor, like ["${aws_instance.example.*.id}"]
, but this requirement was lifted in Terraform 0.9.6 and this form was deprecated. In Terraform 0.12, that expression now produces a list of lists, since the splat expression produces a list itself and then the outer brackets wrap that result in another list. This is generally expected behavior but may be surprising for long-time Terraform users.
» Next
This was part 4 of the blog post series previewing Terraform 0.12.
The generalized splat operator 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.
Sign up for the latest HashiCorp news
More blog posts like this one
Terraform delivers launch-day support for Amazon S3 Tables, EKS Hybrid Nodes, and more at re:Invent
The Terraform provider for AWS now enables users to manage a variety of new services just announced at re:Invent.
HashiCorp at re:Invent 2024: Infrastructure Lifecycle Management with AWS
A recap of HashiCorp infrastructure news and developments on AWS from the past year, from a new provider launch to simplifying infrastructure provisioning and more.
Simplify policy adoption in Terraform with pre-written Sentinel policies for AWS
HashiCorp introduces a new pre-written policy library co-developed with AWS, aiming to reduce the barrier of adoption for policy as code infrastructure workflows.