Skip to content

Commit 1d9a850

Browse files
committed
Templating out Framework implementation for Pluggable State Storage
1 parent 58c003c commit 1d9a850

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+14908
-12
lines changed

go.mod

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ toolchain go1.24.4
66

77
require (
88
github.com/google/go-cmp v0.7.0
9-
github.com/hashicorp/terraform-plugin-go v0.29.0
9+
github.com/hashicorp/terraform-plugin-go v0.29.1-0.20251028091959-b0e5c5f97a7c
1010
github.com/hashicorp/terraform-plugin-log v0.9.0
1111
)
1212

@@ -28,7 +28,7 @@ require (
2828
golang.org/x/net v0.43.0 // indirect
2929
golang.org/x/sys v0.35.0 // indirect
3030
golang.org/x/text v0.28.0 // indirect
31-
google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 // indirect
32-
google.golang.org/grpc v1.75.1 // indirect
33-
google.golang.org/protobuf v1.36.9 // indirect
31+
google.golang.org/genproto/googleapis/rpc v0.0.0-20250804133106-a7a43d27e69b // indirect
32+
google.golang.org/grpc v1.76.0 // indirect
33+
google.golang.org/protobuf v1.36.10 // indirect
3434
)

go.sum

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ github.com/hashicorp/go-plugin v1.7.0 h1:YghfQH/0QmPNc/AZMTFE3ac8fipZyZECHdDPshf
2323
github.com/hashicorp/go-plugin v1.7.0/go.mod h1:BExt6KEaIYx804z8k4gRzRLEvxKVb+kn0NMcihqOqb8=
2424
github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
2525
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
26-
github.com/hashicorp/terraform-plugin-go v0.29.0 h1:1nXKl/nSpaYIUBU1IG/EsDOX0vv+9JxAltQyDMpq5mU=
27-
github.com/hashicorp/terraform-plugin-go v0.29.0/go.mod h1:vYZbIyvxyy0FWSmDHChCqKvI40cFTDGSb3D8D70i9GM=
26+
github.com/hashicorp/terraform-plugin-go v0.29.1-0.20251028091959-b0e5c5f97a7c h1:CZun5uZTGnQhElJBvo49mqvIBzQOPH2OSL6xazuzeQE=
27+
github.com/hashicorp/terraform-plugin-go v0.29.1-0.20251028091959-b0e5c5f97a7c/go.mod h1:KHRnT9vExG+r1fLxwOzOP6C6YXiaKHtsCIrky7teDYc=
2828
github.com/hashicorp/terraform-plugin-log v0.9.0 h1:i7hOA+vdAItN1/7UrfBqBwvYPQ9TFvymaRGZED3FCV0=
2929
github.com/hashicorp/terraform-plugin-log v0.9.0/go.mod h1:rKL8egZQ/eXSyDqzLUuwUYLVdlYeamldAHSxjUFADow=
3030
github.com/hashicorp/terraform-registry-address v0.4.0 h1:S1yCGomj30Sao4l5BMPjTGZmCNzuv7/GDTDX99E9gTk=
@@ -86,12 +86,12 @@ golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
8686
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
8787
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
8888
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
89-
google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 h1:pFyd6EwwL2TqFf8emdthzeX+gZE1ElRq3iM8pui4KBY=
90-
google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
91-
google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI=
92-
google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ=
93-
google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw=
94-
google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
89+
google.golang.org/genproto/googleapis/rpc v0.0.0-20250804133106-a7a43d27e69b h1:zPKJod4w6F1+nRGDI9ubnXYhU9NSWoFAijkHkUXeTK8=
90+
google.golang.org/genproto/googleapis/rpc v0.0.0-20250804133106-a7a43d27e69b/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
91+
google.golang.org/grpc v1.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A=
92+
google.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c=
93+
google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
94+
google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
9595
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
9696
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
9797
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

provider/provider.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,3 +164,16 @@ type ProviderWithValidateConfig interface {
164164
// ValidateConfig performs the validation.
165165
ValidateConfig(context.Context, ValidateConfigRequest, *ValidateConfigResponse)
166166
}
167+
168+
// ProviderWithStateStores is an interface type that extends Provider to include state store.
169+
type ProviderWithStateStores interface {
170+
Provider
171+
172+
// StateStores returns a slice of functions to instantiate each
173+
// StateStore implementation.
174+
//
175+
// The state store type name is determined by the
176+
// StateStore implementing the Metadata method. All state
177+
// stores must have unique names.
178+
StateStores(context.Context) []func() statestore.StateStore
179+
}

