Skip to content

Commit c36c1b3

Browse files
committed
Trying out a solution for proto5server/server_moveresourcestate_test, still failing tests
1 parent bdb5ab0 commit c36c1b3

File tree

4 files changed

+245
-2
lines changed

4 files changed

+245
-2
lines changed

internal/fwserver/server_moveresourcestate.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,14 +144,21 @@ func (s *Server) MoveResourceState(ctx context.Context, req *MoveResourceStateRe
144144
SourceIdentity: req.SourceIdentity,
145145
SourceIdentitySchemaVersion: req.SourceIdentitySchemaVersion,
146146
}
147+
148+
var taridentity tftypes.Type
149+
150+
if req.IdentitySchema != nil {
151+
taridentity = req.IdentitySchema.Type().TerraformType(ctx)
152+
}
153+
147154
moveStateResp := resource.MoveStateResponse{
148155
TargetPrivate: privatestate.EmptyProviderData(ctx),
149156
TargetState: tfsdk.State{
150157
Schema: req.TargetResourceSchema,
151158
Raw: tftypes.NewValue(req.TargetResourceSchema.Type().TerraformType(ctx), nil),
152159
},
153160
TargetIdentity: &tfsdk.ResourceIdentity{
154-
Raw: tftypes.NewValue(req.IdentitySchema.Type().TerraformType(ctx), nil),
161+
Raw: tftypes.NewValue(taridentity, nil),
155162
Schema: req.IdentitySchema,
156163
},
157164
}

