Skip to content

Commit e3c7b5d

Browse files
committed
add toproto and fromproto tests, code comments and thread through generate resource config server capabilities flag
1 parent a684191 commit e3c7b5d

File tree

10 files changed

+206
-9
lines changed

10 files changed

+206
-9
lines changed

internal/logging/keys.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,9 @@ const (
8484
// Whether the PlanDestroy server capability is enabled
8585
KeyServerCapabilityPlanDestroy = "tf_server_capability_plan_destroy"
8686

87+
// Whether the PlanDestroy server capability is enabled
88+
KeyServerCapabilityGenerateResourceConfig = "tf_server_capability_generate_resource_config"
89+
8790
// Whether the DeferralAllowed client capability is enabled
8891
KeyClientCapabilityDeferralAllowed = "tf_client_capability_deferral_allowed"
8992

tfprotov5/generate_resource_config.go

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,28 +5,29 @@ import (
55
)
66

77
// GenerateResourceConfigRequest is the request Terraform sends when it wants to generate configuration
8-
// from a resource's state value
8+
// from a resource's state value.
99
type GenerateResourceConfigRequest struct {
10-
// TODO comment
10+
// TypeName is the name of the resource.
1111
TypeName string
1212

13-
// TODO comment
13+
// State is the resource's state value.
1414
State *DynamicValue
1515

16-
// Mux fills this in
17-
ResourceSchema *Schema
16+
// Experimental, mux would fill this in
17+
// ResourceSchema *Schema
1818
}
1919

20-
// GenerateResourceConfigResponse TODO
20+
// GenerateResourceConfigResponse is the response from the provider containing the config value
21+
// that can be generated by Terraform.
2122
type GenerateResourceConfigResponse struct {
22-
// TODO comment
23+
// Config contains the resource's config value.
2324
Config *DynamicValue
2425

25-
// TODO comment
26+
// Diagnostics report errors or warnings related to the creation of the config value.
2627
Diagnostics []*Diagnostic
2728
}
2829

29-
// TODO comment
30+
// GenerateResourceConfigServer is an interface containing the method to generate resource config.
3031
type GenerateResourceConfigServer interface {
3132
GenerateResourceConfig(context.Context, *GenerateResourceConfigRequest) (*GenerateResourceConfigResponse, error)
3233
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package fromproto_test
5+
6+
import (
7+
"testing"
8+
9+
"github.com/google/go-cmp/cmp"
10+
11+
"github.com/hashicorp/terraform-plugin-go/tfprotov5"
12+
"github.com/hashicorp/terraform-plugin-go/tfprotov5/internal/fromproto"
13+
"github.com/hashicorp/terraform-plugin-go/tfprotov5/internal/tfplugin5"
14+
)
15+
16+
func TestGenerateResourceConfigRequest(t *testing.T) {
17+
t.Parallel()
18+
19+
testCases := map[string]struct {
20+
in *tfplugin5.GenerateResourceConfig_Request
21+
expected *tfprotov5.GenerateResourceConfigRequest
22+
}{
23+
"nil": {
24+
in: nil,
25+
expected: nil,
26+
},
27+
"zero": {
28+
in: &tfplugin5.GenerateResourceConfig_Request{},
29+
expected: &tfprotov5.GenerateResourceConfigRequest{},
30+
},
31+
"State": {
32+
in: &tfplugin5.GenerateResourceConfig_Request{
33+
State: testTfplugin5DynamicValue(),
34+
},
35+
expected: &tfprotov5.GenerateResourceConfigRequest{
36+
State: testTfprotov5DynamicValue(),
37+
},
38+
},
39+
"TypeName": {
40+
in: &tfplugin5.GenerateResourceConfig_Request{
41+
TypeName: "test",
42+
},
43+
expected: &tfprotov5.GenerateResourceConfigRequest{
44+
TypeName: "test",
45+
},
46+
},
47+
}
48+
49+
for name, testCase := range testCases {
50+
t.Run(name, func(t *testing.T) {
51+
t.Parallel()
52+
53+
got := fromproto.GenerateResourceConfigRequest(testCase.in)
54+
55+
if diff := cmp.Diff(got, testCase.expected); diff != "" {
56+
t.Errorf("unexpected difference: %s", diff)
57+
}
58+
})
59+
}
60+
}

tfprotov5/internal/tf5serverlogging/server_capabilities.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,14 @@ func ServerCapabilities(ctx context.Context, capabilities *tfprotov5.ServerCapab
1616
logging.KeyServerCapabilityGetProviderSchemaOptional: false,
1717
logging.KeyServerCapabilityMoveResourceState: false,
1818
logging.KeyServerCapabilityPlanDestroy: false,
19+
logging.KeyServerCapabilityGenerateResourceConfig: false,
1920
}
2021

2122
if capabilities != nil {
2223
responseFields[logging.KeyServerCapabilityGetProviderSchemaOptional] = capabilities.GetProviderSchemaOptional
2324
responseFields[logging.KeyServerCapabilityMoveResourceState] = capabilities.MoveResourceState
2425
responseFields[logging.KeyServerCapabilityPlanDestroy] = capabilities.PlanDestroy
26+
responseFields[logging.KeyServerCapabilityGenerateResourceConfig] = capabilities.GenerateResourceConfig
2527
}
2628

2729
logging.ProtocolTrace(ctx, "Announced server capabilities", responseFields)

tfprotov5/internal/tf5serverlogging/server_capabilities_test.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ func TestServerCapabilities(t *testing.T) {
3333
"tf_server_capability_get_provider_schema_optional": false,
3434
"tf_server_capability_move_resource_state": false,
3535
"tf_server_capability_plan_destroy": false,
36+
"tf_server_capability_generate_resource_config": false,
3637
},
3738
},
3839
},
@@ -46,6 +47,7 @@ func TestServerCapabilities(t *testing.T) {
4647
"tf_server_capability_get_provider_schema_optional": false,
4748
"tf_server_capability_move_resource_state": false,
4849
"tf_server_capability_plan_destroy": false,
50+
"tf_server_capability_generate_resource_config": false,
4951
},
5052
},
5153
},
@@ -61,6 +63,7 @@ func TestServerCapabilities(t *testing.T) {
6163
"tf_server_capability_get_provider_schema_optional": true,
6264
"tf_server_capability_move_resource_state": false,
6365
"tf_server_capability_plan_destroy": false,
66+
"tf_server_capability_generate_resource_config": false,
6467
},
6568
},
6669
},
@@ -76,6 +79,7 @@ func TestServerCapabilities(t *testing.T) {
7679
"tf_server_capability_get_provider_schema_optional": false,
7780
"tf_server_capability_move_resource_state": true,
7881
"tf_server_capability_plan_destroy": false,
82+
"tf_server_capability_generate_resource_config": false,
7983
},
8084
},
8185
},
@@ -91,6 +95,23 @@ func TestServerCapabilities(t *testing.T) {
9195
"tf_server_capability_get_provider_schema_optional": false,
9296
"tf_server_capability_move_resource_state": false,
9397
"tf_server_capability_plan_destroy": true,
98+
"tf_server_capability_generate_resource_config": false,
99+
},
100+
},
101+
},
102+
"generate_resource_config": {
103+
capabilities: &tfprotov5.ServerCapabilities{
104+
GenerateResourceConfig: true,
105+
},
106+
expected: []map[string]interface{}{
107+
{
108+
"@level": "trace",
109+
"@message": "Announced server capabilities",
110+
"@module": "sdk.proto",
111+
"tf_server_capability_get_provider_schema_optional": false,
112+
"tf_server_capability_move_resource_state": false,
113+
"tf_server_capability_plan_destroy": false,
114+
"tf_server_capability_generate_resource_config": true,
94115
},
95116
},
96117
},
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package toproto_test
5+
6+
import (
7+
"testing"
8+
9+
"github.com/google/go-cmp/cmp"
10+
"github.com/google/go-cmp/cmp/cmpopts"
11+
"google.golang.org/protobuf/types/known/timestamppb"
12+
13+
"github.com/hashicorp/terraform-plugin-go/tfprotov5"
14+
"github.com/hashicorp/terraform-plugin-go/tfprotov5/internal/tfplugin5"
15+
"github.com/hashicorp/terraform-plugin-go/tfprotov5/internal/toproto"
16+
)
17+
18+
func TestGenerateResourceConfig_Response(t *testing.T) {
19+
t.Parallel()
20+
21+
testCases := map[string]struct {
22+
in *tfprotov5.GenerateResourceConfigResponse
23+
expected *tfplugin5.GenerateResourceConfig_Response
24+
}{
25+
"nil": {
26+
in: nil,
27+
expected: nil,
28+
},
29+
"zero": {
30+
in: &tfprotov5.GenerateResourceConfigResponse{},
31+
expected: &tfplugin5.GenerateResourceConfig_Response{
32+
Diagnostics: []*tfplugin5.Diagnostic{},
33+
},
34+
},
35+
"Diagnostics": {
36+
in: &tfprotov5.GenerateResourceConfigResponse{
37+
Diagnostics: []*tfprotov5.Diagnostic{
38+
testTfprotov5Diagnostic,
39+
},
40+
},
41+
expected: &tfplugin5.GenerateResourceConfig_Response{
42+
Diagnostics: []*tfplugin5.Diagnostic{
43+
testTfplugin5Diagnostic,
44+
},
45+
},
46+
},
47+
"Config": {
48+
in: &tfprotov5.GenerateResourceConfigResponse{
49+
Config: testTfprotov5DynamicValue(),
50+
},
51+
expected: &tfplugin5.GenerateResourceConfig_Response{
52+
Diagnostics: []*tfplugin5.Diagnostic{},
53+
Config: testTfplugin5DynamicValue(),
54+
},
55+
},
56+
}
57+
58+
for name, testCase := range testCases {
59+
t.Run(name, func(t *testing.T) {
60+
t.Parallel()
61+
62+
got := toproto.GenerateResourceConfigResponse(testCase.in)
63+
64+
// Protocol Buffers generated types must have unexported fields
65+
// ignored or cmp.Diff() will raise an error. This is easier than
66+
// writing a custom Comparer for each type, which would have no
67+
// benefits.
68+
diffOpts := cmpopts.IgnoreUnexported(
69+
tfplugin5.Diagnostic{},
70+
tfplugin5.DynamicValue{},
71+
tfplugin5.GenerateResourceConfig_Response{},
72+
tfplugin5.Deferred{},
73+
timestamppb.Timestamp{},
74+
)
75+
76+
if diff := cmp.Diff(got, testCase.expected, diffOpts); diff != "" {
77+
t.Errorf("unexpected difference: %s", diff)
78+
}
79+
})
80+
}
81+
}