statestore/config_validator.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package statestore
5+
6+
import "context"
7+
8+
// ConfigValidator describes reusable state store configuration validation functionality.
9+
type ConfigValidator interface {
10+
// Description describes the validation in plain text formatting.
11+
//
12+
// This information may be automatically added to state store plain text
13+
// descriptions by external tooling.
14+
Description(context.Context) string
15+
16+
// MarkdownDescription describes the validation in Markdown formatting.
17+
//
18+
// This information may be automatically added to state store Markdown
19+
// descriptions by external tooling.
20+
MarkdownDescription(context.Context) string
21+
22+
// ValidateStateStore performs the validation.
23+
//
24+
// This method name is separate from ConfigValidators in resource and other packages in
25+
// order to allow generic validators.
26+
ValidateStateStore(context.Context, ValidateConfigRequest, *ValidateConfigResponse)
27+
}

statestore/configure.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package statestore
5+
6+
import "github.com/hashicorp/terraform-plugin-framework/diag"
7+
8+
// ConfigureRequest represents a request for the provider to configure an
9+
// state store, i.e., set provider-level data or clients. An instance of this
10+
// request struct is supplied as an argument to the StateStore type Configure
11+
// method.
12+
type ConfigureRequest struct {
13+
// ProviderData is the data set in the
14+
// [provider.ConfigureResponse.StateStoreData] field. This data is
15+
// provider-specific and therefore can contain any necessary remote system
16+
// clients, custom provider data, or anything else pertinent to the
17+
// functionality of the StateStore.
18+
//
19+
// This data is only set after the ConfigureProvider RPC has been called
20+
// by Terraform.
21+
ProviderData any
22+
}
23+
24+
// ConfigureResponse represents a response to a ConfigureRequest. An
25+
// instance of this response struct is supplied as an argument to the
26+
// StateStore type Configure method.
27+
type ConfigureResponse struct {
28+
// Diagnostics report errors or warnings related to configuring of the
29+
// Datasource. An empty slice indicates a successful operation with no
30+
// warnings or errors generated.
31+
Diagnostics diag.Diagnostics
32+
}

statestore/delete_states.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package statestore
5+
6+
import (
7+
"github.com/hashicorp/terraform-plugin-framework/diag"
8+
"github.com/hashicorp/terraform-plugin-framework/internal/privatestate"
9+
)
10+
11+
// DeleteStatesRequest represents a request for the provider to delete a
12+
// state. An instance of this request struct is supplied as an argument to
13+
// the state's DeleteStates function.
14+
type DeleteStatesRequest struct {
15+
// Private is provider-defined state private state data which was previously
16+
// stored with the state state.
17+
//
18+
// Use the GetKey method to read data.
19+
Private *privatestate.ProviderData
20+
}
21+
22+
// DeleteStatesResponse represents a response to a DeleteStatesRequest. An
23+
// instance of this response struct is supplied as
24+
// an argument to the state's DeleteStates function, in which the provider
25+
// should set values on the DeleteStatesResponse as appropriate.
26+
type DeleteStatesResponse struct {
27+
// Private is the private state data following the DeleteStates
28+
// operation. This field is pre-populated from DeleteStatesRequest.Private and
29+
// can be modified during the state's DeleteStates operation in cases where
30+
// an error diagnostic is being returned. Otherwise if no error diagnostic
31+
// is being returned, indicating that the state was successfully deleted,
32+
// this data will be automatically cleared to prevent Terraform errors.
33+
Private *privatestate.ProviderData
34+
35+
// Diagnostics report errors or warnings related to deleting the
36+
// state. An empty slice indicates a successful operation with no
37+
// warnings or errors generated.
38+
Diagnostics diag.Diagnostics
39+
}

