Skip to content

Commit 0882433

Browse files
committed
refactor: Configure state stores through the backend.Backend interface, instead of directly using methods related to RPCs. This requires changing where we call SetStateStoreChunkSize.
1 parent 66b0ee9 commit 0882433

File tree

3 files changed

+61
-96
lines changed

3 files changed

+61
-96
lines changed

internal/backend/pluggable/pluggable.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ package pluggable
55

66
import (
77
"errors"
8+
"fmt"
9+
"log"
810

911
"github.com/hashicorp/terraform/internal/backend"
1012
"github.com/hashicorp/terraform/internal/backend/pluggable/chunks"
@@ -103,6 +105,7 @@ func (p *Pluggable) PrepareConfig(config cty.Value) (cty.Value, tfdiags.Diagnost
103105
//
104106
// Configure implements backend.Backend
105107
func (p *Pluggable) Configure(config cty.Value) tfdiags.Diagnostics {
108+
var diags tfdiags.Diagnostics
106109
req := providers.ConfigureStateStoreRequest{
107110
TypeName: p.typeName,
108111
Config: config,
@@ -112,6 +115,31 @@ func (p *Pluggable) Configure(config cty.Value) tfdiags.Diagnostics {
112115
},
113116
}
114117
resp := p.provider.ConfigureStateStore(req)
118+
diags = diags.Append(resp.Diagnostics)
119+
if diags.HasErrors() {
120+
return diags
121+
}
122+
123+
// Validate the returned value from chunk size negotiation
124+
chunkSize := resp.Capabilities.ChunkSize
125+
if chunkSize == 0 || chunkSize > chunks.MaxStateStoreChunkSize {
126+
diags = diags.Append(fmt.Errorf("Failed to negotiate acceptable chunk size. "+
127+
"Expected size > 0 and <= %d bytes, provider wants %d bytes",
128+
chunks.MaxStateStoreChunkSize, chunkSize,
129+
))
130+
return diags
131+
}
132+
133+
// Negotiated chunk size is valid, so set it in the provider server
134+
// that will use the value for future RPCs to read/write state.
135+
if cs, ok := p.provider.(providers.StateStoreChunkSizeSetter); ok {
136+
cs.SetStateStoreChunkSize(p.typeName, int(chunkSize))
137+
}
138+
log.Printf("[TRACE] Pluggable.Configure: negotiated a chunk size of %v when configuring state store %s",
139+
chunkSize,
140+
p.typeName,
141+
)
142+
115143
return resp.Diagnostics
116144
}
117145

internal/command/meta_backend.go

Lines changed: 28 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ import (
3131
backendInit "github.com/hashicorp/terraform/internal/backend/init"
3232
backendLocal "github.com/hashicorp/terraform/internal/backend/local"
3333
backendPluggable "github.com/hashicorp/terraform/internal/backend/pluggable"
34-
"github.com/hashicorp/terraform/internal/backend/pluggable/chunks"
3534
"github.com/hashicorp/terraform/internal/cloud"
3635
"github.com/hashicorp/terraform/internal/command/arguments"
3736
"github.com/hashicorp/terraform/internal/command/clistate"
@@ -2053,57 +2052,24 @@ func (m *Meta) savedStateStore(sMgr *clistate.LocalState, factory providers.Fact
20532052
return nil, diags
20542053
}
20552054

2056-
// Validate and configure the state store
2057-
//
2058-
// NOTE: there are no marks we need to remove at this point.
2059-
// We haven't added marks since the state store config from the backend state was used
2060-
// because the state store's config isn't going to be presented to the user via terminal output or diags.
2061-
validateStoreResp := provider.ValidateStateStoreConfig(providers.ValidateStateStoreConfigRequest{
2062-
TypeName: s.StateStore.Type,
2063-
Config: stateStoreConfigVal,
2064-
})
2065-
diags = diags.Append(validateStoreResp.Diagnostics)
2066-
if diags.HasErrors() {
2067-
return nil, diags
2068-
}
2069-
2070-
cfgStoreResp := provider.ConfigureStateStore(providers.ConfigureStateStoreRequest{
2071-
TypeName: s.StateStore.Type,
2072-
Config: stateStoreConfigVal,
2073-
Capabilities: providers.StateStoreClientCapabilities{
2074-
ChunkSize: chunks.DefaultStateStoreChunkSize,
2075-
},
2076-
})
2077-
diags = diags.Append(cfgStoreResp.Diagnostics)
2078-
if diags.HasErrors() {
2079-
return nil, diags
2080-
}
2081-
2082-
chunkSize := cfgStoreResp.Capabilities.ChunkSize
2083-
if chunkSize == 0 || chunkSize > chunks.MaxStateStoreChunkSize {
2084-
diags = diags.Append(fmt.Errorf("Failed to negotiate acceptable chunk size. "+
2085-
"Expected size > 0 and <= %d bytes, provider wants %d bytes",
2086-
chunks.MaxStateStoreChunkSize, chunkSize,
2087-
))
2088-
return nil, diags
2089-
}
2090-
2091-
p, ok := provider.(providers.StateStoreChunkSizeSetter)
2092-
if !ok {
2093-
msg := fmt.Sprintf("Unable to set chunk size for provider %s; this is a bug in Terraform - please report it", s.StateStore.Type)
2094-
panic(msg)
2095-
}
2096-
// casting to int here is okay because the number should never exceed int32
2097-
p.SetStateStoreChunkSize(s.StateStore.Type, int(chunkSize))
2098-
2099-
// Now we have a fully configured state store, ready to be used.
2100-
// To make it usable we need to return it in a backend.Backend interface.
2101-
b, err := backendPluggable.NewPluggable(provider, s.StateStore.Type)
2055+
// Now that the provider is configured we can begin using the state store through
2056+
// the backend.Backend interface.
2057+
p, err := backendPluggable.NewPluggable(provider, s.StateStore.Type)
21022058
if err != nil {
21032059
diags = diags.Append(err)
21042060
}
21052061

2106-
return b, diags
2062+
// Validate and configure the state store
2063+
//
2064+
// Note: we do not use the value returned from PrepareConfig for state stores,
2065+
// however that old approach is still used with backends for compatibility reasons.
2066+
_, validateDiags := p.PrepareConfig(stateStoreConfigVal)
2067+
diags = diags.Append(validateDiags)
2068+
2069+
configureDiags := p.Configure(stateStoreConfigVal)
2070+
diags = diags.Append(configureDiags)
2071+
2072+
return p, diags
21072073
}
21082074

21092075
//-------------------------------------------------------------------
@@ -2330,58 +2296,24 @@ func (m *Meta) stateStoreInitFromConfig(c *configs.StateStore, factory providers
23302296
return nil, cty.NilVal, cty.NilVal, diags
23312297
}
23322298

2333-
// Validate state store config and configure the state store
2334-
//
2335-
// NOTE: there are no marks we need to remove at this point.
2336-
// We haven't added marks since the provider config from the backend state was used
2337-
// because the state-storage provider's config isn't going to be presented to the user via terminal output or diags.
2338-
validateStoreResp := provider.ValidateStateStoreConfig(providers.ValidateStateStoreConfigRequest{
2339-
TypeName: c.Type,
2340-
Config: stateStoreConfigVal,
2341-
})
2342-
diags = diags.Append(validateStoreResp.Diagnostics)
2343-
if validateStoreResp.Diagnostics.HasErrors() {
2344-
return nil, cty.NilVal, cty.NilVal, diags
2345-
}
2346-
2347-
cfgStoreResp := provider.ConfigureStateStore(providers.ConfigureStateStoreRequest{
2348-
TypeName: c.Type,
2349-
Config: stateStoreConfigVal,
2350-
Capabilities: providers.StateStoreClientCapabilities{
2351-
ChunkSize: chunks.DefaultStateStoreChunkSize,
2352-
},
2353-
})
2354-
diags = diags.Append(cfgStoreResp.Diagnostics)
2355-
if cfgStoreResp.Diagnostics.HasErrors() {
2356-
return nil, cty.NilVal, cty.NilVal, diags
2357-
}
2358-
2359-
chunkSize := cfgStoreResp.Capabilities.ChunkSize
2360-
if chunkSize == 0 || chunkSize > chunks.MaxStateStoreChunkSize {
2361-
diags = diags.Append(fmt.Errorf("Failed to negotiate acceptable chunk size. "+
2362-
"Expected size > 0 and <= %d bytes, provider wants %d bytes",
2363-
chunks.MaxStateStoreChunkSize, chunkSize,
2364-
))
2365-
return nil, cty.NilVal, cty.NilVal, diags
2366-
}
2367-
2368-
p, ok := provider.(providers.StateStoreChunkSizeSetter)
2369-
if !ok {
2370-
msg := fmt.Sprintf("Unable to set chunk size for provider %s; this is a bug in Terraform - please report it", c.Type)
2371-
panic(msg)
2372-
}
2373-
// casting to int here is okay because the number should never exceed int32
2374-
p.SetStateStoreChunkSize(c.Type, int(chunkSize))
2375-
2376-
// Now we have a fully configured state store, ready to be used.
2377-
// To make it usable we need to return it in a backend.Backend interface.
2378-
b, err := backendPluggable.NewPluggable(provider, c.Type)
2299+
// Now that the provider is configured we can begin using the state store through
2300+
// the backend.Backend interface.
2301+
p, err := backendPluggable.NewPluggable(provider, c.Type)
23792302
if err != nil {
23802303
diags = diags.Append(err)
2381-
return nil, cty.NilVal, cty.NilVal, diags
23822304
}
23832305

2384-
return b, stateStoreConfigVal, providerConfigVal, diags
2306+
// Validate and configure the state store
2307+
//
2308+
// Note: we do not use the value returned from PrepareConfig for state stores,
2309+
// however that old approach is still used with backends for compatibility reasons.
2310+
_, validateDiags := p.PrepareConfig(stateStoreConfigVal)
2311+
diags = diags.Append(validateDiags)
2312+
2313+
configureDiags := p.Configure(stateStoreConfigVal)
2314+
diags = diags.Append(configureDiags)
2315+
2316+
return p, stateStoreConfigVal, providerConfigVal, diags
23852317
}
23862318

23872319
// Helper method to get aliases from the enhanced backend and alias them

internal/plugin6/grpc_provider.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1520,6 +1520,11 @@ func (p *GRPCProvider) ConfigureStateStore(r providers.ConfigureStateStoreReques
15201520
logger.Trace("GRPCProvider.v6: ConfigureStateStore: received server capabilities", resp.Capabilities)
15211521

15221522
resp.Diagnostics = resp.Diagnostics.Append(convert.ProtoToDiagnostics(protoResp.Diagnostics))
1523+
1524+
// Note: validation of chunk size will happen in the calling code, and if the data is valid
1525+
// (p *GRPCProvider) SetStateStoreChunkSize should be used to make the value accessible in
1526+
// the instance of GRPCProvider.
1527+
15231528
return resp
15241529
}
15251530

0 commit comments

Comments
 (0)