Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
5 changes: 5 additions & 0 deletions .changes/unreleased/FEATURES-20260120-165734.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
kind: FEATURES
body: 'tfprotov6: Upgraded protocol v6 and added types to support the new state store type.'
time: 2026-01-20T16:57:34.518083-05:00
custom:
Issue: "563"
5 changes: 5 additions & 0 deletions .changes/unreleased/NOTES-20260120-165912.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
kind: NOTES
body: 'tfprotov6: An upcoming release will require the `StateStoreServer` implementation as part of `ProviderServer`.'
time: 2026-01-20T16:59:12.981851-05:00
custom:
Issue: "594"
8 changes: 7 additions & 1 deletion internal/logging/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ const (
// The action being operated on
KeyActionType = "tf_action_type"

// The type of state store being operated on, such as "terraform_fs"
// The type of state store being operated on, such as "examplecloud_fs"
KeyStateStoreType = "tf_state_store_type"

// Path to protocol data file, such as "/tmp/example.json"
Expand All @@ -87,9 +87,15 @@ const (
// Whether the PlanDestroy server capability is enabled
KeyServerCapabilityPlanDestroy = "tf_server_capability_plan_destroy"

// The final determined ChunkSize returned from the provider for transmitting state bytes.
KeyServerCapabilityChunkSize = "tf_server_capability_chunk_size"

// Whether the DeferralAllowed client capability is enabled
KeyClientCapabilityDeferralAllowed = "tf_client_capability_deferral_allowed"

// Whether the WriteOnlyAttributesAllowed client capability is enabled
KeyClientCapabilityWriteOnlyAttributesAllowed = "tf_client_capability_write_only_attributes_allowed"

// The ChunkSize requested from Terraform core for transmitting state bytes.
KeyClientCapabilityChunkSize = "tf_client_capability_chunk_size"
)
6 changes: 3 additions & 3 deletions tfprotov5/internal/tfplugin5/tfplugin5.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions tfprotov5/internal/tfplugin5/tfplugin5.proto
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

// Terraform Plugin RPC protocol version 5.10
// Terraform Plugin RPC protocol version 5.11
//
// This file defines version 5.10 of the RPC protocol. To implement a plugin
// This file defines version 5.11 of the RPC protocol. To implement a plugin
// against this protocol, copy this definition into your own codebase and
// use protoc to generate stubs for your target language.
//
// This file will not be updated. Any minor versions of protocol 5 to follow
// should copy this file and modify the copy while maintaing backwards
// should copy this file and modify the copy while maintaining backwards
// compatibility. Breaking changes, if any are required, will come
// in a subsequent major version with its own separate proto definition.
//
Expand Down Expand Up @@ -71,7 +71,7 @@ message Stop {
message Request {
}
message Response {
string Error = 1;
string Error = 1;
}
}

Expand Down
6 changes: 3 additions & 3 deletions tfprotov5/internal/tfplugin5/tfplugin5_grpc.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion tfprotov5/tf5server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ const (
//
// In the future, it may be possible to include this information directly
// in the protocol buffers rather than recreating a constant here.
protocolVersionMinor uint = 10
protocolVersionMinor uint = 11
)

// protocolVersion represents the combined major and minor version numbers of
Expand Down
11 changes: 11 additions & 0 deletions tfprotov6/client_capabilities.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,14 @@ type PlanActionClientCapabilities struct {
// but currently they are not sending any capabilities for this RPC.
type InvokeActionClientCapabilities struct {
}

// ConfigureStateStoreClientCapabilities allows Terraform to publish information
// regarding optionally supported protocol features for the ConfigureStateStore RPC,
// such as forward-compatible Terraform behavior changes.
type ConfigureStateStoreClientCapabilities struct {
// ChunkSize is the client-requested size of state byte chunks that are sent between Terraform Core and
// the provider. The final value is determined by the provider and returned in [ConfigureStateStoreResponse.Capabilities]
//
// The default chunk size in Terraform core is 8 MB.
ChunkSize int64
}
12 changes: 12 additions & 0 deletions tfprotov6/internal/fromproto/client_capabilities.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,15 @@ func InvokeActionClientCapabilities(in *tfplugin6.ClientCapabilities) *tfprotov6

return resp
}

func ConfigureStateStoreClientCapabilities(in *tfplugin6.StateStoreClientCapabilities) *tfprotov6.ConfigureStateStoreClientCapabilities {
if in == nil {
return nil
}

resp := &tfprotov6.ConfigureStateStoreClientCapabilities{
ChunkSize: in.ChunkSize,
}

return resp
}
64 changes: 52 additions & 12 deletions tfprotov6/internal/fromproto/state_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ import (
"github.com/hashicorp/terraform-plugin-go/tfprotov6/internal/tfplugin6"
)

func ValidateStateStoreRequest(in *tfplugin6.ValidateStateStore_Request) *tfprotov6.ValidateStateStoreRequest {
func ValidateStateStoreConfigRequest(in *tfplugin6.ValidateStateStoreConfig_Request) *tfprotov6.ValidateStateStoreConfigRequest {
if in == nil {
return nil
}

return &tfprotov6.ValidateStateStoreRequest{
return &tfprotov6.ValidateStateStoreConfigRequest{
TypeName: in.TypeName,
Config: DynamicValue(in.Config),
}
Expand All @@ -25,11 +25,9 @@ func ConfigureStateStoreRequest(in *tfplugin6.ConfigureStateStore_Request) *tfpr
}

return &tfprotov6.ConfigureStateStoreRequest{
TypeName: in.TypeName,
Config: DynamicValue(in.Config),
Capabilities: tfprotov6.StateStoreClientCapabilities{
ChunkSize: in.Capabilities.ChunkSize,
},
TypeName: in.TypeName,
Config: DynamicValue(in.Config),
Capabilities: ConfigureStateStoreClientCapabilities(in.Capabilities),
}
}

Expand All @@ -40,7 +38,7 @@ func ReadStateBytesRequest(in *tfplugin6.ReadStateBytes_Request) *tfprotov6.Read

return &tfprotov6.ReadStateBytesRequest{
TypeName: in.TypeName,
StateId: in.StateId,
StateID: in.StateId,
}
}

Expand All @@ -61,7 +59,7 @@ func DeleteStateRequest(in *tfplugin6.DeleteState_Request) *tfprotov6.DeleteStat

return &tfprotov6.DeleteStateRequest{
TypeName: in.TypeName,
StateId: in.StateId,
StateID: in.StateId,
}
}