internal/proto5server/server_moveresourcestate_test.go

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package proto5server
66
import (
77
"context"
88
"fmt"
9+
"github.com/hashicorp/terraform-plugin-framework/resource/identityschema"
910
"testing"
1011

1112
"github.com/google/go-cmp/cmp"
@@ -39,6 +40,14 @@ func TestServerMoveResourceState(t *testing.T) {
3940
}
4041
schemaType := testSchema.Type().TerraformType(ctx)
4142

43+
testIdentitySchema := identityschema.Schema{
44+
Attributes: map[string]identityschema.Attribute{
45+
"test_id": identityschema.StringAttribute{
46+
RequiredForImport: true,
47+
},
48+
},
49+
}
50+
4251
testCases := map[string]struct {
4352
server *Server
4453
request *tfprotov5.MoveResourceStateRequest
@@ -413,6 +422,132 @@ func TestServerMoveResourceState(t *testing.T) {
413422
}),
414423
},
415424
},
425+
"request-SourceIdentitySchemaVersion": {
426+
server: &Server{
427+
FrameworkServer: fwserver.Server{
428+
Provider: &testprovider.Provider{
429+
ResourcesMethod: func(_ context.Context) []func() resource.Resource {
430+
return []func() resource.Resource{
431+
func() resource.Resource {
432+
return &testprovider.ResourceWithMoveState{
433+
Resource: &testprovider.Resource{
434+
SchemaMethod: func(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
435+
resp.Schema = testSchema
436+
},
437+
MetadataMethod: func(_ context.Context, _ resource.MetadataRequest, resp *resource.MetadataResponse) {
438+
resp.TypeName = "test_resource"
439+
},
440+
},
441+
MoveStateMethod: func(ctx context.Context) []resource.StateMover {
442+
return []resource.StateMover{
443+
{
444+
StateMover: func(_ context.Context, req resource.MoveStateRequest, resp *resource.MoveStateResponse) {
445+
expected := int64(123)
446+
447+
if diff := cmp.Diff(req.SourceIdentitySchemaVersion, expected); diff != "" {
448+
resp.Diagnostics.AddError("Unexpected req.SourceIdentitySchemaVersion difference", diff)
449+
}
450+
451+
// Prevent missing implementation error, the values do not matter except for response assertion
452+
resp.Diagnostics.Append(resp.TargetState.SetAttribute(ctx, path.Root("id"), "test-id-value")...)
453+
resp.Diagnostics.Append(resp.TargetState.SetAttribute(ctx, path.Root("required_attribute"), "true")...)
454+
},
455+
},
456+
}
457+
},
458+
}
459+
},
460+
}
461+
},
462+
},
463+
},
464+
},
465+
request: &tfprotov5.MoveResourceStateRequest{
466+
SourceIdentitySchemaVersion: 123,
467+
// SourceState required to prevent error
468+
SourceState: testNewTfprotov5RawState(t, map[string]interface{}{
469+
"id": "test-id-value",
470+
"required_attribute": true,
471+
}),
472+
TargetTypeName: "test_resource",
473+
},
474+
expectedResponse: &tfprotov5.MoveResourceStateResponse{
475+
TargetState: testNewDynamicValue(t, schemaType, map[string]tftypes.Value{
476+
"id": tftypes.NewValue(tftypes.String, "test-id-value"),
477+
"optional_attribute": tftypes.NewValue(tftypes.String, nil),
478+
"required_attribute": tftypes.NewValue(tftypes.String, "true"),
479+
}),
480+
},
481+
},
482+
"request-SourceIdentity": {
483+
server: &Server{
484+
FrameworkServer: fwserver.Server{
485+
Provider: &testprovider.Provider{
486+
ResourcesMethod: func(_ context.Context) []func() resource.Resource {
487+
return []func() resource.Resource{
488+
func() resource.Resource {
489+
return &testprovider.ResourceWithIdentityAndMoveState{
490+
Resource: &testprovider.Resource{
491+
SchemaMethod: func(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
492+
resp.Schema = testSchema
493+
},
494+
MetadataMethod: func(_ context.Context, _ resource.MetadataRequest, resp *resource.MetadataResponse) {
495+
resp.TypeName = "test_resource"
496+
},
497+
},
498+
MoveStateMethod: func(ctx context.Context) []resource.StateMover {
499+
return []resource.StateMover{
500+
{
501+
StateMover: func(_ context.Context, req resource.MoveStateRequest, resp *resource.MoveStateResponse) {
502+
expectedSourceRawState := testNewTfprotov6RawState(t, map[string]interface{}{
503+
"id": "test-id-value",
504+
"required_attribute": true,
505+
})
506+
507+
if diff := cmp.Diff(req.SourceRawState, expectedSourceRawState); diff != "" {
508+
resp.Diagnostics.AddError("Unexpected req.SourceRawState difference", diff)
509+
}
510+
511+
resp.Diagnostics.Append(resp.TargetIdentity.SetAttribute(ctx, path.Root("test_id"), "test_id_value")...)
512+
513+
// Prevent missing implementation error, the values do not matter except for response assertion
514+
resp.Diagnostics.Append(resp.TargetState.SetAttribute(ctx, path.Root("id"), "test-id-value")...)
515+
resp.Diagnostics.Append(resp.TargetState.SetAttribute(ctx, path.Root("required_attribute"), "true")...)
516+
},
517+
},
518+
}
519+
},
520+
IdentitySchemaMethod: func(ctx context.Context, req resource.IdentitySchemaRequest, resp *resource.IdentitySchemaResponse) {
521+
resp.IdentitySchema = testIdentitySchema
522+
},
523+
}
524+
},
525+
}
526+
},
527+
},
528+
},
529+
},
530+
request: &tfprotov5.MoveResourceStateRequest{
531+
SourceState: testNewTfprotov5RawState(t, map[string]interface{}{
532+
"id": "test-id-value",
533+
"required_attribute": true,
534+
}),
535+
SourceIdentity: testNewTfprotov5RawState(t, map[string]interface{}{
536+
"test_id": "test-id-value",
537+
}),
538+
TargetTypeName: "test_resource",
539+
},
540+
expectedResponse: &tfprotov5.MoveResourceStateResponse{
541+
TargetIdentity: &tfprotov5.ResourceIdentityData{IdentityData: testNewDynamicValue(t, schemaType, map[string]tftypes.Value{
542+
"test_id": tftypes.NewValue(tftypes.String, "test-id-value"),
543+
})},
544+
TargetState: testNewDynamicValue(t, schemaType, map[string]tftypes.Value{
545+
"id": tftypes.NewValue(tftypes.String, "test-id-value"),
546+
"optional_attribute": tftypes.NewValue(tftypes.String, nil),
547+
"required_attribute": tftypes.NewValue(tftypes.String, "true"),
548+
}),
549+
},
550+
},
416551
"request-TargetTypeName-missing": {
417552
server: &Server{
418553
FrameworkServer: fwserver.Server{
@@ -705,6 +840,64 @@ func TestServerMoveResourceState(t *testing.T) {
705840
}),
706841
},
707842
},
843+
"response-TargetIdentity": {
844+
server: &Server{
845+
FrameworkServer: fwserver.Server{
846+
Provider: &testprovider.Provider{
847+
ResourcesMethod: func(_ context.Context) []func() resource.Resource {
848+
return []func() resource.Resource{
849+
func() resource.Resource {
850+
return &testprovider.ResourceWithIdentityAndMoveState{
851+
Resource: &testprovider.Resource{
852+
SchemaMethod: func(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
853+
resp.Schema = testSchema
854+
},
855+
MetadataMethod: func(_ context.Context, _ resource.MetadataRequest, resp *resource.MetadataResponse) {
856+
resp.TypeName = "test_resource"
857+
},
858+
},
859+
MoveStateMethod: func(ctx context.Context) []resource.StateMover {
860+
return []resource.StateMover{
861+
{
862+
StateMover: func(_ context.Context, req resource.MoveStateRequest, resp *resource.MoveStateResponse) {
863+
resp.Diagnostics.Append(resp.TargetIdentity.SetAttribute(ctx, path.Root("test_id"), "test_id_value")...)
864+
resp.Diagnostics.Append(resp.TargetState.SetAttribute(ctx, path.Root("id"), "test-id-value")...)
865+
resp.Diagnostics.Append(resp.TargetState.SetAttribute(ctx, path.Root("required_attribute"), "true")...)
866+
},
867+
},
868+
}
869+
},
870+
IdentitySchemaMethod: func(ctx context.Context, req resource.IdentitySchemaRequest, resp *resource.IdentitySchemaResponse) {
871+
resp.IdentitySchema = testIdentitySchema
872+
},
873+
}
874+
},
875+
}
876+
},
877+
},
878+
},
879+
},
880+
request: &tfprotov5.MoveResourceStateRequest{
881+
SourceState: testNewTfprotov5RawState(t, map[string]interface{}{
882+
"id": "test-id-value",
883+
"required_attribute": true,
884+
}),
885+
SourceIdentity: testNewTfprotov5RawState(t, map[string]interface{}{
886+
"test_id": "test-id-value",
887+
}),
888+
TargetTypeName: "test_resource",
889+
},
890+
expectedResponse: &tfprotov5.MoveResourceStateResponse{
891+
TargetState: testNewDynamicValue(t, schemaType, map[string]tftypes.Value{
892+
"id": tftypes.NewValue(tftypes.String, "test-id-value"),
893+
"optional_attribute": tftypes.NewValue(tftypes.String, nil),
894+
"required_attribute": tftypes.NewValue(tftypes.String, "true"),
895+
}),
896+
TargetIdentity: &tfprotov5.ResourceIdentityData{IdentityData: testNewDynamicValue(t, schemaType, map[string]tftypes.Value{
897+
"test_id": tftypes.NewValue(tftypes.String, "test-id-value"),
898+
})},
899+
},
900+
},
708901
}
709902

