Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switch upgradeResourceState to use SDKv2's gRPC method #1735

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 24 additions & 4 deletions pkg/tfshim/sdk-v2/upgrade_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"strconv"

"github.com/hashicorp/go-cty/cty"
ctyjson "github.com/hashicorp/go-cty/cty/json"
"github.com/hashicorp/go-cty/cty/msgpack"
"github.com/hashicorp/terraform-plugin-go/tfprotov5"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
Expand All @@ -20,7 +21,10 @@ func upgradeResourceState(ctx context.Context, typeName string, p *schema.Provid
}

// Ensure that we have an ID in the attributes.
instanceState.Attributes["id"] = instanceState.ID
if state := instanceState.RawState.AsValueMap(); !has(state, "id") {
state["id"] = cty.StringVal(instanceState.ID)
instanceState.RawState = cty.ObjectVal(state)
}

version, hasVersion := int64(0), false
if versionValue, ok := instanceState.Meta["schema_version"]; ok {
Expand All @@ -35,13 +39,18 @@ func upgradeResourceState(ctx context.Context, typeName string, p *schema.Provid
version, hasVersion = v, true
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see a check for downgrades here - pretty sure TF doesn't allow downgrades, see #1998 (comment)


// Now, we perform the UpgradeResourceState operation by re-implementing TF's UpgradeResourceState.
json, err := ctyjson.Marshal(instanceState.RawState, res.CoreConfigSchema().ImpliedType())
Copy link
Member

@t0yv0 t0yv0 May 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Eyes on this line please, I think res.CoreConfigSchema().ImpliedType() comes from the current provider schema but instanceState.RawState may be on prev provider schema in the case of actual upgrade. We could try inferring the type from the value. I think it's about tradeoffs both approaches slightly problematic. If this is exactly how it worked before perhaps can leave that.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should be able to change that to

	json, err := ctyjson.Marshal(instanceState.RawState, res.RawState.Type())

I'll add a test where we do a more substantial upgrade to verify that this works as expected.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It didn't work without the change. Good catch! I have added the fix and a test to go with it.

if err != nil {
return nil, fmt.Errorf("failed to marshal RawState: %w", err)
}

// Now, we perform the UpgradeResourceState operation by calling into TF's UpgradeResourceState.

resp, err := schema.NewGRPCProviderServer(p).
UpgradeResourceState(ctx, &tfprotov5.UpgradeResourceStateRequest{
TypeName: typeName,
Version: version,
RawState: &tfprotov5.RawState{Flatmap: instanceState.Attributes},
RawState: &tfprotov5.RawState{JSON: json},
})
if err != nil {
return nil, fmt.Errorf("upgrade resource state GRPC: %w", err)
Expand All @@ -62,7 +71,13 @@ func upgradeResourceState(ctx context.Context, typeName string, p *schema.Provid
}

// Unmarshal to get back the underlying type.
rawState, err := msgpack.Unmarshal(resp.UpgradedState.MsgPack, res.CoreConfigSchema().ImpliedType())
var rawState cty.Value
if resp.UpgradedState.JSON != nil {
rawState, err = ctyjson.Unmarshal(resp.UpgradedState.JSON, res.CoreConfigSchema().ImpliedType())
}
if resp.UpgradedState.MsgPack != nil {
rawState, err = msgpack.Unmarshal(resp.UpgradedState.MsgPack, res.CoreConfigSchema().ImpliedType())
}
if err != nil {
return nil, fmt.Errorf("failed to unmarshal: %w", err)
}
Expand Down Expand Up @@ -105,3 +120,8 @@ func findID(v cty.Value) (string, bool) {
}
return id.AsString(), true
}

func has[K comparable, V any](m map[K]V, k K) bool {
_, ok := m[k]
return ok
}
1 change: 1 addition & 0 deletions pkg/tfshim/sdk-v2/upgrade_state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ func TestUpgradeResourceState(t *testing.T) {
actual, err := upgradeResourceState(context.Background(), tfToken, &schema.Provider{
ResourcesMap: map[string]*schema.Resource{
tfToken: {
UseJSONNumber: true,
Schema: map[string]*schema.Schema{
"x": {Type: schema.TypeInt, Optional: true},
},
Expand Down