Terraform override files now preserve ignore_changes all
Terraform 1.0.11 fixes a missing lifecycle flag in override-file merging. The repair restores a specific management policy without turning it into protection against destruction.
Terraform normally rejects duplicate resource declarations across files in one directory. Override files deliberately make an exception so a second file can change selected parts of an existing declaration. That merge path must preserve lifecycle policy as well as ordinary resource arguments. Terraform 1.0.11, released on November 10, fixes a case where ignore_changes = all did not survive that merge.
The bug was not a failure to recognize the syntax. Terraform stores the special all form separately from a list of ignored attribute paths. The override merge already handled the list, but omitted the flag representing all attributes. The policy could therefore be present in the override file without appearing in the merged resource definition.
I consider that an important distinction when reading configuration. Terraform is useful because declarations express operational policy, including where another process may share responsibility for an object. A declaration that parses but loses its policy during merging is harder to understand than one rejected with a clear diagnostic.
Override files use a separate loading path
The override-file documentation shipped with this version describes the special filenames. Terraform recognizes override.tf and override.tf.json, along with names ending in _override.tf or _override.tf.json. It initially skips them while loading ordinary configuration, then processes them afterward in lexicographical order.
An override block matches an existing top-level block by its type and labels. Ordinary attribute arguments replace arguments with the same name. Nested blocks generally replace blocks of the same type, but lifecycle has a special rule. Its arguments merge individually, so setting one lifecycle argument does not discard another that exists in the original resource.
That rule is relevant to the fix. A generic replacement of the whole lifecycle block would have a different meaning. Terraform's implementation must carry each supported lifecycle setting through the resource merge. The special representation of all made it possible for the list form to work while the all-attributes form failed.
An override for an already declared resource can express the intended policy like this:
resource "aws_instance" "example" {
lifecycle {
ignore_changes = all
}
}
This is an override-file fragment, not a complete standalone instance declaration. The ordinary configuration supplies the resource's required arguments. The matching type and name identify the resource whose lifecycle policy the override changes.
The patch copies the missing flag
Katy Moe's pull request 29849 begins with a regression test. Its fixture has an ordinary resource declaration and a matching main_override.tf containing ignore_changes = all. The test loads the module and checks that the merged resource's IgnoreAllChanges field is true.
The implementation then adds a branch to the resource merge. If the overriding resource has IgnoreAllChanges set, the merged resource receives that flag. Existing handling for a nonempty IgnoreChanges list remains beside it. The correction addresses the distinct internal representation of the special keyword.
The test's scope is useful. It checks the result of loading and merging configuration, which is where the information disappeared. A test that only verified parsing the override file would not establish that the final resource retains the setting. Conversely, the patch does not need a live cloud instance to demonstrate this particular defect.
The order of the commits also makes the failure and repair understandable. The test establishes the intended merged state, and the code change supplies the missing field propagation. This production change is small because the language already has a representation for the policy. Its merge path simply failed to transfer it.
Ignoring updates still allows creation and destruction
The versioned lifecycle documentation defines the policy's limits. Listed ignored attributes still participate in creation, but Terraform ignores them when planning updates. The special all form covers every attribute, meaning Terraform can create and destroy the object but will not propose updates to it.
That is different from prevent_destroy. Ignoring updates does not promise that removing the resource declaration will preserve the object. It also does not make the object unmanaged in every respect. Terraform still has the resource in its configuration and state, with the creation and destruction behavior described by the documentation.
The policy applies to resource attributes defined by the provider. It cannot ignore itself or another Terraform meta-argument. Lifecycle settings also require literal values because Terraform processes them while constructing the graph, before arbitrary expression evaluation is available.
I prefer to read an all-attributes policy as a specific allocation of management responsibility. Terraform retains a role in the object's lifecycle while declining attribute updates. With this fix, an override file can express that allocation through the supported keyword, and the merged configuration carries it into planning instead of silently losing the flag.