Skip to content

Persistent state and automatic reimport for resources that aren't fully deleted on destroy #33216

@geekofalltrades

Description

@geekofalltrades

Terraform Version

Terraform v1.5.0-beta1
on linux_amd64
+ provider registry.terraform.io/hashicorp/aws v4.67.0

Use Cases

Some resources, like aws_secretsmanager_secret or aws_kms_key, go into a pending deletion state outside of Terraform when destroyed, rather than being immediately deleted.

If a configuration containing a resource like this is intended to be applied and destroyed regularly -- for example, a dev or CI environment -- then it is currently already painful to handle. Because the resource can't be fully deleted by design, it must be manually undeleted and reimported into Terraform before the configuration can be applied again. The new import blocks coming in Terraform 1.5.0 seemed like they had the potential to improve this: if those resources could be enhanced to undelete themselves when imported, then the import block would get rid of any manual steps needed in between applies.

resource "aws_secretsmanager_secret" "test" {
  name = "test"
}

import {
  # Doesn't actually need to be a full ARN to be imported successfully, in spite of documentation.
  # This resource type gets some random characters added to the end of its ARN by AWS.
  id = "arn:aws:secretsmanager:us-west-2:xxx:secret:test"
  to = aws_secretsmanager_secret.test
}

But now the pain point comes on the first apply. In a configuration like this, the import block would be intended to be permanent. But this means that on the first apply, it needs to be commented out, otherwise it fails with Error: Cannot import non-existent remote object.

Attempted Solutions

The way we currently manage resources of this type is with a wrapper script that undeletes and reimports the resource outside of Terraform before running apply.

Proposal

A new concept of "persistence" is added to resources. A persistent resource continues to have its ID stored in the state after it is destroyed. Persistent bool is added as a new attribute to schema.Resource to effect this change. When a provider adds support for a resource that can't be immediately deleted by Terraform, they should set this to true on that resource.

Every time state is refreshed, if the resource has been previously destroyed, the resource is read via the stored ID, and is only removed from the state when it is found to have been fully deleted outside of Terraform.

When a destroyed persistent resource is applied, Terraform automatically proposes an import of the previously deleted resource, rather than creation of a new resource. It would be up to providers to ensure that import of the resource includes undeleting/restoring it.

terraform state list for a resource like this that has been destroyed might show:

aws_secretsmanager_secret.test [destroyed]

The resource could be terraform state rm'd to make Terraform fully forget about it and attempt to create a new resource instead of reimporting the previous one. A new lifecycle option, persistence, of type bool, can be used on persistent resources to optionally disable the behavior:

lifecycle {
  persistence = false
}

Trying to use this attribute on a resource that is not persistent would generate an error.

Open Questions

What should terraform taint do with a persistent resource? taint is intended to destroy and recreate, but this is likely to cause a conflict with the resource that was just destroyed, but isn't actually gone. Maybe it should be an error.

What happens if the configuration for a persistent resource is removed from the configuration? It should likely be retained in the state as if it were destroyed, since it still has the same property of not actually having been deleted. A user might be switching between git branches that do and don't have the resource.

References

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions