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
countnumber | mutually exclusive withfor_eachdepends_onlist of referencesfor_eachmap or set of strings | mutually exclusive withcountproviderreferencelifecycleblockpreconditionblockconditionstringerror_message& nbsp string
postconditionblockconditionstringerror_messagestring
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_statedata 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/"
}