HashiCorp Terraform 0.12 Preview: Rich Value Types

HashiCorp Terraform 0.12 Preview: Rich Value Types

Aug 02 2018    Martin Atkins

This is the sixth 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 addition of rich value types in variables and outputs.

Terraform variables and outputs today support basic primitives and simple lists and maps. Lists and maps in particular have surprising limitations that lead to unintuitive and frustrating errors. Terraform 0.12 allows the use of arbitrarily complex values for both input variables and outputs, and the types of these values can be exactly specified.

» Complex Values

Due to the new type system introduced in 0.12, Terraform now allows use of arbitrary collection values in both input variables and attributes.

Terraform has always supported primitive values (strings, numbers, booleans), and Terraform 0.7 added support for simple lists and maps. Unfortunately, due to limitations of the previous generation core of Terraform, lists and maps had a number of surprising limitations. Terraform 0.12 removes all of these limitations.

In Terraform 0.12, complex objects can now be passed to child modules as inputs, and returned to parent modules as outputs. The example below shows a purposely complex module using complex objects as variables:

# Configuration for Terraform 0.12

module "subnets" {
  source = "./subnets"

  parent_vpc_id = "vpc-abcd1234"
  networks = {
    production_a = {
      network_number    = 1
      availability_zone = "us-east-1a"
    production_b = {
      network_number    = 2
      availability_zone = "us-east-1b"
    staging_a = {
      network_number    = 1
      availability_zone = "us-east-1a"

These values are then accessed like any other value in Terraform. In the above example, the subnets module could access network information using the new Terraform 0.12 For Expression: for network in var.networks.

» Rich Types

Terraform providers and resources always expect specific data types to be provided. Terraform will continue to attempt to automatically convert a provided value to the expected type if it doesn't match. An error will be produced if this isn't possible.

Terraform 0.12 introduces a powerful type system that module authors can use to specify expected types for input variables. This forces values to be validated and converted properly if possible. This also improves the error messages shown to users of a module.

Terraform has always supported a very simple type requirement for variables. The example below uses Terraform 0.12 syntax, but showcases functionality that has been possible in Terraform for many years:

# Configuration for Terraform 0.12

variable "environment_name" {
  type = string

Experienced Terraform users may notice that a difference is that string is not quoted. Types are now first-class values in Terraform and can be used directly.

Terraform 0.12 can now also represent the types of complex object structures like those shown in the previous section. This was not possible in earlier versions of Terraform. The example below shows a type specification for the example above:

# Configuration for Terraform 0.12

variable "networks" {
  type = map(object({
    network_number    = number
    availability_zone = string
    tags              = map(string)

This results in great validation for users of a Terraform configuration or module with clear error messages.

» Resources and Modules as Values

Building on this capability, Terraform 0.12 now permits using entire resources as object values within configuration, including returning them as outputs and passing them as input variables:

# Configuration for Terraform 0.12

output "vpc" {
  value = aws_vpc.example

The type of this output value is an object type derived from the schema of the aws_vpc resource type. The calling module can then access attributes of this result in the same way as the returning module would use aws_vpc.example, such as module.example.vpc.cidr_block.

This capability also works for modules themselves, with an expression like module.vpc evaluating to an object value with attributes corresponding to the modules's named outputs.

» Upgrade Guide

The new type system does not introduce any breaking changes. Existing configurations should continue to work as-is. Terraform 0.12 remains compatibile with the simple type system in previous versions of Terraform.

» Next

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

This new rich type system 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.

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now