Skip to content

Commit c052215

Browse files
committed
Remove BackendOpts.ProviderFactory abstraction layer
1 parent f2818db commit c052215

File tree

3 files changed

+203
-161
lines changed

3 files changed

+203
-161
lines changed

internal/command/init_run_experiment.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,6 @@ func (c *InitCommand) initPssBackend(ctx context.Context, root *configs.Module,
439439
opts = &BackendOpts{
440440
StateStoreConfig: root.StateStore,
441441
Locks: configLocks,
442-
ProviderFactory: factory,
443442
CreateDefaultWorkspace: initArgs.CreateDefaultWorkspace,
444443
ConfigOverride: configOverride,
445444
Init: true,
@@ -492,6 +491,7 @@ func (c *InitCommand) initPssBackend(ctx context.Context, root *configs.Module,
492491

493492
opts = &BackendOpts{
494493
BackendConfig: backendConfig,
494+
Locks: configLocks,
495495
ConfigOverride: configOverride,
496496
Init: true,
497497
ViewType: initArgs.ViewType,
@@ -526,6 +526,7 @@ the backend configuration is present and valid.
526526

527527
opts = &BackendOpts{
528528
Init: true,
529+
Locks: configLocks,
529530
ViewType: initArgs.ViewType,
530531
}
531532
}

internal/command/meta_backend.go

Lines changed: 84 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -60,18 +60,9 @@ type BackendOpts struct {
6060
// the root module, or nil if no such block is present.
6161
StateStoreConfig *configs.StateStore
6262

63-
// ProvidersFactory contains a factory for creating instances of the
64-
// provider used for pluggable state storage. Each call created a new instance,
65-
// so be conscious of when the provider needs to be configured, etc.
66-
//
67-
// This will only be set if the configuration contains a state_store block.
68-
ProviderFactory providers.Factory
69-
7063
// Locks allows state-migration logic to detect when the provider used for pluggable state storage
7164
// during the last init (i.e. what's in the backend state file) is mismatched with the provider
7265
// version in use currently.
73-
//
74-
// This will only be set if the configuration contains a state_store block.
7566
Locks *depsfile.Locks
7667

7768
// ConfigOverride is an hcl.Body that, if non-nil, will be used with
@@ -577,16 +568,13 @@ func (m *Meta) stateStoreConfig(opts *BackendOpts) (*configs.StateStore, int, tf
577568
return nil, 0, diags
578569
}
579570

580-
// Check - is the state store type in the config supported by the provider?
581-
if opts.ProviderFactory == nil {
582-
diags = diags.Append(&hcl.Diagnostic{
583-
Severity: hcl.DiagError,
584-
Summary: "Missing provider details when configuring state store",
585-
Detail: "Terraform attempted to configure a state store and no provider factory was available to launch it. This is a bug in Terraform and should be reported.",
586-
})
571+
pFactory, pDiags := m.GetStateStoreProviderFactory(opts.StateStoreConfig, opts.Locks)
572+
diags = diags.Append(pDiags)
573+
if pDiags.HasErrors() {
587574
return nil, 0, diags
588575
}
589-
provider, err := opts.ProviderFactory()
576+
577+
provider, err := pFactory()
590578
if err != nil {
591579
diags = diags.Append(fmt.Errorf("error when obtaining provider instance during state store initialization: %w", err))
592580
return nil, 0, diags
@@ -941,7 +929,7 @@ func (m *Meta) backendFromConfig(opts *BackendOpts) (backend.Backend, tfdiags.Di
941929
// AND we're not providing any overrides. An override can mean a change overriding an unchanged backend block (indicated by the hash value).
942930
if (uint64(cHash) == s.StateStore.Hash) && (!opts.Init || opts.ConfigOverride == nil) {
943931
log.Printf("[TRACE] Meta.Backend: using already-initialized, unchanged %q state_store configuration", stateStoreConfig.Type)
944-
savedStateStore, sssDiags := m.savedStateStore(sMgr, opts.ProviderFactory)
932+
savedStateStore, sssDiags := m.savedStateStore(sMgr)
945933
diags = diags.Append(sssDiags)
946934
// Verify that selected workspace exist. Otherwise prompt user to create one
947935
if opts.Init && savedStateStore != nil {
@@ -1587,43 +1575,37 @@ func (m *Meta) backend(configPath string, viewType arguments.ViewType) (backendr
15871575
return nil, diags
15881576
}
15891577

1578+
locks, lDiags := m.lockedDependencies()
1579+
diags = diags.Append(lDiags)
1580+
if lDiags.HasErrors() {
1581+
return nil, diags
1582+
}
1583+
15901584
var opts *BackendOpts
15911585
switch {
15921586
case root.Backend != nil:
15931587
opts = &BackendOpts{
15941588
BackendConfig: root.Backend,
1589+
Locks: locks,
15951590
ViewType: viewType,
15961591
}
15971592
case root.CloudConfig != nil:
15981593
backendConfig := root.CloudConfig.ToBackendConfig()
15991594
opts = &BackendOpts{
16001595
BackendConfig: &backendConfig,
1596+
Locks: locks,
16011597
ViewType: viewType,
16021598
}
16031599
case root.StateStore != nil:
1604-
// In addition to config, use of a state_store requires
1605-
// provider factory and provider locks data
1606-
locks, lDiags := m.lockedDependencies()
1607-
diags = diags.Append(lDiags)
1608-
if lDiags.HasErrors() {
1609-
return nil, diags
1610-
}
1611-
1612-
factory, fDiags := m.GetStateStoreProviderFactory(root.StateStore, locks)
1613-
diags = diags.Append(fDiags)
1614-
if fDiags.HasErrors() {
1615-
return nil, diags
1616-
}
1617-
16181600
opts = &BackendOpts{
16191601
StateStoreConfig: root.StateStore,
1620-
ProviderFactory: factory,
16211602
Locks: locks,
16221603
ViewType: viewType,
16231604
}
16241605
default:
16251606
// there is no config; defaults to local state storage
16261607
opts = &BackendOpts{
1608+
Locks: locks,
16271609
ViewType: viewType,
16281610
}
16291611
}
@@ -1702,7 +1684,7 @@ func (m *Meta) stateStore_C_s(c *configs.StateStore, stateStoreHash int, backend
17021684
}
17031685

17041686
// Get the state store as an instance of backend.Backend
1705-
b, storeConfigVal, providerConfigVal, moreDiags := m.stateStoreInitFromConfig(c, opts.ProviderFactory)
1687+
b, storeConfigVal, providerConfigVal, moreDiags := m.stateStoreInitFromConfig(c, opts.Locks)
17061688
diags = diags.Append(moreDiags)
17071689
if diags.HasErrors() {
17081690
return nil, diags
@@ -1939,22 +1921,28 @@ func (m *Meta) createDefaultWorkspace(c *configs.StateStore, b backend.Backend)
19391921
}
19401922

19411923
// Initializing a saved state store from the backend state file (aka 'cache file', aka 'legacy state file')
1942-
func (m *Meta) savedStateStore(sMgr *clistate.LocalState, factory providers.Factory) (backend.Backend, tfdiags.Diagnostics) {
1924+
func (m *Meta) savedStateStore(sMgr *clistate.LocalState) (backend.Backend, tfdiags.Diagnostics) {
19431925
// We're preparing a state_store version of backend.Backend.
19441926
//
19451927
// The provider and state store will be configured using the backend state file.
19461928

19471929
var diags tfdiags.Diagnostics
19481930
var b backend.Backend
19491931

1950-
if factory == nil {
1951-
diags = diags.Append(&hcl.Diagnostic{
1952-
Severity: hcl.DiagError,
1953-
Summary: "Missing provider details when configuring state store",
1954-
Detail: "Terraform attempted to configure a state store and no provider factory was available to launch it. This is a bug in Terraform and should be reported.",
1955-
})
1932+
s := sMgr.State()
1933+
1934+
locks, lDiags := m.lockedDependencies()
1935+
diags = diags.Append(lDiags)
1936+
if lDiags.HasErrors() {
19561937
return nil, diags
19571938
}
1939+
1940+
factory, pDiags := m.StateStoreProviderFactoryFromConfigState(s.StateStore, locks)
1941+
diags = diags.Append(pDiags)
1942+
if pDiags.HasErrors() {
1943+
return nil, diags
1944+
}
1945+
19581946
provider, err := factory()
19591947
if err != nil {
19601948
diags = diags.Append(fmt.Errorf("error when obtaining provider instance during state store initialization: %w", err))
@@ -1964,7 +1952,6 @@ func (m *Meta) savedStateStore(sMgr *clistate.LocalState, factory providers.Fact
19641952
// running provider instance inside the returned backend.Backend instance.
19651953
// Stopping the provider process is the responsibility of the calling code.
19661954

1967-
s := sMgr.State()
19681955
resp := provider.GetProviderSchema()
19691956

19701957
if len(resp.StateStores) == 0 {
@@ -2242,17 +2229,15 @@ func (m *Meta) backendInitFromConfig(c *configs.Backend) (backend.Backend, cty.V
22422229
//
22432230
// NOTE: the backend version of this method, `backendInitFromConfig`, prompts users for input if any required fields
22442231
// are missing from the backend config. In `stateStoreInitFromConfig` we don't do this, and instead users will see an error.
2245-
func (m *Meta) stateStoreInitFromConfig(c *configs.StateStore, factory providers.Factory) (backend.Backend, cty.Value, cty.Value, tfdiags.Diagnostics) {
2232+
func (m *Meta) stateStoreInitFromConfig(c *configs.StateStore, locks *depsfile.Locks) (backend.Backend, cty.Value, cty.Value, tfdiags.Diagnostics) {
22462233
var diags tfdiags.Diagnostics
22472234

2248-
if factory == nil {
2249-
diags = diags.Append(&hcl.Diagnostic{
2250-
Severity: hcl.DiagError,
2251-
Summary: "Missing provider details when configuring state store",
2252-
Detail: "Terraform attempted to configure a state store and no provider factory was available to launch it. This is a bug in Terraform and should be reported.",
2253-
})
2235+
factory, pDiags := m.GetStateStoreProviderFactory(c, locks)
2236+
diags = diags.Append(pDiags)
2237+
if pDiags.HasErrors() {
22542238
return nil, cty.NilVal, cty.NilVal, diags
22552239
}
2240+
22562241
provider, err := factory()
22572242
if err != nil {
22582243
diags = diags.Append(fmt.Errorf("error when obtaining provider instance during state store initialization: %w", err))
@@ -2533,6 +2518,56 @@ func (m *Meta) GetStateStoreProviderFactory(config *configs.StateStore, locks *d
25332518
return factory, diags
25342519
}
25352520

2521+
func (m *Meta) StateStoreProviderFactoryFromConfigState(cfgState *workdir.StateStoreConfigState, locks *depsfile.Locks) (providers.Factory, tfdiags.Diagnostics) {
2522+
var diags tfdiags.Diagnostics
2523+
2524+
if cfgState == nil || locks == nil {
2525+
panic(fmt.Sprintf("nil config or nil locks passed to GetStateStoreProviderFactory: config %#v, locks %#v", cfgState, locks))
2526+
}
2527+
2528+
if cfgState.Provider == nil || cfgState.Provider.Source.IsZero() {
2529+
// This should not happen; this data is populated when storing config state
2530+
return nil, diags.Append(&hcl.Diagnostic{
2531+
Severity: hcl.DiagError,
2532+
Summary: "Unknown provider used for state storage",
2533+
Detail: "Terraform could not find the provider used with the state_store. This is a bug in Terraform and should be reported.",
2534+
// Subject: &cfgState.TypeRange,
2535+
})
2536+
}
2537+
2538+
factories, err := m.ProviderFactoriesFromLocks(locks)
2539+
if err != nil {
2540+
// This may happen if the provider isn't present in the provider cache.
2541+
// This should be caught earlier by logic that diffs the config against the backend state file.
2542+
return nil, diags.Append(&hcl.Diagnostic{
2543+
Severity: hcl.DiagError,
2544+
Summary: "Provider unavailable",
2545+
Detail: fmt.Sprintf("Terraform experienced an error when trying to use provider %s (%q) to initialize the %q state store: %s",
2546+
cfgState.Type,
2547+
cfgState.Provider.Source,
2548+
cfgState.Type,
2549+
err),
2550+
// Subject: &cfgState.TypeRange,
2551+
})
2552+
}
2553+
2554+
factory, exists := factories[*cfgState.Provider.Source]
2555+
if !exists {
2556+
return nil, diags.Append(&hcl.Diagnostic{
2557+
Severity: hcl.DiagError,
2558+
Summary: "Provider unavailable",
2559+
Detail: fmt.Sprintf("The provider %s (%q) is required to initialize the %q state store, but the matching provider factory is missing. This is a bug in Terraform and should be reported.",
2560+
cfgState.Type,
2561+
cfgState.Provider.Source,
2562+
cfgState.Type,
2563+
),
2564+
// Subject: &cfgState.TypeRange,
2565+
})
2566+
}
2567+
2568+
return factory, diags
2569+
}
2570+
25362571
//-------------------------------------------------------------------
25372572
// Output constants and initialization code
25382573
//-------------------------------------------------------------------

0 commit comments

Comments
 (0)