hashicorp / hashicorp/terraform-plugin-sdk
Persist existing ResourceDiff from plan during apply
- Dominant language
- Go
- Stars
- 485
- Forks
- 244
- Avg merge
- 19h 57m
- Merged PRs (30d)
- 4
Description
### SDK version
```
github.com/hashicorp/terraform-plugin-sdk/v2 v2.6.1
```
### Use-cases
I'd like to make a provider that exposes a variant of the `random_shuffle` resource, except that it attempts to provide stability when the `input` field changes. I ran with https://github.com/hashicorp/terraform-provider-random/issues/121, and mostly got an approach that uses `CustomizeDiff` working. However, I'm finding that I have no way to use the value created during the plan phase - this results in Terraform complaining about an inconsistent final plan:
```
Error: Provider produced inconsistent final plan
When expanding the plan for stable_subset.res to include new values learned so
far during apply, provider "registry.terraform.io/hashicorp/stable" produced
an invalid new value for .result: planned set element cty.StringVal("b") does
not correlate with any element in actual.
This is a bug in the provider, which should be reported in the provider's own
issue tracker.
Error: Provider produced inconsistent final plan
When expanding the plan for stable_subset.res to include new values learned so
far during apply, provider "registry.terraform.io/hashicorp/stable" produced
an invalid new value for .result: planned set element cty.StringVal("d") does
not correlate with any element in actual.
This is a bug in the provider, which should be reported in the provider's own
issue tracker.
```
### Attempted Solutions
I've looked through all the interfaces I can find in the various `helper` packages, and got as far as discovering the [`PlannedPrivate` field](https://github.com/hashicorp/terraform/blob/2cd1619c40124116cc65350c2c321479ce5237b9/providers/provider.go#L247-L250) in the provider messaging implementation before discovering that I couldn't seem use that mechanism from a provider implementation either.
I suspect this is getting complicated by the `CreateContext` not getting called when the `CustomizeDiff` hook invokes `SetNew`; I wouldn't expect this to be the case, but perhaps if I was able to do both it would be possible to work around the problem?
Work-in-progress implementation is [here](https://github.com/skeggse/terraform-provider-stable/blob/main/internal/provider/resource_subset.go) for anyone interested.
### Proposal
Prepopulate (opt-in, perhaps?) the `schema.ResourceDiff` value passed to `CustomizeDiff` and the `Create/Read/Update/Delete` family of functions in a `schema.Resource` based on a previously-generated plan - atop addition to anything already in the state file.
Example:
1. `terraform plan -out tfplan` generates a `tfplan` file that includes the resource-level changes Terraform anticipates
2. `terraform apply tfplan` takes the existing `tfplan` file and passes its content to the provider
3. the provider exposes the existing diff information in resource-level `ResourceDiff` objects, so that the provider can avoid duplicate work and maintain stability for random operations.
### References
- #133
- https://github.com/hashicorp/terraform-provider-random/issues/121
Contributor guide
Research direction
Start by tracing the schema.ResourceDiff and CustomizeDiff interfaces through the Create/Read/Update/Delete lifecycle, then compare how terraform plan and terraform apply exchange resource changes. Done means an opt-in provider mechanism can reuse the planned ResourceDiff during apply without producing an inconsistent final plan; the payload does not name tests or implementation files.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go, terraform
- Domain
- devtools
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100