---
page_title: References to Values - Configuration Language
description: >-
  Reference values in configurations, including resources, input variables,
  local and block-local values, module outputs, data sources, and workspace
  data.
---

# References to Named Values

> **Hands-on:** Try the [Create Dynamic Expressions](https://learn.hashicorp.com/tutorials/terraform/expressions?in=terraform/configuration-language&utm_source=WEBSITE&utm_medium=WEB_IO&utm_offer=ARTICLE_PAGE&utm_content=DOCS) 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](/language/expressions/types#indices-and-attributes) 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](/language/resources) 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](/language/expressions/types#indices-and-attributes).
* 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](#references-to-resource-attributes) below.

### Input Variables

`var.<NAME>` is the value of the [input variable](/language/values/variables) of the given name.

If the variable has a type constraint (`type` argument) as part of its
declaration, Terraform will automatically convert the caller's given value
to conform to the type constraint.

For that reason, you can safely assume that a reference using `var.` will
always produce a value that conforms to the type constraint, even if the caller
provided a value of a different type that was automatically converted.

In particular, note that if you define a variable as being of an object type
with particular attributes then only _those specific attributes_ will be
available in expressions elsewhere in the module, even if the caller actually
passed in a value with additional attributes. You must define in the type
constraint all of the attributes you intend to use elsewhere in your module.

### Local Values

`local.<NAME>` is the value of the [local value](/language/values/locals) of the given name.

Local values can refer to other local values, even within the same `locals`
block, as long as you don't introduce circular dependencies.

### Child Module Outputs

`module.<MODULE NAME>` is an value representing the results of
[a `module` block](/language/modules/syntax).

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](/language/values/outputs), 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](/language/data-sources) 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](#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](/language/state/workspaces).

Use the values in this section carefully, because they include information
about the context in which a configuration is being applied and so may
inadvertently hurt the portability or composability of a module.

For example, if you use `path.cwd` directly to populate a path into a resource
argument then later applying the same configuration from a different directory
or on a different computer with a different directory structure will cause
the provider to consider the change of path to be a change to be applied, even
if the path still refers to the same file.

Similarly, if you use any of these values as a form of namespacing in a shared
module, such as using `terraform.workspace` as a prefix for globally-unique
object names, it may not be possible to call your module more than once in
the same configuration.

Aside from `path.module`, we recommend using the values in this section only
in the root module of your configuration. If you are writing a shared module
which needs a prefix to help create unique names, define an input variable
for your module and allow the calling module to define the prefix. The
calling module can then use `terraform.workspace` to define it if appropriate,
or some other value if not:

```hcl
module "example" {
  # ...

  name_prefix = "app-${terraform.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:

* `count.index`, in resources that use
  [the `count` meta-argument](/language/meta-arguments/count).
* `each.key` / `each.value`, in resources that use
  [the `for_each` meta-argument](/language/meta-arguments/for_each).
* `self`, in [provisioner](/language/resources/provisioners/syntax) and
  [connection](/language/resources/provisioners/connection) blocks.

-> **Note:** Local names are often referred to as _variables_ or
_temporary variables_ in their documentation. These are not [input
variables](/language/values/variables); they are just arbitrary names
that temporarily represent a value.

The names in this section relate to top-level configuration blocks only.
If you use [`dynamic` blocks](/language/expressions/dynamic-blocks) to dynamically generate
resource-type-specific _nested_ blocks within `resource` and `data` blocks then
you'll refer to the key and value of each element differently. See the
`dynamic` blocks documentation for details.

## 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:

```hcl
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`](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/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](/language/expressions/splat). 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:

  ```hcl
    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](/language/expressions/for):
  `{for k, device in aws_instance.example.device : k => device.size}`.

When a resource has the
[`count`](/language/meta-arguments/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](/language/expressions/splat) or index syntax:

* `aws_instance.example[*].id` returns a list of all of the ids of each of the
  instances.
* `aws_instance.example[0].id` returns just the id of the first instance.

When a resource has the
[`for_each`](/language/meta-arguments/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](/language/expressions/for).

* `aws_instance.example["a"].id` returns the id of the "a"-keyed resource.
* `[for value in aws_instance.example: value.id]` returns a list of all of the ids
  of each of the instances.

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(aws_instance.example)[*].id`

### 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.

A provider attribute marked as sensitive behaves similarly to an
[an input variable declared as sensitive](/language/values/variables#suppressing-values-in-cli-output),
where Terraform will hide the value in the plan and apply messages and will
also hide any other values you derive from it as sensitive.
However, there are some limitations to that behavior as described in
[Cases where Terraform may disclose a sensitive variable](/language/values/variables#cases-where-terraform-may-disclose-a-sensitive-variable).

If you use a sensitive value from a resource attribute as part of an
[output value](/language/values/outputs) then Terraform will require
you to also mark the output value itself as sensitive, to confirm that you
intended to export it.

Terraform will still record sensitive values in the [state](/language/state),
and so anyone who can access the state data will have access to the sensitive
values in cleartext. For more information, see
[_Sensitive Data in State_](/language/state/sensitive-data).

-> **Note:** Treating values derived from a sensitive resource attribute as
sensitive themselves was introduced in Terraform v0.15. Earlier versions of
Terraform will obscure the direct value of a sensitive resource attribute,
but will _not_ automatically obscure other values derived from sensitive
resource attributes.

### 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)`.
