Terraform
data block reference
The data
block fetches data about a resource from the provider without provisioning an associated infrastructure object. You can reference data source attributes to configure other resources, keeping your configuration dynamic and preventing hardcoding. Refer to Query infrastructure data for more information.
The source type, arguments, and attributes depend on the provider. Refer to the provider documentation for more information.
Configuration model
The data
block supports the following configuration:
data "<TYPE>" "<LABEL>"
block- provider-specific arguments block | refer to your provider documentation
count
number | mutually exclusive withfor_each
depends_on
list of referencesfor_each
map or set of strings | mutually exclusive withcount
provider
referencelifecycle
blockprecondition
blockcondition
stringerror_message
& nbsp string
postcondition
blockcondition
stringerror_message
string
Complete configuration
The following data
block includes all built-in arguments supported in a data source:
data "<TYPE>" "<LABEL>" {
<PROVIDER-SPECIFIC ARGUMENTS>
count = <NUMBER> # `count` and `for_each` are mutually exclusive
depends_on = [ <RESOURCE.ADDRESS.EXPRESSION> ]
for_each = { # `for_each` and `count` are mutually exclusive
<KEY> = <VALUE>
}
for_each = [ # `for_each` accepts a map or a set of strings
"<VALUE>",
"<VALUE>"
]
provider = <REFERENCE.TO.ALIAS>
lifecycle {
precondition {
condition = <EXPRESSION>
error_message = "<STRING>"
}
postcondition {
condition = <EXPRESSION>
error_message = "<STRING>"
}
}
}
Specification
A data
block supports the following configuration.
data "<TYPE>" "<LABEL>"
You must set the following arguments for every data
block:
TYPE
: Specifies the data source type. Provider developers define the support data sources. Refer to the provider documentation for details. Terraform also includes theterraform_remote_state
data source, which lets you access state data from other workspaces.LABEL
: Specifies a name for the data source. Use thedata.<label>.<attribute>
syntax to reference the data. Refer to References to Named Values and Resource naming for expression syntax and label recommendations.
Provider-specific arguments
The provider developer determines which arguments you can define for a data source. Refer to the provider documentation for details.
count
The count
meta-argument instructs Terraform to provision multiple instances of the same data source with identical or similar configuration.
data "<TYPE>" "<LABEL>" {
count = <number>
}
You can reference variables or local values and use expressions to compute the value, but the value must resolve to a whole number.
In blocks where count
is set, Terraform exposes an additional count
object. You can reference the object to modify the configuration of each instance. The count
object has an index
attribute starting from 0
.
To refer to an individual instance of a data source created using the count
meta-argument, use the <TYPE>.<NAME>[INDEX]
syntax. For example, data.aws_instance.server[0]
refers to the first instance of the aws_instance
data source named server
.
Tip
You can use the count
argument as a conditional for creating data sources. For example, setting a count = var.creator ? 3 : 0
instructs Terraform to create three instances of the data source when a variable named creator
is set to true
. Refer to [Conditional Expressions]/terraform/language/expressions/conditionals) for more information.
The count
argument is a meta-argument, which is built into Terraform and controls the way that Terraform creates resources. Refer to Meta-arguments for more information.
Summary
- Data type: Number.
- Default: None.
depends_on
The depends_on
meta-argument specifies an upstream resource that the data source depends on. Terraform must complete all operations on the upstream resource before performing operations on the data source containing the depends_on
argument.
data "<TYPE>" "<LABEL>" {
depends_on = [ <resource reference> ]
}
When a data source configuration refers to another resource, Terraform identifies the dependency and creates the upstream resource first. In some cases, you may need Terraform to create one resource before creating a data source, even though the resource and the data source are configured independently.
Use the depends_on
argument when the resource and data source do not reference each other. We recommend always including a comment to explain dependencies when using a depends_on
argument.
When using the depends_on
meta-argument, you can only reference other resources or child modules in the same root module. The list cannot include arbitrary expressions. Any values referenced in the depends_on
list must be known before Terraform begins the operation so that it can evaluate dependencies.
Specifying an entire module in the depends_on
argument affects the order in which Terraform provisions all of the resources and data sources associated with that module. Refer to Resource dependencies and Data resource dependencies for more information.
The depends_on argument is a meta-argument, which is built into Terraform and controls the way that Terraform creates resources. Refer to Meta-arguments for more information.
Summary
- Data type: List.
- Default: None.
- Example: Specify a dependency.
for_each
The for_each
meta-argument instructs Terraform to provision similar resources without requiring separate configuration blocks for each resource.
data "<TYPE>" "<LABEL>" {
for_each = [ "<VALUE>" ]
# . . .
}
The for_each
meta-argument accepts a map or a set of strings and creates an instance for each item in that map or set. Each instance is associated with a distinct infrastructure object. Terraform creates, updates, or destroys each instance when applying changes to the configuration.
You can use pure functions, such as toset()
and tomap()
, to create a map or set for use in the for_each
argument. Whether iterating over the keys of a map or set of strings, all must be known values. Otherwise, Terraform prints an error message that for_each
has dependencies that it cannot determine before applying the configuration.
Keys in the for_each
argument cannot be the result of or rely on the result of impure functions, including uuid
, bcrypt
, or timestamp
, because Terraform defers evaluating impure functions during the main evaluation step.
The for_each
argument does not implicitly convert lists or tuples to sets. To declare data source instances based on a nested data structure or combinations of elements from multiple data structures, you can use Terraform expressions and functions to derive a suitable value. Refer to the following examples for more information:
- Transform a multi-level nested structure into a flat list.
- Combine collections to produce a list of element combinations.
You cannot use sensitive values, such as sensitive input variables, sensitive outputs, or sensitive resource attributes, as arguments in for_each
. Terraform uses the value in for_each
to identify the data source instance and always discloses it in UI output, so sensitive values are not allowed. Terraform returns an error if you attempt to use sensitive values as for_each
arguments.
If you transform a value containing sensitive data into an argument for use in for_each
, most functions in Terraform return a sensitive result when given an argument with any sensitive content. In many cases, you can achieve similar results with a for
expression. For example, to call keys(local.map)
where local.map
is an object with sensitive values, but non-sensitive keys, you can create a value to pass to for_each
using toset([for k,v in local.map : k])
.
Refer to Manage sensitive data for more information.
The for_each
argument exposes an each
object that you can reference within the same block to modify specific instances of the data source. The object has the following attributes:
each.key
: Map key or list member that corresponds to an instance.each.value
: Map value that corresponds to an instance.
Use the <TYPE>.<NAME>[<KEY>]
syntax to access an instance of a data source created using for_each
. For example, data.azurerm_resource_group.rg["a_group"]
refers to an instance of the data.azurrm_resource_group
resource named rg
created off of the a_group
key.
The for_each
argument is a meta-argument, which is built into Terraform and controls the way that Terraform creates resources. Refer to Meta-arguments for more information.
Summary
- Data type: Map or set of strings.
- Default: None.
provider
The provider
argument instructs Terraform to use an alternate provider configuration.
data "<TYPE>" "<LABEL>" {
provider = <provider>.<alias>
}
By default, Terraform automatically selects a provider based on the data source type, but you can create multiple provider configurations and use a non-default configuration for specific data sources.
Use the <PROVIDER>.<ALIAS>
syntax to reference a provider configuration in the provider
argument. Refer to Using an alternate provider configuration for an example of how to reference a specific provider configuration.
The provider
argument is a meta-argument, which is built into Terraform and controls the way that Terraform creates resources. Refer to Meta-arguments for more information.
Summary
- Data type: Reference.
- Default: None.
lifecycle
The lifecycle
block defines lifecycle rules for how Terraform operates on your data source.
data "<TYPE>" "<LABEL>" {
lifecycle {
<lifecycle>
}
}
You can specify the following lifecycle rules to manage how Terraform performs operations on the resource:
precondition
: Specifies a condition that Terraform evaluates before creating the data source. Refer to Validate your configuration for more information.postcondition
: Specifies a condition that Terraform evaluates after creating the data source. Refer to Validate your configuration for more information.
Configurations defined in the lifecycle
block affect how Terraform constructs and traverses the dependency graph. You can only use literal values in the lifecycle block because Terraform processes them before it evaluates arbitrary expressions for a run.
The lifecycle
block is a meta-argument. Meta-arguments are built-in arguments that control how Terraform creates data sources. Refer to Meta-arguments for more information.
Summary
- Data type: Block.
- Default: None.
precondition
The precondition
block specifies a condition that must return true
before Terraform evaluates and performs operations on the data source. You can also specify an error message for Terraform to print when the condition returns false
.
resource {
lifecycle {
precondition {
condition = <expression>
error_message = "<message>"
}
}
}
The following arguments in the precondition
block are required:
Argument | Description | Data type |
---|---|---|
condition | Expression that must return true for Terraform to proceed with an operation. You can refer to any other object in the same configuration scope unless the reference creates a cyclic dependency. | Expression that can include references, strings, and operators. |
error_message | Message that Terraform prints to the console if the condition returns false . | String |
Terraform evaluates precondition
blocks before evaluating the resource's configuration arguments. The precondition
can take precedence over argument evaluation errors.
Terraform evaluates precondition blocks after evaluating count
and for_each
meta-arguments. As a result, Terraform can evaluate the precondition
separately for each instance and makes the each.key
and count.index
objects available in the conditions.
You can include a precondition
and postcondition
block in the same resource. Do not add precondition
blocks to a resource
block and a data
block that represent the same object in the same configuration. Doing so may cause Terraform to ignore changes to the data
block that result from changes in the resource
block.
Refer to Validate your configuration for information about adding validations to your Terraform configuration.
Summary
- Data type: Block.
- Default: None.
- Example: Apply custom conditions.
postcondition
The postcondition
block specifies a condition that must return true
after Terraform performs operations on the data source. You can also specify an error message for Terraform to print to the console when the condition returns false
.
data "<TYPE>" "<LABEL>" {
lifecycle {
postcondition {
condition = <expression>
error_message = "<message>"
}
}
}
The following arguments in the precondition
block are required:
Argument | Description | Data type |
---|---|---|
condition | Expression that must return true for Terraform to perform operations on downstream resources. You can refer to any other object in the same configuration scope unless the reference creates a cyclic dependency. | Expression that can include references, strings, and operators. |
error_message | Message that Terraform prints to the console if the condition returns false . | String |
Terraform evaluates postcondition
blocks after planning and applying changes to the data source. Postcondition failures prevent changes to other resources that depend on the failing resource.
You can include a postcondition
and precondition
block in the same resource. Do not add postcondition
blocks to a resource
block and a data
block that represent the same object in the same configuration. Doing so may cause Terraform to ignore changes to the data
block that result from changes in the resource
block.
Refer to Validate your configuration for information about adding validations to your Terraform configuration.
Summary
- Data type: Block.
- Default: None.
- Example: Apply custom conditions.
Examples
The following examples show how to write configuration for common use cases.
Specify a dependency
In the following example, Terraform gets an AMI for use in the aws_instance
resource after creating the aws_subnet.example_subnet
resource:
resource "aws_vpc" "example_vpc" {
cidr_block = "10.0.0.0/16"
}
resource "aws_subnet" "example_subnet" {
vpc_id = aws_vpc.example_vpc.id
cidr_block = "10.0.1.0/24"
}
data "aws_ami" "example_ami" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["amzn2-ami-hvm-*"]
}
filter {
name = "architecture"
values = ["x86_64"]
}
depends_on = [aws_subnet.example_subnet]
}
resource "aws_instance" "example_instance" {
ami = data.aws_ami.example_ami.id
instance_type = "t2.micro"
subnet_id = aws_subnet.example_subnet.id
}
Note that this is a simplified example and does not represent a real-world use case. The depends_on
argument changes the dependency graph so that Terraform creates the resources in a linear order. Without the argument, Terraform would still successfully create the resources.
Select an alternate provider configuration
In the following example, the google_compute_instance
data source selects the provider configuration with the europe
alias.
provider "google" {
region = "us-central1"
}
provider "google" {
alias = "europe"
region = "europe-west1"
}
data "google_compute_instance" "example" {
provider = google.europe
# ...
}
Apply custom conditions
The following example includes several configurations that illustrate how to define precondition
and postcondition
arguments in the lifecycle
meta-argument.
The following data
block instructs Terraform to retrieve the ID of the ami-abc123
AMI:
data "aws_ami" "example" {
owners = ["amazon"]
filter {
name = "image-id"
values = ["ami-abc123"]
}
}
In the following code, the precondition
block specifies that the AMI ID retrieved from the data
block must include x86_64
as its architecture
attribute. The postcondition
block specifies that the EC2 instance must be allocated a public DNS hostname. When either condition is not met, Terraform returns the error_message
for the failed condition:
resource "aws_instance" "example" {
instance_type = "t3.micro"
ami = data.aws_ami.example.id
lifecycle {
precondition {
condition = data.aws_ami.example.architecture == "x86_64"
error_message = "The selected AMI must be for the x86_64 architecture."
}
postcondition {
condition = self.public_dns != ""
error_message = "EC2 instance must be in a VPC that has public DNS hostnames enabled."
}
}
}
The following data
block retrieves the root storage volume connected to the aws_instance.example
EC2 instance using the volume_id
attribute. When a data
resource verifies the result of a managed resource declared in the same configuration, you must define the check in a postcondition
block in the resource so that Terraform waits for changes to the managed resource to complete before reading the data resource.
data "aws_ebs_volume" "example" {
filter {
name = "volume-id"
values = [aws_instance.example.root_block_device[0].volume_id]
}
lifecycle {
# The EC2 instance will have an encrypted root volume.
postcondition {
condition = self.encrypted
error_message = "The server's root volume is not encrypted."
}
}
}
output "api_base_url" {
value = "https://${aws_instance.example.private_dns}:8433/"
}