Expand All @@ -72,7 +70,7 @@ func LockStateRequest(in *tfplugin6.LockState_Request) *tfprotov6.LockStateReque

return &tfprotov6.LockStateRequest{
TypeName: in.TypeName,
StateId: in.StateId,
StateID: in.StateId,
Operation: in.Operation,
}
}
Expand All @@ -84,7 +82,49 @@ func UnlockStateRequest(in *tfplugin6.UnlockState_Request) *tfprotov6.UnlockStat

return &tfprotov6.UnlockStateRequest{
TypeName: in.TypeName,
StateId: in.StateId,
LockId: in.LockId,
StateID: in.StateId,
LockID: in.LockId,
}
}

func WriteStateBytesChunk(in *tfplugin6.WriteStateBytes_RequestChunk) (*tfprotov6.WriteStateBytesChunk, *tfprotov6.Diagnostic) {
if in == nil {
return nil, &tfprotov6.Diagnostic{
Severity: tfprotov6.DiagnosticSeverityError,
Summary: "Unexpected empty state chunk in WriteStateBytes",
Detail: "An empty state byte chunk was received. This is a bug in Terraform that should be reported to the maintainers.",
}
}

if in.Range == nil {
return nil, &tfprotov6.Diagnostic{
Severity: tfprotov6.DiagnosticSeverityError,
Summary: "Unexpected state chunk data received in WriteStateBytes",
Detail: "An invalid state byte chunk was received with no range start/end information. " +
"This is a bug in Terraform that should be reported to the maintainers.",
}
}

var meta *tfprotov6.WriteStateChunkMeta
if in.Meta != nil {
// Metadata is only attached to the first chunk
meta = &tfprotov6.WriteStateChunkMeta{
TypeName: in.Meta.TypeName,
StateID: in.Meta.StateId,
}
}

stateChunk := &tfprotov6.WriteStateBytesChunk{
Meta: meta,
StateByteChunk: tfprotov6.StateByteChunk{
Bytes: in.Bytes,
TotalLength: in.TotalLength,
Range: tfprotov6.StateByteRange{
Start: in.Range.Start,
End: in.Range.End,
},
},
}

return stateChunk, nil
}
Loading
Loading