tfprotov5/internal/toproto/server_capabilities.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ func ServerCapabilities(in *tfprotov5.ServerCapabilities) *tfplugin5.ServerCapab
1717
GetProviderSchemaOptional: in.GetProviderSchemaOptional,
1818
MoveResourceState: in.MoveResourceState,
1919
PlanDestroy: in.PlanDestroy,
20+
GenerateResourceConfig: in.GenerateResourceConfig,
2021
}
2122

2223
return resp

tfprotov5/internal/toproto/server_capabilities_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,14 @@ func TestServerCapabilities(t *testing.T) {
5252
PlanDestroy: true,
5353
},
5454
},
55+
"GenerateResourceConfig": {
56+
in: &tfprotov5.ServerCapabilities{
57+
GenerateResourceConfig: true,
58+
},
59+
expected: &tfplugin5.ServerCapabilities{
60+
GenerateResourceConfig: true,
61+
},
62+
},
5563
}
5664

5765
for name, testCase := range testCases {

tfprotov5/provider.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ type ProviderServer interface {
3838
// down as quickly as possible, and usually represents an interrupt.
3939
StopProvider(context.Context, *StopProviderRequest) (*StopProviderResponse, error)
4040

41+
//
4142
GenerateResourceConfig(context.Context, *GenerateResourceConfigRequest) (*GenerateResourceConfigResponse, error)
4243

4344
// ResourceServer is an interface encapsulating all the
@@ -111,6 +112,21 @@ type ProviderServerWithActions interface {
111112
ActionServer
112113
}
113114

115+
// ProviderServerWithGenerateResourceConfig is a temporary interface for servers
116+
// to implement the GenerateResourceConfig RPC.
117+
//
118+
// - GenerateResourceConfig
119+
//
120+
// Deprecated: This method will be moved into the
121+
// ProviderServer interface and this interface will be removed in a future
122+
// version.
123+
type ProviderServerWithGenerateResourceConfig interface {
124+
ProviderServer
125+
126+
// GenerateResourceConfigServer is an interface containing the method to generate resource config.
127+
GenerateResourceConfigServer
128+
}
129+
114130
// GetMetadataRequest represents a GetMetadata RPC request.
115131
type GetMetadataRequest struct{}
116132

tfprotov5/server_capabilities.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,8 @@ type ServerCapabilities struct {
2323
// opt-in to prevent unexpected errors or panics since the
2424
// ProposedNewState in PlanResourceChangeRequest will be a null value.
2525
PlanDestroy bool
26+
27+
// GenerateResourceConfig signals that a provider supports the GenerateResourceConfig
28+
// RPC.
29+
GenerateResourceConfig bool
2630
}

0 commit comments

Comments
 (0)