hashicorp / terraform-plugin-go

A low-level Go binding for the Terraform protocol for integrations to be built on top of.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

`PlanResourceChange` can't indicate whether it is for a "recreate"

magodo opened this issue · comments

terraform-plugin-go version

v0.19.0

Use cases

See:

Long to short, we have a resource, whose name is globally unique, which means creating this resource with an existing name would fail. So we want to add validation in plan time, by using the "CustomizeDiff" (SDKv2) or "ModifyPlan" (FW). It works fine for most cases, whilst if the resource is tainted, the plan will fail (at least for CustomizeDiff), in that the state is nil and the plan will have the name set to the existing name, with that resource still existed (not deleted yet).

Attempted solutions

Proposal

I don't have a comprehensive proposal here, whilst I'd like to ask for a way to meet the requirement above, any suggestion would also be appreciated!

References

Hi @magodo 👋 Thank you for raising this feature request. This is certainly an area of Terraform we have wanted to improve over the last few years.

One idea here is as you mention -- introducing new information into the Terraform Plugin Protocol during the PlanResourceChange RPC which signifies the actual action(s) occurring, beyond the existing prior state, proposed new state, and configuration data. There is a certain amount of tradeoff that occurs with this type of solution:

  • Seemingly positive: it feels like it would be a relatively small addition to existing Terraform and provider logic
  • Both positive and negative: it is a targeted solution for a very specific use case
  • Seemingly negative: it is up to providers to discover this functionality and correctly implement the solution (although admittedly an issue with many potential proposals in this space)
  • Seemingly negative: design/abstraction-wise it is introducing additional Terraform operational context into the protocol where the protocol has never been exposed to those implementation details and it may cause provider developers to become reliant on those implementation details and therefore introduces new compatibility concerns into Terraform and providers

Since Terraform is very targeted in its requests to providers, I think we also would need to ensure that just providing something like the action(s) would be enough -- it would be up to the provider in this case to somehow "know" about the existence of the "same" resource elsewhere either by remote system lookup, an errant caching solution as it receives requests, or by adding even more data to the protocol that is unrelated to the specific operation being requested (such as information about other resources, etc). Each time we have approached this type of solution, it feels like it requires more and more effort to make it work correctly across more of Terraform's and the real world's functionality.

Another idea we are poking at for tangential reasons to this specific use case (sorry cannot publicly say), is whether providers could announce unique identification data for each resource type. In terms of this use case, Terraform would be able to automatically detect that a plan is attempting to create the "same" resource if two resource instances caused equal identification data, whether it be via separate resource configuration blocks, separate resource instances within the same configuration block, or via other Terraform functionality such as an errant use of create_before_destroy. If that proposal sounds reasonable, then I would suggest following hashicorp/terraform-plugin-sdk#224 (probably needs a better issue tracking home at this point, so it might be transferred to another repository).

@bflad Thank you for the clarification! Regarding the following:

it would be up to the provider in this case to somehow "know" about the existence of the "same" resource

Would you mind to elaborate more about how shall I manage to do this for my use case? From my understanding, a remote system lookup can only tell the resource exist, which doesn't tell whether this resource is currently managed by TF, so I can't tell whether this is a recreate, or requires to import case.

You are correct, a remote system lookup could not detect anything beyond existence, unless there was extremely specific details saved in the remote system and only possible to manage via Terraform, such as tags/metadata. In practice, it is never guaranteed that every resource would only be locked down to Terraform-only access like that and it would not prove that this resource is being managed by the configuration causing the recreation plan. I'm not sure we could recommend any correct solution at the moment due to the tradeoffs of the various options.

If you would like to hear a Terraform core maintainers' opinion on this sort of resource instance lifecycle feature request, I might suggest raising an issue upstream at https://github.com/hashicorp/terraform/issues, since ultimately, any protocol level changes would need to be discussed and designed there first.