Skip to content

Commit e0dc01d

Browse files
committed
Remove BackendOpts.ProviderFactory abstraction layer
1 parent 078ac7c commit e0dc01d

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
@@ -74,18 +74,9 @@ type BackendOpts struct {
7474
// the root module, or nil if no such block is present.
7575
StateStoreConfig *configs.StateStore
7676

77-
// ProvidersFactory contains a factory for creating instances of the
78-
// provider used for pluggable state storage. Each call created a new instance,
79-
// so be conscious of when the provider needs to be configured, etc.
80-
//
81-
// This will only be set if the configuration contains a state_store block.
82-
ProviderFactory providers.Factory
83-
8477
// Locks allows state-migration logic to detect when the provider used for pluggable state storage
8578
// during the last init (i.e. what's in the backend state file) is mismatched with the provider
8679
// version in use currently.
87-
//
88-
// This will only be set if the configuration contains a state_store block.
8980
Locks *depsfile.Locks
9081

9182
// ConfigOverride is an hcl.Body that, if non-nil, will be used with
@@ -591,16 +582,13 @@ func (m *Meta) stateStoreConfig(opts *BackendOpts) (*configs.StateStore, int, tf
591582
return nil, 0, diags
592583
}
593584

594-
// Check - is the state store type in the config supported by the provider?
595-
if opts.ProviderFactory == nil {
596-
diags = diags.Append(&hcl.Diagnostic{
597-
Severity: hcl.DiagError,
598-
Summary: "Missing provider details when configuring state store",
599-
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.",
600-
})
585+
pFactory, pDiags := m.GetStateStoreProviderFactory(opts.StateStoreConfig, opts.Locks)
586+
diags = diags.Append(pDiags)
587+
if pDiags.HasErrors() {
601588
return nil, 0, diags
602589
}
603-
provider, err := opts.ProviderFactory()
590+
591+
provider, err := pFactory()
604592
if err != nil {
605593
diags = diags.Append(fmt.Errorf("error when obtaining provider instance during state store initialization: %w", err))
606594
return nil, 0, diags
@@ -955,7 +943,7 @@ func (m *Meta) backendFromConfig(opts *BackendOpts) (backend.Backend, tfdiags.Di
955943
// AND we're not providing any overrides. An override can mean a change overriding an unchanged backend block (indicated by the hash value).
956944
if (uint64(cHash) == s.StateStore.Hash) && (!opts.Init || opts.ConfigOverride == nil) {
957945
log.Printf("[TRACE] Meta.Backend: using already-initialized, unchanged %q state_store configuration", stateStoreConfig.Type)
958-
savedStateStore, sssDiags := m.savedStateStore(sMgr, opts.ProviderFactory)
946+
savedStateStore, sssDiags := m.savedStateStore(sMgr)
959947
diags = diags.Append(sssDiags)
960948
// Verify that selected workspace exist. Otherwise prompt user to create one
961949
if opts.Init && savedStateStore != nil {
@@ -1601,43 +1589,37 @@ func (m *Meta) backend(configPath string, viewType arguments.ViewType) (backendr
16011589
return nil, diags
16021590
}
16031591

1592+
locks, lDiags := m.lockedDependencies()
1593+
diags = diags.Append(lDiags)
1594+
if lDiags.HasErrors() {
1595+
return nil, diags
1596+
}
1597+
16041598
var opts *BackendOpts
16051599
switch {
16061600
case root.Backend != nil:
16071601
opts = &BackendOpts{
16081602
BackendConfig: root.Backend,
1603+
Locks: locks,
16091604
ViewType: viewType,
16101605
}
16111606
case root.CloudConfig != nil:
16121607
backendConfig := root.CloudConfig.ToBackendConfig()
16131608
opts = &BackendOpts{
16141609
BackendConfig: &backendConfig,
1610+
Locks: locks,
16151611
ViewType: viewType,
16161612
}
16171613
case root.StateStore != nil:
1618-
// In addition to config, use of a state_store requires
1619-
// provider factory and provider locks data
1620-
locks, lDiags := m.lockedDependencies()
1621-
diags = diags.Append(lDiags)
1622-
if lDiags.HasErrors() {
1623-
return nil, diags
1624-
}
1625-
1626-
factory, fDiags := m.GetStateStoreProviderFactory(root.StateStore, locks)
1627-
diags = diags.Append(fDiags)
1628-
if fDiags.HasErrors() {
1629-
return nil, diags
1630-
}
1631-
16321614
opts = &BackendOpts{
16331615
StateStoreConfig: root.StateStore,
1634-
ProviderFactory: factory,
16351616
Locks: locks,
16361617
ViewType: viewType,
16371618
}
16381619
default:
16391620
// there is no config; defaults to local state storage
16401621
opts = &BackendOpts{
1622+
Locks: locks,
16411623
ViewType: viewType,
16421624
}
16431625
}
@@ -1716,7 +1698,7 @@ func (m *Meta) stateStore_C_s(c *configs.StateStore, stateStoreHash int, backend
17161698
}
17171699

17181700
// Get the state store as an instance of backend.Backend
1719-
b, storeConfigVal, providerConfigVal, moreDiags := m.stateStoreInitFromConfig(c, opts.ProviderFactory)
1701+
b, storeConfigVal, providerConfigVal, moreDiags := m.stateStoreInitFromConfig(c, opts.Locks)
17201702
diags = diags.Append(moreDiags)
17211703
if diags.HasErrors() {
17221704
return nil, diags
@@ -1953,22 +1935,28 @@ func (m *Meta) createDefaultWorkspace(c *configs.StateStore, b backend.Backend)
19531935
}
19541936

19551937
// Initializing a saved state store from the backend state file (aka 'cache file', aka 'legacy state file')
1956-
func (m *Meta) savedStateStore(sMgr *clistate.LocalState, factory providers.Factory) (backend.Backend, tfdiags.Diagnostics) {
1938+
func (m *Meta) savedStateStore(sMgr *clistate.LocalState) (backend.Backend, tfdiags.Diagnostics) {
19571939
// We're preparing a state_store version of backend.Backend.
19581940
//
19591941
// The provider and state store will be configured using the backend state file.
19601942

19611943
var diags tfdiags.Diagnostics
19621944
var b backend.Backend
19631945

1964-
if factory == nil {
1965-
diags = diags.Append(&hcl.Diagnostic{
1966-
Severity: hcl.DiagError,
1967-
Summary: "Missing provider details when configuring state store",
1968-
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.",
1969-
})
1946+
s := sMgr.State()
1947+
1948+
locks, lDiags := m.lockedDependencies()
1949+
diags = diags.Append(lDiags)
1950+
if lDiags.HasErrors() {
19701951
return nil, diags
19711952
}
1953+
1954+
factory, pDiags := m.StateStoreProviderFactoryFromConfigState(s.StateStore, locks)
1955+
diags = diags.Append(pDiags)
1956+
if pDiags.HasErrors() {
1957+
return nil, diags
1958+
}
1959+
19721960
provider, err := factory()
19731961
if err != nil {
19741962
diags = diags.Append(fmt.Errorf("error when obtaining provider instance during state store initialization: %w", err))
@@ -1978,7 +1966,6 @@ func (m *Meta) savedStateStore(sMgr *clistate.LocalState, factory providers.Fact
19781966
// running provider instance inside the returned backend.Backend instance.
19791967
// Stopping the provider process is the responsibility of the calling code.
19801968

1981-
s := sMgr.State()
19821969
resp := provider.GetProviderSchema()
19831970

19841971
if len(resp.StateStores) == 0 {
@@ -2256,17 +2243,15 @@ func (m *Meta) backendInitFromConfig(c *configs.Backend) (backend.Backend, cty.V
22562243
//
22572244
// NOTE: the backend version of this method, `backendInitFromConfig`, prompts users for input if any required fields
22582245
// are missing from the backend config. In `stateStoreInitFromConfig` we don't do this, and instead users will see an error.
2259-
func (m *Meta) stateStoreInitFromConfig(c *configs.StateStore, factory providers.Factory) (backend.Backend, cty.Value, cty.Value, tfdiags.Diagnostics) {
2246+
func (m *Meta) stateStoreInitFromConfig(c *configs.StateStore, locks *depsfile.Locks) (backend.Backend, cty.Value, cty.Value, tfdiags.Diagnostics) {
22602247
var diags tfdiags.Diagnostics
22612248

2262-
if factory == nil {
2263-
diags = diags.Append(&hcl.Diagnostic{
2264-
Severity: hcl.DiagError,
2265-
Summary: "Missing provider details when configuring state store",
2266-
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.",
2267-
})
2249+
factory, pDiags := m.GetStateStoreProviderFactory(c, locks)
2250+
diags = diags.Append(pDiags)
2251+
if pDiags.HasErrors() {
22682252
return nil, cty.NilVal, cty.NilVal, diags
22692253
}
2254+
22702255
provider, err := factory()
22712256
if err != nil {
22722257
diags = diags.Append(fmt.Errorf("error when obtaining provider instance during state store initialization: %w", err))
@@ -2547,6 +2532,56 @@ func (m *Meta) GetStateStoreProviderFactory(config *configs.StateStore, locks *d
25472532
return factory, diags
25482533
}
25492534

2535+
func (m *Meta) StateStoreProviderFactoryFromConfigState(cfgState *workdir.StateStoreConfigState, locks *depsfile.Locks) (providers.Factory, tfdiags.Diagnostics) {
2536+
var diags tfdiags.Diagnostics
2537+
2538+
if cfgState == nil || locks == nil {
2539+
panic(fmt.Sprintf("nil config or nil locks passed to GetStateStoreProviderFactory: config %#v, locks %#v", cfgState, locks))
2540+
}
2541+
2542+
if cfgState.Provider == nil || cfgState.Provider.Source.IsZero() {
2543+
// This should not happen; this data is populated when storing config state
2544+
return nil, diags.Append(&hcl.Diagnostic{
2545+
Severity: hcl.DiagError,
2546+
Summary: "Unknown provider used for state storage",
2547+
Detail: "Terraform could not find the provider used with the state_store. This is a bug in Terraform and should be reported.",
2548+
// Subject: &cfgState.TypeRange,
2549+
})
2550+
}
2551+
2552+
factories, err := m.ProviderFactoriesFromLocks(locks)
2553+
if err != nil {
2554+
// This may happen if the provider isn't present in the provider cache.
2555+
// This should be caught earlier by logic that diffs the config against the backend state file.
2556+
return nil, diags.Append(&hcl.Diagnostic{
2557+
Severity: hcl.DiagError,
2558+
Summary: "Provider unavailable",
2559+
Detail: fmt.Sprintf("Terraform experienced an error when trying to use provider %s (%q) to initialize the %q state store: %s",
2560+
cfgState.Type,
2561+
cfgState.Provider.Source,
2562+
cfgState.Type,
2563+
err),
2564+
// Subject: &cfgState.TypeRange,
2565+
})
2566+
}
2567+
2568+
factory, exists := factories[*cfgState.Provider.Source]
2569+
if !exists {
2570+
return nil, diags.Append(&hcl.Diagnostic{
2571+
Severity: hcl.DiagError,
2572+
Summary: "Provider unavailable",
2573+
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.",
2574+
cfgState.Type,
2575+
cfgState.Provider.Source,
2576+
cfgState.Type,
2577+
),
2578+
// Subject: &cfgState.TypeRange,
2579+
})
2580+
}
2581+
2582+
return factory, diags
2583+
}
2584+
25502585
//-------------------------------------------------------------------
25512586
// Output constants and initialization code
25522587
//-------------------------------------------------------------------

0 commit comments

Comments
 (0)