Skip to content

Commit 3497335

Browse files
authored
Add resource identity to Move RPC (#1123)
* Add initial updates for identity to MoveResourceState RPC * Add toproto updates for identity to MoveResourceState RPC * Added more tests for identity to move rpc and added identitySchema to MoveState Request * Trying out a solution for proto5server/server_moveresourcestate_test, still failing tests * Fixed failing tests * Update resource/move_state.go * Added a response-invalid-identity test to test invalid identity responses * Updating the response-invalid-identity test output
1 parent 0b93e31 commit 3497335

16 files changed

+749
-33
lines changed

internal/fromproto5/moveresourcestate.go

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ package fromproto5
55

66
import (
77
"context"
8-
98
"github.com/hashicorp/terraform-plugin-framework/diag"
109
"github.com/hashicorp/terraform-plugin-framework/internal/fwschema"
1110
"github.com/hashicorp/terraform-plugin-framework/internal/fwserver"
@@ -17,7 +16,7 @@ import (
1716

1817
// MoveResourceStateRequest returns the *fwserver.MoveResourceStateRequest
1918
// equivalent of a *tfprotov5.MoveResourceStateRequest.
20-
func MoveResourceStateRequest(ctx context.Context, proto5 *tfprotov5.MoveResourceStateRequest, resource resource.Resource, resourceSchema fwschema.Schema) (*fwserver.MoveResourceStateRequest, diag.Diagnostics) {
19+
func MoveResourceStateRequest(ctx context.Context, proto5 *tfprotov5.MoveResourceStateRequest, resource resource.Resource, resourceSchema fwschema.Schema, identitySchema fwschema.Schema) (*fwserver.MoveResourceStateRequest, diag.Diagnostics) {
2120
if proto5 == nil {
2221
return nil, nil
2322
}
@@ -38,13 +37,16 @@ func MoveResourceStateRequest(ctx context.Context, proto5 *tfprotov5.MoveResourc
3837
}
3938

4039
fw := &fwserver.MoveResourceStateRequest{
41-
SourceProviderAddress: proto5.SourceProviderAddress,
42-
SourceRawState: (*tfprotov6.RawState)(proto5.SourceState),
43-
SourceSchemaVersion: proto5.SourceSchemaVersion,
44-
SourceTypeName: proto5.SourceTypeName,
45-
TargetResource: resource,
46-
TargetResourceSchema: resourceSchema,
47-
TargetTypeName: proto5.TargetTypeName,
40+
SourceProviderAddress: proto5.SourceProviderAddress,
41+
SourceRawState: (*tfprotov6.RawState)(proto5.SourceState),
42+
SourceSchemaVersion: proto5.SourceSchemaVersion,
43+
SourceTypeName: proto5.SourceTypeName,
44+
TargetResource: resource,
45+
TargetResourceSchema: resourceSchema,
46+
TargetTypeName: proto5.TargetTypeName,
47+
SourceIdentity: (*tfprotov6.RawState)(proto5.SourceIdentity),
48+
SourceIdentitySchemaVersion: proto5.SourceIdentitySchemaVersion,
49+
IdentitySchema: identitySchema,
4850
}
4951

5052
sourcePrivate, sourcePrivateDiags := privatestate.NewData(ctx, proto5.SourcePrivate)

internal/fromproto5/moveresourcestate_test.go

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ func TestMoveResourceStateRequest(t *testing.T) {
3232
testCases := map[string]struct {
3333
input *tfprotov5.MoveResourceStateRequest
3434
resourceSchema fwschema.Schema
35+
identitySchema fwschema.Schema
3536
resource resource.Resource
3637
expected *fwserver.MoveResourceStateRequest
3738
expectedDiagnostics diag.Diagnostics
@@ -162,13 +163,37 @@ func TestMoveResourceStateRequest(t *testing.T) {
162163
TargetTypeName: "examplecloud_thing",
163164
},
164165
},
166+
"SourceIdentity": {
167+
input: &tfprotov5.MoveResourceStateRequest{
168+
SourceIdentity: testNewTfprotov5RawState(t, map[string]interface{}{
169+
"test_identity_attribute": "test-value",
170+
}),
171+
},
172+
resourceSchema: testFwSchema,
173+
expected: &fwserver.MoveResourceStateRequest{
174+
SourceIdentity: testNewTfprotov6RawState(t, map[string]interface{}{
175+
"test_identity_attribute": "test-value",
176+
}),
177+
TargetResourceSchema: testFwSchema,
178+
},
179+
},
180+
"SourceIdentitySchemaVersion": {
181+
input: &tfprotov5.MoveResourceStateRequest{
182+
SourceIdentitySchemaVersion: 123,
183+
},
184+
resourceSchema: testFwSchema,
185+
expected: &fwserver.MoveResourceStateRequest{
186+
SourceIdentitySchemaVersion: 123,
187+
TargetResourceSchema: testFwSchema,
188+
},
189+
},
165190
}
166191

167192
for name, testCase := range testCases {
168193
t.Run(name, func(t *testing.T) {
169194
t.Parallel()
170195

171-
got, diags := fromproto5.MoveResourceStateRequest(context.Background(), testCase.input, testCase.resource, testCase.resourceSchema)
196+
got, diags := fromproto5.MoveResourceStateRequest(context.Background(), testCase.input, testCase.resource, testCase.resourceSchema, testCase.identitySchema)
172197

173198
if diff := cmp.Diff(got, testCase.expected); diff != "" {
174199
t.Errorf("unexpected difference: %s", diff)

internal/fromproto6/moveresourcestate.go

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ package fromproto6
55

66
import (
77
"context"
8-
98
"github.com/hashicorp/terraform-plugin-framework/diag"
109
"github.com/hashicorp/terraform-plugin-framework/internal/fwschema"
1110
"github.com/hashicorp/terraform-plugin-framework/internal/fwserver"
@@ -16,7 +15,7 @@ import (
1615

1716
// MoveResourceStateRequest returns the *fwserver.MoveResourceStateRequest
1817
// equivalent of a *tfprotov6.MoveResourceStateRequest.
19-
func MoveResourceStateRequest(ctx context.Context, proto6 *tfprotov6.MoveResourceStateRequest, resource resource.Resource, resourceSchema fwschema.Schema) (*fwserver.MoveResourceStateRequest, diag.Diagnostics) {
18+
func MoveResourceStateRequest(ctx context.Context, proto6 *tfprotov6.MoveResourceStateRequest, resource resource.Resource, resourceSchema fwschema.Schema, identitySchema fwschema.Schema) (*fwserver.MoveResourceStateRequest, diag.Diagnostics) {
2019
if proto6 == nil {
2120
return nil, nil
2221
}
@@ -37,13 +36,16 @@ func MoveResourceStateRequest(ctx context.Context, proto6 *tfprotov6.MoveResourc
3736
}
3837

3938
fw := &fwserver.MoveResourceStateRequest{
40-
SourceProviderAddress: proto6.SourceProviderAddress,
41-
SourceRawState: proto6.SourceState,
42-
SourceSchemaVersion: proto6.SourceSchemaVersion,
43-
SourceTypeName: proto6.SourceTypeName,
44-
TargetResource: resource,
45-
TargetResourceSchema: resourceSchema,
46-
TargetTypeName: proto6.TargetTypeName,
39+
SourceProviderAddress: proto6.SourceProviderAddress,
40+
SourceRawState: proto6.SourceState,
41+
SourceSchemaVersion: proto6.SourceSchemaVersion,
42+
SourceTypeName: proto6.SourceTypeName,
43+
TargetResource: resource,
44+
TargetResourceSchema: resourceSchema,
45+
TargetTypeName: proto6.TargetTypeName,
46+
SourceIdentity: proto6.SourceIdentity,
47+
SourceIdentitySchemaVersion: proto6.SourceIdentitySchemaVersion,
48+
IdentitySchema: identitySchema,
4749
}
4850

4951
sourcePrivate, sourcePrivateDiags := privatestate.NewData(ctx, proto6.SourcePrivate)

internal/fromproto6/moveresourcestate_test.go

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ func TestMoveResourceStateRequest(t *testing.T) {
3232
testCases := map[string]struct {
3333
input *tfprotov6.MoveResourceStateRequest
3434
resourceSchema fwschema.Schema
35+
identitySchema fwschema.Schema
3536
resource resource.Resource
3637
expected *fwserver.MoveResourceStateRequest
3738
expectedDiagnostics diag.Diagnostics
@@ -162,13 +163,37 @@ func TestMoveResourceStateRequest(t *testing.T) {
162163
TargetTypeName: "examplecloud_thing",
163164
},
164165
},
166+
"SourceIdentity": {
167+
input: &tfprotov6.MoveResourceStateRequest{
168+
SourceIdentity: testNewRawState(t, map[string]interface{}{
169+
"test_identity_attribute": "test-value",
170+
}),
171+
},
172+
resourceSchema: testFwSchema,
173+
expected: &fwserver.MoveResourceStateRequest{
174+
SourceIdentity: testNewRawState(t, map[string]interface{}{
175+
"test_identity_attribute": "test-value",
176+
}),
177+
TargetResourceSchema: testFwSchema,
178+
},
179+
},
180+
"SourceIdentitySchemaVersion": {
181+
input: &tfprotov6.MoveResourceStateRequest{
182+
SourceIdentitySchemaVersion: 123,
183+
},
184+
resourceSchema: testFwSchema,
185+
expected: &fwserver.MoveResourceStateRequest{
186+
SourceIdentitySchemaVersion: 123,
187+
TargetResourceSchema: testFwSchema,
188+
},
189+
},
165190
}
166191

167192
for name, testCase := range testCases {
168193
t.Run(name, func(t *testing.T) {
169194
t.Parallel()
170195

171-
got, diags := fromproto6.MoveResourceStateRequest(context.Background(), testCase.input, testCase.resource, testCase.resourceSchema)
196+
got, diags := fromproto6.MoveResourceStateRequest(context.Background(), testCase.input, testCase.resource, testCase.resourceSchema, testCase.identitySchema)
172197

173198
if diff := cmp.Diff(got, testCase.expected); diff != "" {
174199
t.Errorf("unexpected difference: %s", diff)

internal/fwserver/server_moveresourcestate.go

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -65,14 +65,25 @@ type MoveResourceStateRequest struct {
6565
// TargetTypeName is the type name of the target resource as given by
6666
// Terraform across the protocol.
6767
TargetTypeName string
68+
69+
// SourceIdentity is the identity of the source resource.
70+
//
71+
// Only the underlying JSON field is populated.
72+
SourceIdentity *tfprotov6.RawState
73+
74+
// SourceIdentitySchemaVersion is the version of the source resource state.
75+
SourceIdentitySchemaVersion int64
76+
77+
IdentitySchema fwschema.Schema
6878
}
6979

7080
// MoveResourceStateResponse is the framework server response for the
7181
// MoveResourceState RPC.
7282
type MoveResourceStateResponse struct {
73-
Diagnostics diag.Diagnostics
74-
TargetPrivate *privatestate.Data
75-
TargetState *tfsdk.State
83+
Diagnostics diag.Diagnostics
84+
TargetPrivate *privatestate.Data
85+
TargetState *tfsdk.State
86+
TargetIdentity *tfsdk.ResourceIdentity
7687
}
7788

7889
// MoveResourceState implements the framework server MoveResourceState RPC.
@@ -125,12 +136,15 @@ func (s *Server) MoveResourceState(ctx context.Context, req *MoveResourceStateRe
125136

126137
for _, resourceStateMover := range resourceStateMovers {
127138
moveStateReq := resource.MoveStateRequest{
128-
SourcePrivate: sourcePrivate,
129-
SourceProviderAddress: req.SourceProviderAddress,
130-
SourceRawState: req.SourceRawState,
131-
SourceSchemaVersion: req.SourceSchemaVersion,
132-
SourceTypeName: req.SourceTypeName,
139+
SourcePrivate: sourcePrivate,
140+
SourceProviderAddress: req.SourceProviderAddress,
141+
SourceRawState: req.SourceRawState,
142+
SourceSchemaVersion: req.SourceSchemaVersion,
143+
SourceTypeName: req.SourceTypeName,
144+
SourceIdentity: req.SourceIdentity,
145+
SourceIdentitySchemaVersion: req.SourceIdentitySchemaVersion,
133146
}
147+
134148
moveStateResp := resource.MoveStateResponse{
135149
TargetPrivate: privatestate.EmptyProviderData(ctx),
136150
TargetState: tfsdk.State{
@@ -139,6 +153,13 @@ func (s *Server) MoveResourceState(ctx context.Context, req *MoveResourceStateRe
139153
},
140154
}
141155

156+
if req.IdentitySchema != nil {
157+
moveStateResp.TargetIdentity = &tfsdk.ResourceIdentity{
158+
Raw: tftypes.NewValue(req.IdentitySchema.Type().TerraformType(ctx), nil),
159+
Schema: req.IdentitySchema,
160+
}
161+
}
162+
142163
if resourceStateMover.SourceSchema != nil {
143164
logging.FrameworkTrace(ctx, "Attempting to populate MoveResourceStateRequest SourceState from provider defined SourceSchema")
144165

@@ -221,6 +242,19 @@ func (s *Server) MoveResourceState(ctx context.Context, req *MoveResourceStateRe
221242
if !moveStateResp.TargetState.Raw.Equal(tftypes.NewValue(req.TargetResourceSchema.Type().TerraformType(ctx), nil)) {
222243
resp.Diagnostics = moveStateResp.Diagnostics
223244
resp.TargetState = &moveStateResp.TargetState
245+
if moveStateResp.TargetIdentity != nil {
246+
resp.TargetIdentity = moveStateResp.TargetIdentity
247+
}
248+
249+
if resp.TargetIdentity != nil && req.IdentitySchema == nil {
250+
resp.Diagnostics.AddError(
251+
"Unexpected Move State Response",
252+
"An unexpected error was encountered when creating the move state response. New identity data was returned by the provider move state operation, but the resource does not indicate identity support.\n\n"+
253+
"This is always a problem with the provider and should be reported to the provider developer.",
254+
)
255+
256+
return
257+
}
224258

225259
if moveStateResp.TargetPrivate != nil {
226260
resp.TargetPrivate.Provider = moveStateResp.TargetPrivate

0 commit comments

Comments
 (0)