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

Terraform Cloud's handling of data-only changes prevents workspace deletion #35236

Open
theipster opened this issue May 24, 2024 · 2 comments
Open
Labels
bug cloud Related to Terraform Cloud's integration with Terraform new new issue not yet triaged v1.8 Issues (primarily bugs) reported against v1.8 releases

Comments

@theipster
Copy link

Terraform Version

v1.8.4

Terraform Configuration Files

# data.tf
data "null_resource_data" "this" {}

# resources.tf
resource "null_resource" "this" {}

# versions.tf
terraform {
  cloud {}
}

Debug Output

https://gist.github.com/theipster/c5640574bc5d6a5cdf605c741c139cbc

Expected Behavior

When only data sources exist (both in the state and the source configuration), removing those data sources from the configuration and running terraform apply should remove the data sources from the state.

Furthermore, by removing those remaining data sources to result in an empty state, the Terraform Cloud workspace should then become deletable.

Actual Behavior

Removing those data sources from the configuration and running terraform apply does nothing to remove the data sources from the state.

Furthermore, because the Terraform Cloud workspace is stuck with > 0 remaining "resources" in the state, it is therefore not deletable.

Steps to Reproduce

As per debug output above:

  1. echo -en "data \"null_data_source\" \"this\" {}\n" > data.tf
  2. echo -en "resource \"null_resource\" \"this\" {}\n" > resources.tf
  3. echo -en "terraform {\n cloud {}\n}\n" > versions.tf
  4. terraform init
  5. terraform apply -auto-approve
  6. terraform show -json (State should contain data.null_data_source.this and null_resource.this.)
  7. rm resources.tf
  8. terraform apply -auto-approve
  9. terraform show -json (State should contain data.null_data_source.this only.)
  10. rm data.tf
  11. terraform apply -auto-approve
  12. terraform show -json (State should contain nothing, but in practice...)

Additional Context

I understand that this Terraform Cloud behaviour is trying to be "clever" by saving CPU cycles, but it is arguably inconsistent with how the non-Cloud version of terraform apply behaves and violates the principle of least surprise.

(To replicate the behaviour with non-Cloud / local execution mode, one can replace terraform apply -auto-approve with a combination of terraform plan -out tfplan plus terraform apply tfplan but obviously skipping the terraform apply tfplan when the tfplan file contains zero resource changes.)

I also understand there are some workarounds available, but they all require additional commands / additional complexity:

  1. Configure the Terraform Cloud workspace to force_destroy = true, so that the data sources simply get ignored when deleting the workspace. This is of course risky in case there happens to be actual resources remaining.
  2. Run terraform destroy (or terraform apply -destroy). However, for CI/CD pipelines that most commonly need to run apply and rarely need to run destroy, this would require pipeline authors to write additional logic for switching between apply vs destroy in the right circumstances. And again, more logic means more risk of accidentally doing the wrong thing, i.e. destroying a workspace full of resources.
  3. Run an extra terraform apply command that introduces a dummy resource in order to force the state to be updated (and simultaneously removes the data sources from the state), and then run yet another terraform apply command to delete that dummy resource from the state, finally resulting in the desired empty state.

References

No response

@theipster theipster added bug new new issue not yet triaged labels May 24, 2024
@jbardin jbardin added the cloud Related to Terraform Cloud's integration with Terraform label May 24, 2024
@apparentlymart
Copy link
Member

Hi @theipster! Thanks for opening this issue.

Based on what you've described, I think what you are commenting on here is the fact that HCP Terraform doesn't perform the "apply" step for a run unless the plan includes at least one planned action, and therefore it misses the opportunity to persist the plan's updated state snapshot in that case. Is that right?

I believe this also prevents applying other state changes that Terraform Core might detect during the plan phase, unless they are accompanied by a planned action, including but not necessarily limited to:

  • Any changes to managed resource instances made outside of Terraform, which Terraform would detect during the "refreshing" step during plan.
  • Any changes to metadata that gets copied from the configuration to the state during planning, like dependency relationships and relationships between resources and the provider configurations they belong to.

A further potential workaround to add to the list is terraform apply -refresh-only. I believe that HCP Terraform "knows" that the purpose of a refresh-only plan is to get the state updated in these ways and so should allow applying even without planned actions, because a refresh-only plan has no planned actions by definition.


A note for Terraform engineers who might look into this: HCP Terraform treats this situation differently for Stacks (which are in private preview at the time I'm writing this message), by always running the apply phase if the plan is valid and applyable. The logic used for stack workflow might therefore be a useful reference for one way to address this feedback in workspaces.

@theipster
Copy link
Author

Hi @apparentlymart, thanks for your quick reply!

(Also, apologies if I keep using the wrong product names, as I appreciate you've recently rebranded a lot of your products.)

Based on what you've described, I think what you are commenting on here is the fact that HCP Terraform doesn't perform the "apply" step for a run unless the plan includes at least one planned action, and therefore it misses the opportunity to persist the plan's updated state snapshot in that case. Is that right?

Yes, that's correct.

A further potential workaround to add to the list is terraform apply -refresh-only. I believe that HCP Terraform "knows" that the purpose of a refresh-only plan is to get the state updated in these ways and so should allow applying even without planned actions, because a refresh-only plan has no planned actions by definition.

I did experiment with refresh-only applies as well, both via the HCP Terraform web console (clicking all the different buttons 🙂) as well as via CLI command terraform apply -auto-approve -refresh-only. Unfortunately, in both cases, the results are still the same, i.e. the apply step gets skipped and the data sources remain in the state.

Even if that approach were to work, it would still require that additional logic to decide when to include the -refresh-only option, which ultimately means more effort and risk on the user's part.

It is good to know that there is something in the works though. The more transparent and consistent the logic becomes, the more empowering it will be for users.

@apparentlymart apparentlymart added the v1.8 Issues (primarily bugs) reported against v1.8 releases label Jun 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug cloud Related to Terraform Cloud's integration with Terraform new new issue not yet triaged v1.8 Issues (primarily bugs) reported against v1.8 releases
Projects
None yet
Development

No branches or pull requests

3 participants