Skip to content

Add rough code for configure storage methods #36843

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 27 commits into
base: radek/pluggable-backends-protocol
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
d60510b
add protobuf definitions
radeksimko Mar 28, 2025
7a39abe
make protobuf
radeksimko Mar 28, 2025
62389e0
make generate
radeksimko Mar 28, 2025
5a24039
grpcwrap: add skeleton implementation
radeksimko Mar 28, 2025
665e563
add TODOs
radeksimko Mar 28, 2025
b6a8135
providers/testing: Remove unused *TypeName fields
radeksimko Apr 1, 2025
8d2f4b8
WIP
radeksimko Apr 1, 2025
c70376f
Make file for protocol 5.10
SarahFrench Apr 1, 2025
306cfd0
Add pluggable storage-related changes to new proto file
SarahFrench Apr 1, 2025
426aca8
Update symlink for protocol 5 proto file
SarahFrench Apr 1, 2025
40f823b
make protobuf
SarahFrench Apr 1, 2025
4e6851b
make generate
SarahFrench Apr 1, 2025
7a81f2e
Add new methods in tfplugin5.ProviderServer interface to protocol 5 g…
SarahFrench Apr 1, 2025
6ff3410
Merge pull request #36815 from hashicorp/sarah/add-protocol-5-support
SarahFrench Apr 1, 2025
9e6a40d
Update `GetProviderSchema` in .proto files to include state store sch…
SarahFrench Apr 2, 2025
2f0c827
make protobuf
SarahFrench Apr 2, 2025
86a4ad7
Update GetProviderSchemaResponse struct
SarahFrench Apr 2, 2025
1725c70
`terraform` provider reports it has no state stores
SarahFrench Apr 2, 2025
9cec7dd
Update grpcwrap
SarahFrench Apr 2, 2025
4dd18da
Uncertain TODO comments
SarahFrench Apr 2, 2025
0631999
Apply suggestions from code review
SarahFrench Apr 3, 2025
15c7077
Update to StateStoreSchemas
SarahFrench Apr 3, 2025
3bbaa88
make protobuf
SarahFrench Apr 3, 2025
a42dc61
Update to "StateStoreSchemas"
SarahFrench Apr 3, 2025
81b44cf
Add ephemeral resource and state store processing to protocol 5 grpcwrap
SarahFrench Apr 3, 2025
28674b5
WIP adding ConfigureStorage method
SarahFrench Apr 1, 2025
7456716
Fill in `ConfigureStorage` methods
SarahFrench Apr 2, 2025
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
920 changes: 920 additions & 0 deletions docs/plugin-protocol/tfplugin5.10.proto

Large diffs are not rendered by default.

899 changes: 899 additions & 0 deletions docs/plugin-protocol/tfplugin6.10.proto

Large diffs are not rendered by default.

13 changes: 13 additions & 0 deletions internal/builtin/providers/terraform/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ func (p *Provider) GetProviderSchema() providers.GetProviderSchemaResponse {
ReturnType: cty.String,
},
},
StateStoreSchemas: map[string]providers.Schema{},
}
providers.SchemaCache.Set(tfaddr.NewProvider(tfaddr.BuiltInProviderHost, tfaddr.BuiltInProviderNamespace, "terraform"), resp)
return resp
Expand Down Expand Up @@ -268,3 +269,15 @@ func (p *Provider) CallFunction(req providers.CallFunctionRequest) providers.Cal
func (p *Provider) Close() error {
return nil
}

func (p *Provider) ValidateStorageConfig(req providers.ValidateStorageConfigRequest) providers.ValidateStorageConfigResponse {
var resp providers.ValidateStorageConfigResponse
resp.Diagnostics = resp.Diagnostics.Append(fmt.Errorf("unsupported storage type %q", req.TypeName))
return resp
}

func (p *Provider) ConfigureStorage(req providers.ConfigureStorageRequest) providers.ConfigureStorageResponse {
var resp providers.ConfigureStorageResponse
resp.Diagnostics = resp.Diagnostics.Append(fmt.Errorf("Error: unsupported storage type %s", req.TypeName))
return resp
}
1 change: 1 addition & 0 deletions internal/command/testing/test_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ var (
ReturnType: cty.Bool,
},
},
// TODO - add a State Stores map here?
}
)

Expand Down
53 changes: 53 additions & 0 deletions internal/grpcwrap/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ func (p *provider) GetSchema(_ context.Context, req *tfplugin5.GetProviderSchema
ResourceSchemas: make(map[string]*tfplugin5.Schema),
DataSourceSchemas: make(map[string]*tfplugin5.Schema),
EphemeralResourceSchemas: make(map[string]*tfplugin5.Schema),
StateStoreSchemas: make(map[string]*tfplugin5.Schema),
}

