» References to Named Values

Hands-on: Try the Create Dynamic Expressions tutorial on HashiCorp Learn.

Terraform makes several kinds of named values available. Each of these names is an expression that references the associated value; you can use them as standalone expressions, or combine them with other expressions to compute new values.

» Types of Named Values

The main kinds of named values available in Terraform are:

  • Resources
  • Input variables
  • Local values
  • Child module outputs
  • Data sources
  • Filesystem and workspace info
  • Block-local values

The sections below explain each kind of named value in detail.

Although many of these names use dot-separated paths that resemble attribute notation for elements of object values, they are not implemented as real objects. This means you must use them exactly as written: you cannot use square-bracket notation to replace the dot-separated paths, and you cannot iterate over the "parent object" of a named entity; for example, you cannot use aws_instance in a for expression to iterate over every AWS instance resource.

» Resources

<RESOURCE TYPE>.<NAME> represents a managed resource of the given type and name.

The value of a resource reference can vary, depending on whether the resource uses count or for_each:

  • If the resource doesn't use count or for_each, the reference's value is an object. The resource's attributes are elements of the object, and you can access them using dot or square bracket notation.
  • If the resource has the count argument set, the reference's value is a list of objects representing its instances.
  • If the resource has the for_each argument set, the reference's value is a map of objects representing its instances.

Any named value that does not match another pattern listed below will be interpreted by Terraform as a reference to a managed resource.

For more information about how to use resource references, see references to resource attributes below.

» Input Variables

var.<NAME> is the value of the input variable of the given name.

» Local Values

local.<NAME> is the value of the local value of the given name.

» Child Module Outputs

module.<MODULE NAME> is an value representing the results of a module block.

If the corresponding module block does not have either count nor for_each set then the value will be an object with one attribute for each output value defined in the child module. To access one of the module's output values, use module.<MODULE NAME>.<OUTPUT NAME>.

If the corresponding module uses for_each then the value will be a map of objects whose keys correspond with the keys in the for_each expression, and whose values are each objects with one attribute for each output value defined in the child module, each representing one module instance.

If the corresponding module uses count then the result is similar to for for_each except that the value is a list with the requested number of elements, each one representing one module instance.

» Data Sources

data.<DATA TYPE>.<NAME> is an object representing a data resource of the given data source type and name. If the resource has the count argument set, the value is a list of objects representing its instances. If the resource has the for_each argument set, the value is a map of objects representing its instances.

For more information, see References to Resource Attributes, which also applies to data resources aside from the addition of the data. prefix to mark the reference as for a data resource.

» Filesystem and Workspace Info

  • path.module is the filesystem path of the module where the expression is placed.
  • path.root is the filesystem path of the root module of the configuration.
  • path.cwd is the filesystem path of the current working directory. In normal use of Terraform this is the same as path.root, but some advanced uses of Terraform run it from a directory other than the root module directory, causing these paths to be different.
  • terraform.workspace is the name of the currently selected workspace.

» Block-Local Values

Within the bodies of certain blocks, or in some other specific contexts, there are other named values available beyond the global values listed above. These local names are described in the documentation for the specific contexts where they appear. Some of most common local names are:

» Named Values and Dependencies

Constructs like resources and module calls often use references to named values in their block bodies, and Terraform analyzes these expressions to automatically infer dependencies between objects. For example, an expression in a resource argument that refers to another managed resource creates an implicit dependency between the two resources.

» References to Resource Attributes

The most common reference type is a reference to an attribute of a resource which has been declared either with a resource or data block. Because the contents of such blocks can be quite complicated themselves, expressions referring to these contents can also be complicated.

Consider the following example resource block:

resource "aws_instance" "example" {
  ami           = "ami-abc123"
  instance_type = "t2.micro"

  ebs_block_device {
    device_name = "sda2"
    volume_size = 16
  }
  ebs_block_device {
    device_name = "sda3"
    volume_size = 20
  }
}