statestore/get_states.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package statestore
5+
6+
// GetStatesRequest represents a request for the StateStore to return metadata,
7+
// such as its type name. An instance of this request struct is supplied as
8+
// an argument to the StateStore type Get method.
9+
type GetStatesRequest struct {
10+
// ProviderTypeName is the string returned from
11+
// [provider.GetStatesResponse.TypeName], if the Provider type implements
12+
// the Get method. This string should prefix the StateStore type name
13+
// with an underscore in the response.
14+
ProviderTypeName string
15+
}
16+
17+
// GetStatesResponse represents a response to a GetStatesRequest. An
18+
// instance of this response struct is supplied as an argument to the
19+
// StateStore type Get method.
20+
type GetStatesResponse struct {
21+
// TypeName should be the full state store type, including the provider
22+
// type prefix and an underscore. For example, examplecloud_thing.
23+
TypeName string
24+
}

statestore/lock.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package statestore
5+
6+
// LockRequest represents a request for the StateStore to return metadata,
7+
// such as its type name. An instance of this request struct is supplied as
8+
// an argument to the StateStore type Lock method.
9+
type LockRequest struct {
10+
// ProviderTypeName is the string returned from
11+
// [provider.LockResponse.TypeName], if the Provider type implements
12+
// the Lock method. This string should prefix the StateStore type name
13+
// with an underscore in the response.
14+
ProviderTypeName string
15+
}
16+
17+
// LockResponse represents a response to a LockRequest. An
18+
// instance of this response struct is supplied as an argument to the
19+
// StateStore type Lock method.
20+
type LockResponse struct {
21+
// TypeName should be the full state store type, including the provider
22+
// type prefix and an underscore. For example, examplecloud_thing.
23+
TypeName string
24+
}

statestore/metadata.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package statestore
5+
6+
// MetadataRequest represents a request for the StateStore to return metadata,
7+
// such as its type name. An instance of this request struct is supplied as
8+
// an argument to the StateStore type Metadata method.
9+
type MetadataRequest struct {
10+
// ProviderTypeName is the string returned from
11+
// [provider.MetadataResponse.TypeName], if the Provider type implements
12+
// the Metadata method. This string should prefix the StateStore type name
13+
// with an underscore in the response.
14+
ProviderTypeName string
15+
}
16+
17+
// MetadataResponse represents a response to a MetadataRequest. An
18+
// instance of this response struct is supplied as an argument to the
19+
// StateStore type Metadata method.
20+
type MetadataResponse struct {
21+
// TypeName should be the full state store type, including the provider
22+
// type prefix and an underscore. For example, examplecloud_thing.
23+
TypeName string
24+
}

statestore/read.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package statestore
5+
6+
import (
7+
"github.com/hashicorp/terraform-plugin-framework/diag"
8+
"github.com/hashicorp/terraform-plugin-framework/tfsdk"
9+
)
10+
11+
// ReadClientCapabilities allows Terraform to publish information
12+
// regarding optionally supported protocol features for the ReadStateStore RPC,
13+
// such as forward-compatible Terraform behavior changes.
14+
type ReadClientCapabilities struct {
15+
}
16+
17+
// ReadRequest represents a request for the provider to read a data
18+
// source, i.e., update values in state according to the real state of the
19+
// state store. An instance of this request struct is supplied as an argument
20+
// to the state store's Read function.
21+
type ReadRequest struct {
22+
// Config is the configuration the user supplied for the state store.
23+
//
24+
// This configuration may contain unknown values if a user uses
25+
// interpolation or other functionality that would prevent Terraform
26+
// from knowing the value at request time.
27+
Config tfsdk.Config
28+
29+
// ProviderMeta is metadata from the provider_meta block of the module.
30+
ProviderMeta tfsdk.Config
31+
32+
// ClientCapabilities defines optionally supported protocol features for the
33+
// ReadStateStore RPC, such as forward-compatible Terraform behavior changes.
34+
ClientCapabilities ReadClientCapabilities
35+
}
36+
37+
// ReadResponse represents a response to a ReadRequest. An
38+
// instance of this response struct is supplied as an argument to the data
39+
// source's Read function, in which the provider should set values on the
40+
// ReadResponse as appropriate.
41+
type ReadResponse struct {
42+
// State is the state of the state store following the Read operation.
43+
// This field should be set during the resource's Read operation.
44+
State tfsdk.State
45+
46+
// Diagnostics report errors or warnings related to reading the data
47+
// source. An empty slice indicates a successful operation with no
48+
// warnings or errors generated.
49+
Diagnostics diag.Diagnostics
50+
}

0 commit comments

Comments
 (0)