When a data resource is used for the purposes of verifying a condition
about an object managed elsewhere (e.g. if the managed resource doesn't
directly export all of the information required for the condition) it's
important that we defer the data resource read to the apply step if the
corresponding managed resource has any changes pending.
Typically we'd expect that to come "for free" but unfortunately we have
a pragmatic special case in our handling of data resources where we
normally defer to the apply step only if a _direct_ dependency of the data
resource has a change pending, and allow a plan-time read if there's
a pending change in an indirect dependency. This allowed us to preserve
some compatibility with the questionable historical behavior of always
reading data resources proactively unless the configuration contains
unknown values, since the arguably-more-correct behavior would've been a
regression for anyone who had been depending on that before.
Since preconditions and postconditions didn't exist until now, we are not
constrained in the same way by backward compatibility, and so we can adopt
the more correct behavior in the case where a data resource has conditions
specified. This does unfortunately make the handling of data resources
with conditions subtly inconsistent with those that don't, but this is
a better situation than the alternative where it would be easy to get into
a trapped situation where the remote system is invalid and it's impossible
to plan the change that would make it valid again because the conditions
evaluate too soon, prior to the fix being applied.
@ -78,18 +78,23 @@ in more detail in the following sections.
## Data Resource Behavior
If the query constraint arguments for a data resource refer only to constant
values or values that are already known, the data resource will be read and its
state updated during Terraform's "refresh" phase, which runs prior to creating a plan.
This ensures that the retrieved data is available for use during planning and
so Terraform's plan will show the actual values obtained.
Query constraint arguments may refer to values that cannot be determined until
after configuration is applied, such as the id of a managed resource that has
not been created yet. In this case, reading from the data source is deferred
until the apply phase, and any references to the results of the data resource
elsewhere in configuration will themselves be unknown until after the
configuration has been applied.
Terraform 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. Terraform defers reading data
resources in the following situations:
* At least one of the given arguments is a managed resource attribute or
other value that Terraform 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](#custom-condition-checks)
and it depends directly or indirectly on a managed resource that itself
has planned changes in the current plan.
Refer to [Data Resource Dependencies](#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.
## Local-only Data Sources
@ -118,7 +123,9 @@ 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.
referencing the managed resource values through a `local` value, unless the
data resource itself has
[custom conditions](#custom-condition-checks).
~> **NOTE:** **In Terraform 0.12 and earlier**, due to the data resource behavior of deferring the read until the apply phase when depending on values that are not yet known, using `depends_on` with `data` resources will force the read to always be deferred to the apply phase, and therefore a configuration that uses `depends_on` with a `data` resource can never converge. Due to this behavior, we do not recommend using `depends_on` with data resources.
@ -92,11 +92,13 @@ The `lifecycle` block inside a `resource` or `data` block can include both `prec
- Terraform evaluates `precondition` blocks after evaluating existing `count` and `for_each` arguments. This lets Terraform evaluate the precondition separately for each instance and then make `each.key`, `count.index`, etc. available to those conditions. Terraform also evaluates preconditions before evaluating the resource's configuration arguments. Preconditions can take precedence over argument evaluation errors.
- Terraform evaluates `postcondition` blocks after planning and applying changes to a managed resource, or after reading from a data source. Postcondition failures prevent changes to other resources that depend on the failing resource.
In most cases, we do not recommend including both a `data` block and a `resource` block that both represent the same object in the same configuration. Doing so can prevent Terraform from understanding that the `data` block result can be affected by changes in the `resource` block. However, when you need to check a result of a `resource` block that the resource itself does not directly export, you can use a `data` block to check that object safely as long as you place the check as a direct `postcondition` of the `data` block. This tells Terraform that the `data` block is serving as a check of an object defined elsewhere, allowing Terraform to perform actions in the correct order.
#### Outputs
An `output` block can include a `precondition` block.
Preconditions can serve a symmetrical purpose to input variable `validation` blocks. Whereas input variable validation checks assumptions the module makes about its inputs, preconditions check guarantees that the module makes about its outputs. You can use preconditions to prevent Terraform from saving an invalid new output value in the state. You can also use them to preserve the output value from the previous apply, if applicable.
Preconditions can serve a symmetrical purpose to input variable `validation` blocks. Whereas input variable validation checks assumptions the module makes about its inputs, preconditions check guarantees that the module makes about its outputs. You can use preconditions to prevent Terraform from saving an invalid new output value in the state. You can also use them to preserve a valid output value from the previous apply, if applicable.
Terraform evaluates output value preconditions before evaluating the `value` expression to finalize the result. Preconditions can take precedence over potential errors in the `value` expression.
@ -144,16 +146,23 @@ data "aws_ebs_volume" "example" {