The documentation for aws_instance lists all of the arguments and nested blocks supported for this resource type, and also lists a number of attributes that are exported by this resource type. All of these different resource type schema constructs are available for use in references, as follows:

  • The ami argument set in the configuration can be used elsewhere with the reference expression aws_instance.example.ami.
  • The id attribute exported by this resource type can be read using the same syntax, giving aws_instance.example.id.
  • The arguments of the ebs_block_device nested blocks can be accessed using a splat expression. For example, to obtain a list of all of the device_name values, use aws_instance.example.ebs_block_device[*].device_name.
  • The nested blocks in this particular resource type do not have any exported attributes, but if ebs_block_device were to have a documented id attribute then a list of them could be accessed similarly as aws_instance.example.ebs_block_device[*].id.
  • Sometimes nested blocks are defined as taking a logical key to identify each block, which serves a similar purpose as the resource's own name by providing a convenient way to refer to that single block in expressions. If aws_instance had a hypothetical nested block type device that accepted such a key, it would look like this in configuration:

      device "foo" {
        size = 2
      }
      device "bar" {
        size = 4
      }
    

    Arguments inside blocks with keys can be accessed using index syntax, such as aws_instance.example.device["foo"].size.

    To obtain a map of values of a particular argument for labelled nested block types, use a for expression: {for k, device in aws_instance.example.device : k => device.size}.

When a resource has the count argument set, the resource itself becomes a list of instance objects rather than a single object. In that case, access the attributes of the instances using either splat expressions or index syntax:

When a resource has the for_each argument set, the resource itself becomes a map of instance objects rather than a single object, and attributes of instances must be specified by key, or can be accessed using a for expression.

Note that unlike count, splat expressions are not directly applicable to resources managed with for_each, as splat expressions must act on a list value. However, you can use the values() function to extract the instances as a list and use that list value in a splat expression:

» Values Not Yet Known

When Terraform is planning a set of changes that will apply your configuration, some resource attribute values cannot be populated immediately because their values are decided dynamically by the remote system. For example, if a particular remote object type is assigned a generated unique id on creation, Terraform cannot predict the value of this id until the object has been created.

To allow expressions to still be evaluated during the plan phase, Terraform uses special "unknown value" placeholders for these results. In most cases you don't need to do anything special to deal with these, since the Terraform language automatically handles unknown values during expressions, so that for example adding a known value to an unknown value automatically produces an unknown value as the result.

However, there are some situations where unknown values do have a significant effect:

  • The count meta-argument for resources cannot be unknown, since it must be evaluated during the plan phase to determine how many instances are to be created.

  • If unknown values are used in the configuration of a data resource, that data resource cannot be read during the plan phase and so it will be deferred until the apply phase. In this case, the results of the data resource will also be unknown values.

  • If an unknown value is assigned to an argument inside a module block, any references to the corresponding input variable within the child module will use that unknown value.

  • If an unknown value is used in the value argument of an output value, any references to that output value in the parent module will use that unknown value.

  • Terraform will attempt to validate that unknown values are of suitable types where possible, but incorrect use of such values may not be detected until the apply phase, causing the apply to fail.

Unknown values appear in the terraform plan output as (not yet known).

» Sensitive Resource Attributes

When defining the schema for a resource type, a provider developer can mark certain attributes as sensitive, in which case Terraform will show a placeholder marker (sensitive) instead of the actual value when rendering a plan involving that attribute.

The treatment of these particular sensitive values is currently different than for values in input variables and output values that have sensitive = true set. Sensitive resource attributes will be obscured in the plan when they appear directly, but other values that you derive from a sensitive resource attribute will not themselves be considered sensitive, and so Terraform will include those derived values in its output without redacting them.

Terraform v0.14.0 and later has an experimental feature to treat resource attributes that are marked as sensitive in the same way as sensitive input variables and output values, so that Terraform will consider any derived values as sensitive too. You can activate that experiment for your module using the provider_sensitive_attrs experiment keyword:

terraform {
  experiments = [provider_sensitive_attrs]
}

The behavior of this experiment might change even in future patch releases of Terraform, so we don't recommend using this experiment in modules you use to describe production infrastructure.

If you enable this experiment and you have exported any sensitive resource attributes via your module's output values then you will see an error unless you also mark the output value as sensitive = true, confirming your intent to export it.