-
Notifications
You must be signed in to change notification settings - Fork 96
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
tfsdk: Support protocol version 5 and verify valid resource type in U…
…pgradeResourceState RPC (#263) Reference: #42 Reference: #262 Reference: hashicorp/terraform-provider-corner#44 Terraform CLI version 0.12 through 0.14 support protocol version 5 and require the `UpgradeResourceStateResponse` type `UpgradedState` type `Msgpack` field. To support downgraded framework providers via terraform-plugin-mux `tf6to5server`, the `RawState` type `JSON` field cannot simply be passed through like the previous implementation. This change will parse the `RawState` and output it via the `tfprotov6.NewDynamicValue()` function, which will always set the `Msgpack` field. Similar logic would have already been required as part of the larger effort to support resource versioning and upgrading resource state over time. Passthrough of the same state of an invalid resource type should not have been previously allowed, since the provider did not implement the resource type. Regardless, Terraform CLI should not have reached this point since `GetProviderSchema` would not have returned the resource type anyways for other resource operations. Verified via integration testing of terraform-plugin-mux `tf6to5server`, which previously returned a non-descript `EOF` error.
- Loading branch information
Showing
5 changed files
with
404 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
```release-note:bug | ||
tfsdk: Support protocol version 5 and verify valid resource type in `UpgradeResourceState` RPC | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
package tfsdk | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"github.com/hashicorp/terraform-plugin-framework/diag" | ||
"github.com/hashicorp/terraform-plugin-framework/types" | ||
"github.com/hashicorp/terraform-plugin-go/tfprotov6" | ||
"github.com/hashicorp/terraform-plugin-go/tftypes" | ||
) | ||
|
||
// This resource is a placeholder for UpgradeResourceState testing, | ||
// so it is decoupled from other test resources. | ||
// TODO: Implement UpgradeResourceState support, when added | ||
// Reference: https://github.com/hashicorp/terraform-plugin-framework/issues/42 | ||
type testServeResourceTypeUpgradeState struct{} | ||
|
||
func (t testServeResourceTypeUpgradeState) GetSchema(_ context.Context) (Schema, diag.Diagnostics) { | ||
return Schema{ | ||
Attributes: map[string]Attribute{ | ||
"id": { | ||
Type: types.StringType, | ||
Computed: true, | ||
}, | ||
"optional_string": { | ||
Type: types.StringType, | ||
Optional: true, | ||
}, | ||
"required_string": { | ||
Type: types.StringType, | ||
Required: true, | ||
}, | ||
}, | ||
}, nil | ||
} | ||
|
||
func (t testServeResourceTypeUpgradeState) NewResource(_ context.Context, p Provider) (Resource, diag.Diagnostics) { | ||
provider, ok := p.(*testServeProvider) | ||
if !ok { | ||
prov, ok := p.(*testServeProviderWithMetaSchema) | ||
if !ok { | ||
panic(fmt.Sprintf("unexpected provider type %T", p)) | ||
} | ||
provider = prov.testServeProvider | ||
} | ||
return testServeResourceUpgradeState{ | ||
provider: provider, | ||
}, nil | ||
} | ||
|
||
var testServeResourceTypeUpgradeStateSchema = &tfprotov6.Schema{ | ||
Block: &tfprotov6.SchemaBlock{ | ||
Attributes: []*tfprotov6.SchemaAttribute{ | ||
{ | ||
Name: "id", | ||
Computed: true, | ||
Type: tftypes.String, | ||
}, | ||
{ | ||
Name: "optional_string", | ||
Optional: true, | ||
Type: tftypes.String, | ||
}, | ||
{ | ||
Name: "required_string", | ||
Required: true, | ||
Type: tftypes.String, | ||
}, | ||
}, | ||
}, | ||
} | ||
|
||
// var testServeResourceTypeUpgradeStateTftype = tftypes.Object{ | ||
// AttributeTypes: map[string]tftypes.Type{ | ||
// "id": tftypes.String, | ||
// "optional_string": tftypes.String, | ||
// "required_string": tftypes.String, | ||
// }, | ||
// } | ||
|
||
// type testServeResourceUpgradeStateData struct { | ||
// Id string `tfsdk:"id"` | ||
// OptionalString *string `tfsdk:"optional_string"` | ||
// RequiredString string `tfsdk:"required_string"` | ||
// } | ||
|
||
type testServeResourceUpgradeState struct { | ||
provider *testServeProvider | ||
} | ||
|
||
func (r testServeResourceUpgradeState) Create(ctx context.Context, req CreateResourceRequest, resp *CreateResourceResponse) { | ||
// Intentionally blank. Not expected to be called during testing. | ||
} | ||
func (r testServeResourceUpgradeState) Read(ctx context.Context, req ReadResourceRequest, resp *ReadResourceResponse) { | ||
// Intentionally blank. Not expected to be called during testing. | ||
} | ||
func (r testServeResourceUpgradeState) Update(ctx context.Context, req UpdateResourceRequest, resp *UpdateResourceResponse) { | ||
// Intentionally blank. Not expected to be called during testing. | ||
} | ||
func (r testServeResourceUpgradeState) Delete(ctx context.Context, req DeleteResourceRequest, resp *DeleteResourceResponse) { | ||
// Intentionally blank. Not expected to be called during testing. | ||
} | ||
func (r testServeResourceUpgradeState) ImportState(ctx context.Context, req ImportResourceStateRequest, resp *ImportResourceStateResponse) { | ||
ResourceImportStateNotImplemented(ctx, "intentionally not implemented", resp) | ||
} |
Oops, something went wrong.