resp.Provider = &tfplugin5.Schema{
Expand Down Expand Up @@ -73,6 +74,18 @@ func (p *provider) GetSchema(_ context.Context, req *tfplugin5.GetProviderSchema
Block: convert.ConfigSchemaToProto(dat.Body),
}
}
for typ, dat := range p.schema.EphemeralResourceTypes {
resp.EphemeralResourceSchemas[typ] = &tfplugin5.Schema{
Version: int64(dat.Version),
Block: convert.ConfigSchemaToProto(dat.Body),
}
}
for typ, dat := range p.schema.StateStoreSchemas {
resp.StateStoreSchemas[typ] = &tfplugin5.Schema{
Version: int64(dat.Version),
Block: convert.ConfigSchemaToProto(dat.Body),
}
}
if decls, err := convert.FunctionDeclsToProto(p.schema.Functions); err == nil {
resp.Functions = decls
} else {
Expand Down Expand Up @@ -730,6 +743,46 @@ func (p *provider) UpgradeResourceIdentity(_ context.Context, req *tfplugin5.Upg
return resp, nil
}

func (p *provider) ValidateStorageConfig(ctx context.Context, req *tfplugin5.ValidateStorage_Request) (*tfplugin5.ValidateStorage_Response, error) {
// TODO
return nil, nil
}

func (p *provider) ConfigureStorage(ctx context.Context, req *tfplugin5.ConfigureStorage_Request) (*tfplugin5.ConfigureStorage_Response, error) {
// TODO
return nil, nil
}

func (p *provider) ReadState(req *tfplugin5.ReadState_Request, srv tfplugin5.Provider_ReadStateServer) error {
// TODO
return nil
}

func (p *provider) WriteState(srv tfplugin5.Provider_WriteStateServer) error {
// TODO
return nil
}

func (p *provider) LockState(ctx context.Context, req *tfplugin5.LockState_Request) (*tfplugin5.LockState_Response, error) {
// TODO
return nil, nil
}

func (p *provider) UnlockState(ctx context.Context, req *tfplugin5.UnlockState_Request) (*tfplugin5.UnlockState_Response, error) {
// TODO
return nil, nil
}

func (p *provider) GetStates(ctx context.Context, req *tfplugin5.GetStates_Request) (*tfplugin5.GetStates_Response, error) {
// TODO
return nil, nil
}

func (p *provider) DeleteState(ctx context.Context, req *tfplugin5.DeleteState_Request) (*tfplugin5.DeleteState_Response, error) {
// TODO
return nil, nil
}

func (p *provider) Stop(context.Context, *tfplugin5.Stop_Request) (*tfplugin5.Stop_Response, error) {
resp := &tfplugin5.Stop_Response{}
err := p.provider.Stop()
Expand Down
47 changes: 47 additions & 0 deletions internal/grpcwrap/provider6.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ func (p *provider6) GetProviderSchema(_ context.Context, req *tfplugin6.GetProvi
DataSourceSchemas: make(map[string]*tfplugin6.Schema),
EphemeralResourceSchemas: make(map[string]*tfplugin6.Schema),
Functions: make(map[string]*tfplugin6.Function),
StateStoreSchemas: make(map[string]*tfplugin6.Schema),
}

resp.Provider = &tfplugin6.Schema{
Expand Down Expand Up @@ -81,6 +82,12 @@ func (p *provider6) GetProviderSchema(_ context.Context, req *tfplugin6.GetProvi
Block: convert.ConfigSchemaToProto(dat.Body),
}
}
for typ, dat := range p.schema.StateStoreSchemas {
resp.StateStoreSchemas[typ] = &tfplugin6.Schema{
Version: int64(dat.Version),
Block: convert.ConfigSchemaToProto(dat.Body),
}
}
if decls, err := convert.FunctionDeclsToProto(p.schema.Functions); err == nil {
resp.Functions = decls
} else {
Expand Down Expand Up @@ -784,6 +791,46 @@ func (p *provider6) UpgradeResourceIdentity(_ context.Context, req *tfplugin6.Up
return resp, nil
}

func (p *provider6) ValidateStorageConfig(ctx context.Context, req *tfplugin6.ValidateStorage_Request) (*tfplugin6.ValidateStorage_Response, error) {
// TODO
return nil, nil
}

func (p *provider6) ConfigureStorage(ctx context.Context, req *tfplugin6.ConfigureStorage_Request) (*tfplugin6.ConfigureStorage_Response, error) {
// TODO
return nil, nil
}

func (p *provider6) ReadState(req *tfplugin6.ReadState_Request, srv tfplugin6.Provider_ReadStateServer) error {
// TODO
return nil
}

func (p *provider6) WriteState(srv tfplugin6.Provider_WriteStateServer) error {
// TODO
return nil
}

func (p *provider6) LockState(ctx context.Context, req *tfplugin6.LockState_Request) (*tfplugin6.LockState_Response, error) {
// TODO
return nil, nil
}

func (p *provider6) UnlockState(ctx context.Context, req *tfplugin6.UnlockState_Request) (*tfplugin6.UnlockState_Response, error) {
// TODO
return nil, nil
}

func (p *provider6) GetStates(ctx context.Context, req *tfplugin6.GetStates_Request) (*tfplugin6.GetStates_Response, error) {
// TODO
return nil, nil
}

func (p *provider6) DeleteState(ctx context.Context, req *tfplugin6.DeleteState_Request) (*tfplugin6.DeleteState_Response, error) {
// TODO
return nil, nil
}

func (p *provider6) StopProvider(context.Context, *tfplugin6.StopProvider_Request) (*tfplugin6.StopProvider_Response, error) {
resp := &tfplugin6.StopProvider_Response{}
err := p.provider.Stop()
Expand Down
53 changes: 53 additions & 0 deletions internal/plugin/grpc_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ func (p *GRPCProviderPlugin) GRPCServer(broker *plugin.GRPCBroker, s *grpc.Serve
return nil
}

var _ providers.Interface = &GRPCProvider{}

// GRPCProvider handles the client, or core side of the plugin rpc connection.
// The GRPCProvider methods are mostly a translation layer between the
// terraform providers types and the grpc proto types, directly converting
Expand Down Expand Up @@ -101,6 +103,7 @@ func (p *GRPCProvider) GetProviderSchema() providers.GetProviderSchemaResponse {
resp.ResourceTypes = make(map[string]providers.Schema)
resp.DataSources = make(map[string]providers.Schema)
resp.EphemeralResourceTypes = make(map[string]providers.Schema)
resp.StateStores = make(map[string]providers.Schema)

// Some providers may generate quite large schemas, and the internal default
// grpc response size limit is 4MB. 64MB should cover most any use case, and
Expand Down Expand Up @@ -162,6 +165,11 @@ func (p *GRPCProvider) GetProviderSchema() providers.GetProviderSchemaResponse {
resp.EphemeralResourceTypes[name] = convert.ProtoToProviderSchema(ephem, nil)
}

// TODO - update provider schema response
// for name, store := range protoResp.StateStorageSchemas {
// resp.StateStorageTypes[name] = convert.ProtoToProviderSchema(store, nil)
// }

if decls, err := convert.FunctionDeclsFromProto(protoResp.Functions); err == nil {
resp.Functions = decls
} else {
Expand Down Expand Up @@ -1205,6 +1213,46 @@ func (p *GRPCProvider) CallFunction(r providers.CallFunctionRequest) (resp provi
return resp
}

func (p *GRPCProvider) ConfigureStorage(r providers.ConfigureStorageRequest) (resp providers.ConfigureStorageResponse) {
logger.Trace("GRPCProvider: ConfigureStorage")

schema := p.GetProviderSchema()
if schema.Diagnostics.HasErrors() {
resp.Diagnostics = schema.Diagnostics
return resp
}

beSchema, ok := schema.StateStores[r.TypeName]
if !ok {
resp.Diagnostics = resp.Diagnostics.Append(fmt.Errorf("unknown storage type %q", r.TypeName))
return resp
}

var mp []byte

// we don't have anything to marshal if there's no config
mp, err := msgpack.Marshal(r.Config, beSchema.Body.ImpliedType())
if err != nil {
resp.Diagnostics = resp.Diagnostics.Append(err)
return resp
}

protoReq := &proto.ConfigureStorage_Request{
TypeName: r.TypeName,
PreparedConfig: &proto.DynamicValue{
Msgpack: mp,
},
}

protoResp, err := p.client.ConfigureStorage(p.ctx, protoReq)
if err != nil {
resp.Diagnostics = resp.Diagnostics.Append(grpcErr(err))
return resp
}
resp.Diagnostics = resp.Diagnostics.Append(convert.ProtoToDiagnostics(protoResp.Diagnostics))
return resp
}

// closing the grpc connection is final, and terraform will call it at the end of every phase.
func (p *GRPCProvider) Close() error {
logger.Trace("GRPCProvider: Close")
Expand Down Expand Up @@ -1251,3 +1299,8 @@ func clientCapabilitiesToProto(c providers.ClientCapabilities) *proto.ClientCapa
WriteOnlyAttributesAllowed: c.WriteOnlyAttributesAllowed,
}
}

func (p *GRPCProvider) ValidateStorageConfig(r providers.ValidateStorageConfigRequest) providers.ValidateStorageConfigResponse {
// TODO
return providers.ValidateStorageConfigResponse{}
}
Loading
Loading