Reference: #42
Reference: #228
Support provider defined `UpgradeResourceState` RPC handling, by introducing an optional `ResourceWithUpgradeState` interface type, with an `UpgradeState` method. Each underlying state version upgrade implementation is expected to consume the prior state, perform any necessary data manipulations, then respond with the upgraded state.
This framework implementation differs from the terraform-plugin-sdk implementation:
- State upgraders are specified via a mapping, rather than a slice with underlying version field. This should prevent certain classes of coding issues.
- State upgraders must be wholly contained from the prior state version to the current schema version. The framework does not loop through each successive version because attempting to recreate the `tfprotov6.RawState` for each intermediate version request would be very problematic. For example, terraform-plugin-go does not implement functionality for marshalling a `RawState`. Provider developers can use their own coding techniques to reduce code duplications when multiple versions need the same logic.
- Specifying the full prior schema is now an optional implementation detail. Working with the lower level data types is more challenging, however this has been a repeated feature request.
There are some quirks and potential future enhancements to the framework `UpgradeResourceState` handling:
- Past and current versions Terraform CLI will call `UpgradeResourceState` even if the state version matches the current schema version. This implementation keeps the framework's prior logic to roundtrip the existing state into the upgraded state. It may be possible to stop this Terraform CLI behavior with protocol version 6, although the logic would need to remain for backwards compatibility.
- It may be possible to help provider developers simplify logic by attempting to automatically populate compatible parts of the upgraded state from the prior state. This can potentially be done at a later time.