710903
for name, testCase := range testCases {
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package testprovider
5+
6+
import (
7+
"context"
8+
9+
"github.com/hashicorp/terraform-plugin-framework/resource"
10+
)
11+
12+
var _ resource.Resource = &ResourceWithIdentityAndMoveState{}
13+
var _ resource.ResourceWithIdentity = &ResourceWithIdentityAndMoveState{}
14+
var _ resource.ResourceWithMoveState = &ResourceWithIdentityAndMoveState{}
15+
16+
// Declarative resource.ResourceWithIdentityAndMoveState for unit testing.
17+
type ResourceWithIdentityAndMoveState struct {
18+
*Resource
19+
20+
// ResourceWithIdentity interface methods
21+
IdentitySchemaMethod func(context.Context, resource.IdentitySchemaRequest, *resource.IdentitySchemaResponse)
22+
23+
// ResourceWithMoveState interface methods
24+
MoveStateMethod func(context.Context) []resource.StateMover
25+
}
26+
27+
// IdentitySchema implements resource.ResourceWithIdentity.
28+
func (p *ResourceWithIdentityAndMoveState) IdentitySchema(ctx context.Context, req resource.IdentitySchemaRequest, resp *resource.IdentitySchemaResponse) {
29+
if p.IdentitySchemaMethod == nil {
30+
return
31+
}
32+
33+
p.IdentitySchemaMethod(ctx, req, resp)
34+
}
35+
36+
// MoveState satisfies the resource.ResourceWithMoveState interface.
37+
func (r *ResourceWithIdentityAndMoveState) MoveState(ctx context.Context) []resource.StateMover {
38+
if r.MoveStateMethod == nil {
39+
return nil
40+
}
41+
42+
return r.MoveStateMethod(ctx)
43+
}

internal/toproto5/resource_identity.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import (
1414

1515
// ResourceIdentity returns the *tfprotov5.ResourceIdentityData for a *tfsdk.ResourceIdentity.
1616
func ResourceIdentity(ctx context.Context, fw *tfsdk.ResourceIdentity) (*tfprotov5.ResourceIdentityData, diag.Diagnostics) {
17-
if fw == nil {
17+
if fw == nil || fw.Schema == nil {
1818
return nil, nil
1919
}
2020

0 commit comments

Comments
 (0)