Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

When originating resource of propagated create_before_destroy flag is removed at the same time that a resource inheriting the flag is recreated, a cycle occurs. #36154

Open
JohannesMoersch opened this issue Dec 3, 2024 · 3 comments

Comments

@JohannesMoersch
Copy link

Terraform Version

Terraform v1.10.0
on windows_amd64
+ provider registry.terraform.io/hashicorp/null v3.2.3

Terraform Configuration Files

Configuration 1

resource "null_resource" "base" {
  triggers = {
    version = 0
  }
}

resource "null_resource" "depends_on_base" {
  triggers = {
    base = null_resource.base.id
  }

  lifecycle {
    create_before_destroy = true
  }
}

Configuration 2

resource "null_resource" "base" {
  triggers = {
    version = 1
  }
}

Debug Output

Debug Output

Expected Behavior

Apply to treat the base resource as create_before_destroy since the state file indicates it should, leading to it first creating a new base resource, then destroying the dependent resource, and then destroying the origin base resource. If I explicitly set create_before_destroy on the base resource, everything works as expected.

Actual Behavior

Error: Cycle: null_resource.base (destroy), null_resource.base, null_resource.depends_on_base (destroy)

Steps to Reproduce

  1. Apply configuration 1
  2. Apply configuration 2

Additional Context

No response

References

This is related to issue #35959, which I opened about the create_before_destroy flag being removed during some update operations. This has been fixed in Terraform 1.10, but it doesn't seem to be using the value when planning.

@JohannesMoersch JohannesMoersch added bug new new issue not yet triaged labels Dec 3, 2024
@jbardin
Copy link
Member

jbardin commented Dec 3, 2024

Hi @JohannesMoersch,

Thanks for filing the issue. This is an example of one of the few ways you can create a configuration which contradicts the state such that the change results in a cycle. The usual way to avoid these things is to update the order of operations in a separate step before removing resources affected by those operations.

The situation is that you have the state which says depends_on_base must be destroyed after the new base is created but before the old base is destroyed. The configuration however is saying that the old base must be destroyed before crating a new base.

The only real resolution would be to force base to remain create_before_destroy for this plan+apply cycle, and that makes perfect sense in this simple example, but complex configurations are a lot harder to reason about as that would continue to affect all upstream resources (we also have the precedent that the existing behavior is already what is supported). Terraform also can't know why the previous resources were create_before_destroy, and parts of the destroy process may actually fail if that order is not maintained, i.e. it's possible that Configuration 2 is incorrect and the failure is warranted.

These types of situations are hard to debug though, and I'd like a better solution overall. We can link this to #26150 too, which is just another aspect of "what to do when faced with a cycle".

@jbardin jbardin added enhancement core and removed bug new new issue not yet triaged labels Dec 3, 2024
@JohannesMoersch
Copy link
Author

JohannesMoersch commented Dec 3, 2024

Hmm, true. For a scenario like this one though, I'm not sure the cycle makes sense since the resource that has create_before_destroy set isn't being recreated. It's only being destroyed. Would it make sense in this case to treat the objects being destroyed as no longer being create_before_destroy if their dependencies are no longer create_before_destroy (meaning nothing in the configuration is still enforcing create_before_destroy). This would result in:

  • Destroy depends_on_base
  • Destroy base
  • Create base

I'm sure I'm overlooking something, but are you aware of a scenario where that would be undesirable? Manually removing create_before_destroy from depends_on_base in the state file results in this outcome.

@jbardin
Copy link
Member

jbardin commented Dec 4, 2024

Would it make sense in this case to treat the objects being destroyed as no longer being create_before_destroy if their dependencies are no longer create_before_destroy

Yes that's one possibility, though we don't have any mechanism to do that currently, because the graph changes caused by create_before_destroy flow in the opposite direction from what we would need to check.

What we need to consider though is that the destroy order is defined by the state when there's no longer configuration for a resource, so we would be choosing to break the ordering which the user had defined and must determine if there is sufficient reason to do so. With the sheer volume of configuration that exists, any particular behavior of Terraform is eventually used by someone somewhere. We need to verify that no supported configurations would be broken, and preferably that there is no situation which encounters this that does not already require manual intervention.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants