hashicorp / hashicorp/terraform-plugin-sdk

Persist existing ResourceDiff from plan during apply

Open
#760 1 comment 0 reactions 0 assignees View on GitHub
enhancement
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.