Skip to content

Commit dfb1155

Browse files
tfprotov6: Add protocol support for pluggable state storage (#563)
* Add protocol support for pluggable state stores * Implement ValidateStateStoreConfig + ConfigureStateStore methods * implement ReadStateBytes * implement WriteStateBytes * Use iter.Seq2 to allow errors to be accessed by calling code in downstream provider implementation * Stop iterator using return instead of break * Formatting * Update `WriteStateBytesStream` to not use Seq2, instead iterate over 'messages' that contain both chunk data and any raised grpc errors * Seeing what it looks like to use 'message' as name * Seeing what it looks like to avoid 'messages' name * Update WriteStateBytesStreamMsg => WriteStateBytesChunk * implement state chunk size negotiation * handle metadata in WriteStateBytes correctly * Add LockState and UnlockState methods to .proto file for Protocol v6 * Run `make protobuf` * Add handwritten code related to LockState and UnlockState RPCs * Running `make protobuf` after rebasing onto main * Add missing (Lock/Unlock)State related code * add LockId mapping :P --------- Co-authored-by: Sarah French <[email protected]>
1 parent 700ccf6 commit dfb1155

File tree

12 files changed

+5163
-2409
lines changed

12 files changed

+5163
-2409
lines changed

internal/logging/context.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,15 @@ func ActionContext(ctx context.Context, action string) context.Context {
109109
return ctx
110110
}
111111

112+
// StateStoreContext injects the state store type into logger contexts.
113+
func StateStoreContext(ctx context.Context, stateStore string) context.Context {
114+
ctx = tfsdklog.SetField(ctx, KeyStateStoreType, stateStore)
115+
ctx = tfsdklog.SubsystemSetField(ctx, SubsystemProto, KeyStateStoreType, stateStore)
116+
ctx = tflog.SetField(ctx, KeyStateStoreType, stateStore)
117+
118+
return ctx
119+
}
120+
112121
// RpcContext injects the RPC name into logger contexts.
113122
func RpcContext(ctx context.Context, rpc string) context.Context {
114123
ctx = tfsdklog.SetField(ctx, KeyRPC, rpc)

internal/logging/keys.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ const (
6666
// The action being operated on
6767
KeyActionType = "tf_action_type"
6868

69+
// The type of state store being operated on, such as "terraform_fs"
70+
KeyStateStoreType = "tf_state_store_type"
71+
6972
// Path to protocol data file, such as "/tmp/example.json"
7073
KeyProtocolDataFile = "tf_proto_data_file"
7174

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package fromproto
5+
6+
import (
7+
"github.com/hashicorp/terraform-plugin-go/tfprotov6"
8+
"github.com/hashicorp/terraform-plugin-go/tfprotov6/internal/tfplugin6"
9+
)
10+
11+
func ValidateStateStoreRequest(in *tfplugin6.ValidateStateStore_Request) *tfprotov6.ValidateStateStoreRequest {
12+
if in == nil {
13+
return nil
14+
}
15+
16+
return &tfprotov6.ValidateStateStoreRequest{
17+
TypeName: in.TypeName,
18+
Config: DynamicValue(in.Config),
19+
}
20+
}
21+
22+
func ConfigureStateStoreRequest(in *tfplugin6.ConfigureStateStore_Request) *tfprotov6.ConfigureStateStoreRequest {
23+
if in == nil {
24+
return nil
25+
}
26+
27+
return &tfprotov6.ConfigureStateStoreRequest{
28+
TypeName: in.TypeName,
29+
Config: DynamicValue(in.Config),
30+
Capabilities: tfprotov6.StateStoreClientCapabilities{
31+
ChunkSize: in.Capabilities.ChunkSize,
32+
},
33+
}
34+
}
35+
36+
func ReadStateBytesRequest(in *tfplugin6.ReadStateBytes_Request) *tfprotov6.ReadStateBytesRequest {
37+
if in == nil {
38+
return nil
39+
}
40+
41+
return &tfprotov6.ReadStateBytesRequest{
42+
TypeName: in.TypeName,
43+
StateId: in.StateId,
44+
}
45+
}
46+
47+
func GetStatesRequest(in *tfplugin6.GetStates_Request) *tfprotov6.GetStatesRequest {
48+
if in == nil {
49+
return nil
50+
}
51+
52+
return &tfprotov6.GetStatesRequest{
53+
TypeName: in.TypeName,
54+
}
55+
}
56+
57+
func DeleteStateRequest(in *tfplugin6.DeleteState_Request) *tfprotov6.DeleteStateRequest {
58+
if in == nil {
59+
return nil
60+
}
61+
62+
return &tfprotov6.DeleteStateRequest{
63+
TypeName: in.TypeName,
64+
StateId: in.StateId,
65+
}
66+
}
67+
68+
func LockStateRequest(in *tfplugin6.LockState_Request) *tfprotov6.LockStateRequest {
69+
if in == nil {
70+
return nil
71+
}
72+
73+
return &tfprotov6.LockStateRequest{
74+
TypeName: in.TypeName,
75+
StateId: in.StateId,
76+
Operation: in.Operation,
77+
}
78+
}
79+
80+
func UnlockStateRequest(in *tfplugin6.UnlockState_Request) *tfprotov6.UnlockStateRequest {
81+
if in == nil {
82+
return nil
83+
}
84+
85+
return &tfprotov6.UnlockStateRequest{
86+
TypeName: in.TypeName,
87+
StateId: in.StateId,
88+
LockId: in.LockId,
89+
}
90+
}

0 commit comments

Comments
 (0)