mirror of
https://github.com/opentffoundation/opentf.git
synced 2026-02-17 19:00:37 -05:00
Signed-off-by: Ilia Gogotchuri <ilia.gogotchuri0@gmail.com> Co-authored-by: Andrei Ciobanu <andrei.ciobanu@opentofu.org>
324 lines
17 KiB
Plaintext
324 lines
17 KiB
Plaintext
---
|
|
description: >-
|
|
Learn how OpenTofu uses resource blocks to create infrastructure objects.
|
|
Also learn about resource dependencies and how to access resource attributes.
|
|
---
|
|
|
|
# Resource Behavior
|
|
|
|
A `resource` block declares that you want a particular infrastructure object
|
|
to exist with the given settings. If you are writing a new configuration for
|
|
the first time, the resources it defines will exist _only_ in the configuration,
|
|
and will not yet represent real infrastructure objects in the target platform.
|
|
|
|
_Applying_ an OpenTofu configuration is the process of creating, updating,
|
|
and destroying real infrastructure objects in order to make their settings
|
|
match the configuration.
|
|
|
|
## How OpenTofu Applies a Configuration
|
|
|
|
When OpenTofu creates a new infrastructure object represented by a `resource`
|
|
block, the identifier for that real object is saved in OpenTofu's
|
|
[state](../../language/state/index.mdx), allowing it to be updated and destroyed
|
|
in response to future changes. For resource blocks that already have an
|
|
associated infrastructure object in the state, OpenTofu compares the
|
|
actual configuration of the object with the arguments given in the
|
|
configuration and, if necessary, updates the object to match the configuration.
|
|
|
|
In summary, applying an OpenTofu configuration will:
|
|
|
|
- _Create_ resources that exist in the configuration but are not associated with a real infrastructure object in the state.
|
|
- _Destroy_ resources that exist in the state but no longer exist in the configuration.
|
|
- _Forget_ resources that exist in the state but no longer in the configuration and are referenced in a `removed` block within the configuration.
|
|
- _Update in-place_ resources whose arguments have changed.
|
|
- _Destroy and re-create_ resources whose arguments have changed but which cannot be updated in-place due to remote API limitations.
|
|
|
|
This general behavior applies for all resources, regardless of type. The
|
|
details of what it means to create, update, or destroy a resource are different
|
|
for each resource type, but this standard set of verbs is common across them
|
|
all.
|
|
|
|
The meta-arguments within `resource` blocks, documented in the
|
|
sections below, allow some details of this standard resource behavior to be
|
|
customized on a per-resource basis.
|
|
|
|
## Accessing Resource Attributes
|
|
|
|
[Expressions](../../language/expressions/index.mdx) within an OpenTofu module can access
|
|
information about resources in the same module, and you can use that information
|
|
to help configure other resources. Use the `<RESOURCE TYPE>.<NAME>.<ATTRIBUTE>`
|
|
syntax to reference a resource attribute in an expression.
|
|
|
|
In addition to arguments specified in the configuration, resources often provide
|
|
read-only attributes with information obtained from the remote API; this often
|
|
includes things that can't be known until the resource is created, like the
|
|
resource's unique random ID.
|
|
|
|
Many providers also include [data sources](../../language/data-sources/index.mdx),
|
|
which are a special type of resource used only for looking up information.
|
|
|
|
For a list of the attributes a resource or data source type provides, consult
|
|
its documentation; these are generally included in a second list below its list
|
|
of configurable arguments.
|
|
|
|
For more information about referencing resource attributes in expressions, see
|
|
[Expressions: References to Resource Attributes](../../language/expressions/references.mdx#references-to-resource-attributes).
|
|
|
|
## Resource Dependencies
|
|
|
|
Most resources in a configuration don't have any particular relationship, and
|
|
OpenTofu can make changes to several unrelated resources in parallel.
|
|
|
|
However, some resources must be processed after other specific resources;
|
|
sometimes this is because of how the resource works, and sometimes the
|
|
resource's configuration just requires information generated by another
|
|
resource.
|
|
|
|
Most resource dependencies are handled automatically. OpenTofu analyses any
|
|
[expressions](../../language/expressions/index.mdx) within a `resource` block to find references
|
|
to other objects, and treats those references as implicit ordering requirements
|
|
when creating, updating, or destroying resources. Since most resources with
|
|
behavioral dependencies on other resources also refer to those resources' data,
|
|
it's usually not necessary to manually specify dependencies between resources.
|
|
|
|
However, some dependencies cannot be recognized implicitly in configuration. For
|
|
example, if OpenTofu must manage access control policies _and_ take actions
|
|
that require those policies to be present, there is a hidden dependency between
|
|
the access policy and a resource whose creation depends on it. In these rare
|
|
cases,
|
|
[the `depends_on` meta-argument](../../language/meta-arguments/depends_on.mdx)
|
|
can explicitly specify a dependency.
|
|
|
|
You can also use the [`replace_triggered_by` lifecycle argument](#replace_triggered_by) to add dependencies between otherwise independent resources. It forces OpenTofu to replace the parent resource when there is a change to a referenced resource or resource attribute.
|
|
|
|
## Lifecycle Customizations
|
|
|
|
A `lifecycle` block inside a `resource` block allows some customization of
|
|
OpenTofu's behavior relating to instances of a resource at different phases
|
|
of its lifecycle.
|
|
|
|
```hcl
|
|
resource "example" "example" {
|
|
# ...normal resource arguments...
|
|
|
|
lifecycle {
|
|
# ...lifecycle arguments...
|
|
}
|
|
}
|
|
```
|
|
|
|
The following arguments and nested block types are supported in the `lifecycle`
|
|
block for a managed resource:
|
|
|
|
* `create_before_destroy` (bool) - By default, when OpenTofu must change
|
|
a resource argument that cannot be updated in-place due to
|
|
remote API limitations, OpenTofu will instead destroy the existing object
|
|
and then create a new replacement object with the new configured arguments.
|
|
|
|
The `create_before_destroy` meta-argument changes this behavior so that
|
|
the new replacement object is created _first,_ and the prior object
|
|
is destroyed after the replacement is created.
|
|
|
|
This is an opt-in behavior because many remote object types have unique
|
|
name requirements or other constraints that must be accommodated for
|
|
both a new and an old object to exist concurrently. Some resource types
|
|
offer special options to append a random suffix onto each object name to
|
|
avoid collisions, for example. OpenTofu CLI cannot automatically activate
|
|
such features, so you must understand the constraints for each resource
|
|
type before using `create_before_destroy` with it.
|
|
|
|
Note that OpenTofu propagates and applies the `create_before_destroy` meta-attribute
|
|
behaviour to all resource dependencies. For example, if `create_before_destroy`
|
|
is enabled on resource A but not on resource B, but resource A is dependent on
|
|
resource B, then OpenTofu enables `create_before_destroy` for resource B
|
|
implicitly by default and stores it in state snapshots. You cannot override
|
|
`create_before_destroy` to `false` on resource B because that would cause
|
|
dependency cycles in the graph.
|
|
|
|
Destroy provisioners of this resource do not run during replacement if
|
|
`create_before_destroy` is set to `true`. [GitHub issue #13549](https://github.com/hashicorp/terraform/issues/13549) contains more details.
|
|
|
|
* `enabled` (bool) - Controls whether a resource is created and managed by OpenTofu.
|
|
When set to `false`, the resource is excluded from the configuration as if it didn't exist,
|
|
and any existing infrastructure object will be destroyed. When set to `true` (the default),
|
|
the resource operates normally.
|
|
|
|
For more information, refer to [the `enabled` meta-argument](../../language/meta-arguments/enabled.mdx).
|
|
|
|
* `prevent_destroy` (bool) - This meta-argument, when set to `true`, will
|
|
cause OpenTofu to reject with an error any plan that would destroy the
|
|
infrastructure object associated with the resource, as long as the argument
|
|
remains present in the configuration.
|
|
|
|
This can be used as a measure of safety against the accidental replacement
|
|
of objects that may be costly to reproduce, such as database instances.
|
|
However, it will make certain configuration changes impossible to apply,
|
|
and will prevent the use of the `tofu destroy` command once such
|
|
objects are created, and so this option should be used sparingly.
|
|
|
|
Since this argument must be present in configuration for the protection to
|
|
be active, this setting cannot prevent the remote object from being destroyed
|
|
when the `resource` block is removed from configuration entirely: in that
|
|
case, the `prevent_destroy` setting is removed along with it, and so OpenTofu
|
|
would allow the destroy operation to succeed.
|
|
|
|
In case you want to retain the infrastructure object even after removing the
|
|
`resource` block from configuration, consider using the `destroy` argument
|
|
documented below instead. Note that, if you set `destroy = false`, OpenTofu will
|
|
change the `destroy` actions to a variant of `forget` action, and `prevent_destroy`
|
|
will not have any effect.
|
|
|
|
* `destroy` (bool) - By default, when a resource is removed from the configuration,
|
|
requires replacement, or is explicitly destroyed using the `tofu destroy` command,
|
|
OpenTofu will destroy the corresponding infrastructure object. Setting this
|
|
meta-argument to `false` changes this behavior so that OpenTofu will instead
|
|
"forget" the resource instance, removing it from the state without destroying the actual
|
|
infrastructure object.
|
|
|
|
:::note
|
|
`lifecycle.destroy` only accepts constant boolean values (`true` or `false`).
|
|
:::
|
|
|
|
When a resource with `destroy = false` is removed from the configuration or requires replacement,
|
|
OpenTofu will plan to **forget** it rather than **destroy** it. The resource will
|
|
be removed from the state file, but the actual infrastructure object will
|
|
remain unchanged in your cloud provider or other remote system. If the resource requires replacement,
|
|
OpenTofu will then create a new resource instance as per the current configuration.
|
|
|
|
This is useful when you want to keep the resource in configuration but alter its destruction behavior. Incomplete list of use cases includes:
|
|
- Retain critical or compliance resources even when destroying the rest of the environment, without manually removing them from configuration beforehand.
|
|
Enables more automation with reviewable configuration changes.
|
|
- Retain old resource instances when performing resource replacements or infrastructure upgrades,
|
|
avoiding downtime or data loss. Making potential rollbacks faster and easier.
|
|
- Certain resource instances might be impossible or impractical to destroy due to external dependencies or constraints.
|
|
|
|
Note that this argument is **persisted in the state**, once you set and apply `destroy = false` for a resource
|
|
OpenTofu will not plan the resource destruction unless you explicitly change it back to `true` or remove the option from the corresponding resource configuration block.
|
|
OpenTofu errs on the side of caution and avoids destroying resources that were marked with `destroy = false` in the last applied configuration for the resource instance.
|
|
If you are using single instance resources (no count or for_each), you can override this attribute in the state by writing explicit `removed` block for the resource instance with `destroy = true` option.
|
|
|
|
:::note
|
|
This argument can also be used in [`removed` blocks](syntax.mdx#removing-resources)
|
|
to control whether resources should be destroyed or forgotten when explicitly
|
|
removing them from OpenTofu management. The behavior is identical in both contexts.
|
|
Generally, prefer to use `removed` blocks when you want to remove resources from your configurations as a method of refactoring.
|
|
Use `destroy` lifecycle argument when you want to control the destruction behavior of resources that are still present in your configuration.
|
|
:::
|
|
|
|
The `destroy` argument also applies when using the `tofu destroy` command.
|
|
Resources with `destroy = false` will be forgotten rather than destroyed,
|
|
and the command will exit with a non-zero status code to indicate that some
|
|
resources were not fully removed. See the [`tofu destroy` command documentation](../../cli/commands/destroy.mdx#forgotten-resources)
|
|
for more details.
|
|
|
|
:::warning
|
|
Once a resource is forgotten (removed from state), OpenTofu will no longer
|
|
track it. If you later add the resource back to your configuration with the
|
|
same address, OpenTofu will attempt to create a new resource, which may fail
|
|
if the infrastructure object still exists. You may need to import the existing
|
|
resource or use a different resource address.
|
|
:::
|
|
|
|
* <span id="ignore_changes">`ignore_changes`</span> (list of attribute names) - By default, OpenTofu detects
|
|
any difference in the current settings of a real infrastructure object
|
|
and plans to update the remote object to match configuration.
|
|
|
|
The `ignore_changes` feature is intended to be used when a resource is
|
|
created with references to data that may change in the future, but should
|
|
not affect said resource after its creation. In some rare cases, settings
|
|
of a remote object are modified by processes outside of OpenTofu, which
|
|
OpenTofu would then attempt to "fix" on the next run. In order to make
|
|
OpenTofu share management responsibilities of a single object with a
|
|
separate process, the `ignore_changes` meta-argument specifies resource
|
|
attributes that OpenTofu should ignore when planning updates to the
|
|
associated remote object.
|
|
|
|
The arguments corresponding to the given attribute names are considered
|
|
when planning a _create_ operation, but are ignored when planning an
|
|
_update_. The arguments are the relative address of the attributes in the
|
|
resource. Map and list elements can be referenced using index notation,
|
|
like `tags["Name"]` and `list[0]` respectively.
|
|
|
|
```hcl
|
|
resource "aws_instance" "example" {
|
|
# ...
|
|
|
|
lifecycle {
|
|
ignore_changes = [
|
|
# Ignore changes to tags, e.g. because a management agent
|
|
# updates these based on some ruleset managed elsewhere.
|
|
tags,
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
Use the special keyword `all` instead of an attribute list to instruct
|
|
OpenTofu to ignore changes to _all_ attributes, which means that OpenTofu can
|
|
create and destroy the remote object but will never propose updates to it.
|
|
|
|
Only attributes defined by the resource type can be ignored.
|
|
`ignore_changes` cannot be applied to itself or to any other meta-arguments.
|
|
|
|
* `precondition` and `postcondition` blocks, as described in
|
|
[Custom Conditions](../../language/expressions/custom-conditions.mdx#preconditions-and-postconditions).
|
|
|
|
* <span id="replace_triggered_by">`replace_triggered_by`</span> (list of resource or attribute references) -
|
|
Replaces the resource when any of the referenced
|
|
items change. Write a list of expressions referencing managed resources,
|
|
resource instances, or instance attributes. When used in a resource that
|
|
uses `count` or `for_each`, you can use `count.index` or `each.key` in the
|
|
expression to refer to specific instances of other resources that are
|
|
configured with the same count or collection.
|
|
|
|
References trigger replacement in the following conditions:
|
|
|
|
- If the reference is to a resource with multiple instances, a plan to
|
|
update or replace any instance will trigger replacement.
|
|
- If the reference is to a single resource instance, a plan to update or
|
|
replace that instance will trigger replacement.
|
|
- If the reference is to a single attribute of a resource instance, any
|
|
change to the attribute value will trigger replacement.
|
|
|
|
You can only refer to managed resources in `replace_triggered_by`
|
|
expressions. This lets you modify these expressions without forcing
|
|
replacement.
|
|
|
|
```hcl
|
|
resource "aws_appautoscaling_target" "ecs_target" {
|
|
# ...
|
|
lifecycle {
|
|
replace_triggered_by = [
|
|
# Replace `aws_appautoscaling_target` each time this instance of
|
|
# the `aws_ecs_service` is replaced.
|
|
aws_ecs_service.svc.id
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
`replace_triggered_by` allows only resource addresses because the decision is
|
|
based on the planned actions for all of the given resources. Plain values such
|
|
as local values or input variables do not have planned actions of their own,
|
|
but you can treat them with a resource-like lifecycle by using them with
|
|
[the `terraform_data` resource type](tf-data.mdx).
|
|
|
|
## Local-only Resources
|
|
|
|
While most resource types correspond to an infrastructure object type that
|
|
is managed via a remote network API, there are certain specialized resource
|
|
types that operate only within OpenTofu itself, calculating some results and
|
|
saving those results in the state for future use.
|
|
|
|
For example, local-only resource types exist for
|
|
[generating private keys](https://registry.terraform.io/providers/hashicorp/tls/latest/docs/resources/private_key),
|
|
[issuing self-signed TLS certificates](https://registry.terraform.io/providers/hashicorp/tls/latest/docs/resources/self_signed_cert),
|
|
and even [generating random ids](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/id).
|
|
While these resource types often have a more marginal purpose than those
|
|
managing "real" infrastructure objects, they can be useful as glue to help
|
|
connect together other resources.
|
|
|
|
The behavior of local-only resources is the same as all other resources, but
|
|
their result data exists only within the OpenTofu state. "Destroying" such
|
|
a resource means only to remove it from the state, discarding its data.
|