Skip to main content

Data Sources

Data sources allow OpenTofu to use information defined outside of OpenTofu, defined by another separate OpenTofu configuration, or modified by functions.

Each provider may offer data sources alongside its set of resource types.

Using Data Sources​

A data source is accessed via a special kind of resource known as a data resource, declared using a data block:

Code Block
data "aws_ami" "example" {
most_recent = true

owners = ["self"]
tags = {
Name = "app-server"
Tested = "true"
}
}

A data block requests that OpenTofu read from a given data source ("aws_ami") and export the result under the given local name ("example"). The name is used to refer to this resource from elsewhere in the same OpenTofu module, but has no significance outside of the scope of a module.

The data source and name together serve as an identifier for a given resource and so must be unique within a module.

Within the block body (between { and }) are query constraints defined by the data source. Most arguments in this section depend on the data source, and indeed in this example most_recent, owners and tags are all arguments defined specifically for the aws_ami data source.

When distinguishing from data resources, the primary kind of resource (as declared by a resource block) is known as a managed resource. Both kinds of resources take arguments and export attributes for use in configuration, but while managed resources cause OpenTofu to create, update, and delete infrastructure objects, data resources cause OpenTofu only to read objects. For brevity, managed resources are often referred to just as "resources" when the meaning is clear from context.

Data Source Arguments​

Each data resource is associated with a single data source, which determines the kind of object (or objects) it reads and what query constraint arguments are available.

Each data source in turn belongs to a provider, which is a plugin for OpenTofu that offers a collection of resource types and data sources that most often belong to a single cloud or on-premises infrastructure platform.

Most of the items within the body of a data block are defined by and specific to the selected data source, and these arguments can make full use of expressions and other dynamic OpenTofu language features.

However, there are some meta-arguments that are defined by OpenTofu itself and apply across all data resource types. These arguments often have additional restrictions on what language features can be used with them, and are described in more detail in the following sections.

Data Resource Behavior​

OpenTofu reads data resources during the planning phase when possible, but announces in the plan when it must defer reading resources until the apply phase to preserve the order of operations. OpenTofu defers reading data resources in the following situations:

  • At least one of the given arguments is a managed resource attribute or other value that OpenTofu cannot predict until the apply step.
  • The data resource depends directly on a managed resource that itself has planned changes in the current plan.
  • The data resource has custom conditions and it depends directly or indirectly on a managed resource that itself has planned changes in the current plan.

Refer to Data Resource Dependencies for details on what it means for a data resource to depend on other objects. Any resulting attribute of such a data resource will be unknown during planning, so it cannot be used in situations where values must be fully known.

Meta-Arguments​

The OpenTofu language defines several meta-arguments, which can be used with any data resource type to change the behavior of resources.

The following meta-arguments are documented on separate pages:

Lifecycle Customizations​

A lifecycle block inside a data block allows some customization of OpenTofu's behavior relating to instances of a resource at different phases of its lifecycle.

Code Block
data "example" "example" {
# ...normal resource arguments...

lifecycle {
# ...lifecycle arguments...
}
}

The following arguments and nested block types are supported in the lifecycle block for a data resource:

  • enabled (bool) - Controls whether the data resource will be read by OpenTofu. When set to false, the resource is excluded from the configuration as if it didn't exist. When set to true (the default), the resource operates normally.

    For more information, refer to the enabled meta-argument.

  • precondition and postcondition blocks, as described in Custom Conditions.

Local-only Data Sources​

While many data sources correspond to an infrastructure object type that is accessed via a remote network API, some specialized data sources operate only within OpenTofu itself, calculating some results and exposing them for use elsewhere.

For example, local-only data sources exist for rendering templates, reading local files, and rendering AWS IAM policies.

The behavior of local-only data sources is the same as all other data sources, but their result data exists only temporarily during an OpenTofu operation, and is re-calculated each time a new plan is created.

Data Resource Dependencies​

Data resources have the same dependency resolution behavior as defined for managed resources. Setting the depends_on meta-argument within data blocks defers reading of the data source until after all changes to the dependencies have been applied.

In order to ensure that data sources are accessing the most up to date information possible in a wide variety of use cases, arguments directly referencing managed resources are treated the same as if the resource was listed in depends_on. This behavior can be avoided when desired by indirectly referencing the managed resource values through a local value, unless the data resource itself has custom conditions.

Custom Condition Checks​

You can use precondition and postcondition blocks to specify assumptions and guarantees about how the data source operates. The following examples creates a postcondition that checks whether the AMI has the correct tags.

Code Block
data "aws_ami" "example" {
id = var.aws_ami_id

lifecycle {
# The AMI ID must refer to an existing AMI that has the tag "nomad-server".
postcondition {
condition = self.tags["Component"] == "nomad-server"
error_message = "tags[\"Component\"] must be \"nomad-server\"."
}
}
}

Custom conditions can help capture assumptions, helping future maintainers understand the configuration design and intent. They also return useful information about errors earlier and in context, helping consumers more easily diagnose issues in their configurations.

Refer to Custom Condition Checks for more details.

Non-Default Provider Configurations​

Similarly to resources, when a module has multiple configurations for the same provider you can specify which configuration to use with the provider meta-argument:

Code Block
data "aws_ami" "web" {
provider = aws.west

# ...
}

See The Resource provider Meta-Argument for more information.