Add docs for the conditional enabled lifecycle attribute (#3380)

Signed-off-by: Diogenes Fernandes <diofeher@gmail.com>
Co-authored-by: Martin Atkins <mart@degeneration.co.uk>
Co-authored-by: Andrei Ciobanu <andrei.ciobanu@opentofu.org>
This commit is contained in:
Diógenes Fernandes
2025-10-16 13:10:00 -03:00
committed by GitHub
parent c27094e816
commit d42dcc3b0a
8 changed files with 150 additions and 12 deletions

View File

@@ -165,8 +165,23 @@ as defined for managed resources, with the same syntax and behavior.
## Lifecycle Customizations ## Lifecycle Customizations
Data resources do not have any customization settings available Data resources support a `lifecycle` block that includes the [`enabled`](../../language/meta-arguments/enabled.mdx) argument to conditionally enable or disable the data resource.
for their lifecycle. However, the `lifecycle` block is reserved for future versions.
```hcl
variable "fetch_ami_data" {
type = bool
default = true
}
data "aws_ami" "example" {
most_recent = true
owners = ["self"]
lifecycle {
enabled = var.fetch_ami_data
}
}
```
## Example ## Example
@@ -214,9 +229,9 @@ resource "aws_instance" "web" {
## Meta-Arguments ## Meta-Arguments
As data sources are essentially a read only subset of resources, they also As data sources are essentially a read-only subset of resources, they also
support the same [meta-arguments](../../language/resources/syntax.mdx#meta-arguments) of resources support the same [meta-arguments](../../language/resources/syntax.mdx#meta-arguments) as resources
with the exception of the with the exception of a slightly simpler version of the
[`lifecycle` configuration block](../../language/meta-arguments/lifecycle.mdx). [`lifecycle` configuration block](../../language/meta-arguments/lifecycle.mdx).
### Non-Default Provider Configurations ### Non-Default Provider Configurations

View File

@@ -40,7 +40,8 @@ Besides the attributes in the schema of an ephemeral resource, the block support
* [`for_each`](../../language/meta-arguments/for_each.mdx) * [`for_each`](../../language/meta-arguments/for_each.mdx)
* [`provider`](../../language/meta-arguments/resource-provider.mdx) * [`provider`](../../language/meta-arguments/resource-provider.mdx)
* [`lifecycle`](../../language/meta-arguments/lifecycle.mdx) * [`lifecycle`](../../language/meta-arguments/lifecycle.mdx)
* Only [`precondition` and `postcondition`](../../language/expressions/custom-conditions.mdx#preconditions-and-postconditions) * [`enabled`](../../language/meta-arguments/enabled.mdx) for conditional enabling
* [`precondition` and `postcondition`](../../language/expressions/custom-conditions.mdx#preconditions-and-postconditions)
## Deferred opening ## Deferred opening
By design, the ephemeral resources cannot be opened if the configuration is not fully known. By design, the ephemeral resources cannot be opened if the configuration is not fully known.

View File

@@ -7,7 +7,7 @@ description: >-
# The `count` Meta-Argument # The `count` Meta-Argument
:::note :::note
A given resource or module block cannot use both `count` and `for_each`. A given resource or module block cannot use `count` together with `enabled` or `for_each`.
::: :::
By default, a [resource block](../../language/resources/syntax.mdx) configures one real By default, a [resource block](../../language/resources/syntax.mdx) configures one real
@@ -45,6 +45,13 @@ resource "aws_instance" "server" {
} }
``` ```
:::tip
If you're using `count = var.enabled ? 1 : 0` to conditionally enable/disable a
single resource or module, consider using the [the `enabled` argument in a `lifecycle` block](../../language/meta-arguments/enabled.mdx)
argument instead. It provides cleaner syntax without requiring array indexing and supports
automatic migration from the `count` pattern.
:::
## The `count` Object ## The `count` Object
In blocks where `count` is set, an additional `count` object is In blocks where `count` is set, an additional `count` object is

View File

@@ -0,0 +1,81 @@
---
description: >-
The enabled meta-argument allows you to conditionally create or skip a single
resource or module instance based on a boolean value.
---
# The `enabled` Meta-Argument
:::note
A given resource or module block cannot use `enabled` together with `count` or `for_each`.
:::
The `enabled` meta-argument in a `lifecycle` block provides a cleaner way to conditionally create or skip a
single resource or module instance. Unlike the traditional `count = var.enabled ? 1 : 0`
workaround, which requires array indexing to access single instances, `enabled` allows
direct access when the resource is created and properly handles the null state when disabled.
## Basic Syntax
`enabled` is a meta-argument that goes inside a `lifecycle` block. It accepts expressions that turn into boolean values to determine whether the resource or module should be created.
```hcl
variable "create_instance" {
type = bool
default = true
}
resource "aws_instance" "example" {
# ...
lifecycle {
enabled = var.create_instance
}
}
```
When `enabled` is `true` (or not specified), the resource behaves normally. When `enabled`
is `false`, the resource is not created and evaluates to `null`.
## Accessing Disabled Resources
When a resource might be disabled, it evaluates to `null` and cannot be accessed directly.
You must use conditional expressions to handle this safely:
```hcl
# Using try() - most concise but masks other errors
output "instance_id" {
value = try(aws_instance.example.id, "not-created")
}
# Using null check - most verbose but clearest intent
output "instance_id" {
value = aws_instance.example != null ? aws_instance.example.id : "not-created"
}
```
Attempting to directly access a resource configured with `enabled = false` will result in an error during `plan` or `apply`:
```
│ Error: Attempt to get attribute from null value
│ on main.tf line 10, in output "instance_id":
│ 10: value = aws_instance.example.id
│ ├────────────────
│ │ aws_instance.example is null
│ This value is null, so it does not have any attributes.
```
## Restrictions
The `enabled` meta-argument cannot be used together with [`count`](../../language/meta-arguments/count.mdx) or [`for_each`](../../language/meta-arguments/for_each.mdx), as these
meta-arguments serve different purposes. Use `enabled` for conditionally creating
single-instance resources, [`count`](../../language/meta-arguments/count.mdx) for creating multiple numbered instances, or
[`for_each`](../../language/meta-arguments/for_each.mdx) for creating multiple named instances.
The `enabled` meta-argument cannot use:
- Unknown values (values not known until apply)
- Sensitive values
- Null values
- Ephemeral values
- Non-boolean values

View File

@@ -20,7 +20,7 @@ a set of strings, OpenTofu creates one instance for each member of
that map or set. that map or set.
:::note :::note
A given resource or module block cannot use both `count` and `for_each`. A given resource or module block cannot use `for_each` together with `count` or `enabled`.
::: :::
## Basic Syntax ## Basic Syntax

View File

@@ -26,8 +26,15 @@ resource "azurerm_resource_group" "example" {
The `lifecycle` block and its contents are meta-arguments, available The `lifecycle` block and its contents are meta-arguments, available
for all `resource` blocks regardless of type. for all `resource` blocks regardless of type.
The arguments available within a `lifecycle` block are `create_before_destroy`, The arguments available within a `lifecycle` block are `enabled`,
`prevent_destroy`, `ignore_changes`, and `replace_triggered_by`. `create_before_destroy`, `prevent_destroy`, `ignore_changes`, and `replace_triggered_by`.
* `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 full details about the `enabled` meta-argument, see [its documentation](../../language/meta-arguments/enabled.mdx).
* `create_before_destroy` (bool) - By default, when OpenTofu must change * `create_before_destroy` (bool) - By default, when OpenTofu must change
a resource argument that cannot be updated in-place due to a resource argument that cannot be updated in-place due to

View File

@@ -130,7 +130,32 @@ described in more detail in the following pages:
[the `depends_on` page](../../language/meta-arguments/depends_on.mdx) [the `depends_on` page](../../language/meta-arguments/depends_on.mdx)
for details. for details.
OpenTofu does not use the `lifecycle` argument. However, the `lifecycle` block is reserved for future versions. - `lifecycle` - Allows lifecycle customizations for modules. Currently only
supports the `enabled` argument.
## Module Lifecycle
The `lifecycle` block can be used within a `module` block to customize module behavior.
Currently, it only supports the `enabled` argument for conditionally enabling or disabling
entire modules:
```hcl
variable "enable_monitoring" {
type = bool
default = true
}
module "monitoring" {
source = "./monitoring"
lifecycle {
enabled = var.enable_monitoring
}
}
```
For complete details about the `enabled` argument, including restrictions and migration
from the `count` workaround, see the [`lifecycle` meta-argument documentation](../../language/meta-arguments/lifecycle.mdx).
## Accessing Module Output Values ## Accessing Module Output Values
@@ -210,4 +235,4 @@ removed {
``` ```
:::note :::note
In contrast with `resource` blocks removal, `removed` blocks pointing to modules, do not allow usage of `provisioners`. In contrast with `resource` blocks removal, `removed` blocks pointing to modules, do not allow usage of `provisioners`.
::: :::

View File

@@ -181,6 +181,7 @@ The `provisioner` block will be executed only when the `removed` block is config
In any other cases, the execution will be skipped. In any other cases, the execution will be skipped.
For more information about provisioners, you can refer to this [page](./provisioners/syntax.mdx). For more information about provisioners, you can refer to this [page](./provisioners/syntax.mdx).
## Meta-Arguments ## Meta-Arguments
The OpenTofu language defines several meta-arguments, which can be used with The OpenTofu language defines several meta-arguments, which can be used with
@@ -189,6 +190,7 @@ any resource type to change the behavior of resources.
The following meta-arguments are documented on separate pages: The following meta-arguments are documented on separate pages:
- [`depends_on`, for specifying hidden dependencies](../../language/meta-arguments/depends_on.mdx) - [`depends_on`, for specifying hidden dependencies](../../language/meta-arguments/depends_on.mdx)
- [`enabled`, for creating conditionally single-resource instances according to a expression](../../language/meta-arguments/enabled.mdx)
- [`count`, for creating multiple resource instances according to a count](../../language/meta-arguments/count.mdx) - [`count`, for creating multiple resource instances according to a count](../../language/meta-arguments/count.mdx)
- [`for_each`, to create multiple instances according to a map, or set of strings](../../language/meta-arguments/for_each.mdx) - [`for_each`, to create multiple instances according to a map, or set of strings](../../language/meta-arguments/for_each.mdx)
- [`provider`, for selecting a non-default provider configuration](../../language/meta-arguments/resource-provider.mdx) - [`provider`, for selecting a non-default provider configuration](../../language/meta-arguments/resource-provider.mdx)