Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
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
2 changes: 1 addition & 1 deletion internal/command/e2etest/meta_backend_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ func TestMetaBackend_GetStateStoreProviderFactory(t *testing.T) {

// Setup the meta and test GetStateStoreProviderFactory
m := command.Meta{}
factory, diags := m.GetStateStoreProviderFactory(config, locks)
factory, diags := m.StateStoreProviderFactoryFromConfig(config, locks)
if diags.HasErrors() {
t.Fatalf("unexpected error : %s", err)
}
Expand Down
5 changes: 3 additions & 2 deletions internal/command/init_run_experiment.go
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,7 @@ func (c *InitCommand) initPssBackend(ctx context.Context, root *configs.Module,
return nil, true, diags
case root.StateStore != nil:
// state_store config present
factory, fDiags := c.Meta.GetStateStoreProviderFactory(root.StateStore, configLocks)
factory, fDiags := c.Meta.StateStoreProviderFactoryFromConfig(root.StateStore, configLocks)
diags = diags.Append(fDiags)
if fDiags.HasErrors() {
return nil, true, diags
Expand Down Expand Up @@ -439,7 +439,6 @@ func (c *InitCommand) initPssBackend(ctx context.Context, root *configs.Module,
opts = &BackendOpts{
StateStoreConfig: root.StateStore,
Locks: configLocks,
ProviderFactory: factory,
CreateDefaultWorkspace: initArgs.CreateDefaultWorkspace,
ConfigOverride: configOverride,
Init: true,
Expand Down Expand Up @@ -492,6 +491,7 @@ func (c *InitCommand) initPssBackend(ctx context.Context, root *configs.Module,

opts = &BackendOpts{
BackendConfig: backendConfig,
Locks: configLocks,
ConfigOverride: configOverride,
Init: true,
ViewType: initArgs.ViewType,
Expand Down Expand Up @@ -526,6 +526,7 @@ the backend configuration is present and valid.

opts = &BackendOpts{
Init: true,
Locks: configLocks,
ViewType: initArgs.ViewType,
}
}
Expand Down
208 changes: 202 additions & 6 deletions internal/command/init_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
Expand Down Expand Up @@ -524,7 +523,7 @@ func TestInit_backendUnset(t *testing.T) {
log.Printf("[TRACE] TestInit_backendUnset: beginning second init")

// Unset
if err := ioutil.WriteFile("main.tf", []byte(""), 0644); err != nil {
if err := os.WriteFile("main.tf", []byte(""), 0644); err != nil {
t.Fatalf("err: %s", err)
}

Expand Down Expand Up @@ -1144,7 +1143,7 @@ func TestInit_backendReinitConfigToExtra(t *testing.T) {

// init again but remove the path option from the config
cfg := "terraform {\n backend \"local\" {}\n}\n"
if err := ioutil.WriteFile("main.tf", []byte(cfg), 0644); err != nil {
if err := os.WriteFile("main.tf", []byte(cfg), 0644); err != nil {
t.Fatal(err)
}

Expand Down Expand Up @@ -2359,7 +2358,7 @@ func TestInit_providerLockFile(t *testing.T) {
}

lockFile := ".terraform.lock.hcl"
buf, err := ioutil.ReadFile(lockFile)
buf, err := os.ReadFile(lockFile)
if err != nil {
t.Fatalf("failed to read dependency lock file %s: %s", lockFile, err)
}
Expand Down Expand Up @@ -2540,7 +2539,7 @@ provider "registry.terraform.io/hashicorp/test" {

// write input lockfile
lockFile := ".terraform.lock.hcl"
if err := ioutil.WriteFile(lockFile, []byte(tc.input), 0644); err != nil {
if err := os.WriteFile(lockFile, []byte(tc.input), 0644); err != nil {
t.Fatalf("failed to write input lockfile: %s", err)
}

Expand All @@ -2552,7 +2551,7 @@ provider "registry.terraform.io/hashicorp/test" {
t.Fatalf("expected error, got output: \n%s", done(t).Stdout())
}

buf, err := ioutil.ReadFile(lockFile)
buf, err := os.ReadFile(lockFile)
if err != nil {
t.Fatalf("failed to read dependency lock file %s: %s", lockFile, err)
}
Expand Down Expand Up @@ -4018,6 +4017,203 @@ func TestInit_stateStore_providerUpgrade(t *testing.T) {
})
}

func TestInit_stateStore_unset(t *testing.T) {
// Create a temporary working directory that is empty
td := t.TempDir()
testCopyDir(t, testFixturePath("init-state-store"), td)
t.Chdir(td)

mockProvider := mockPluggableStateStorageProvider()
storeName := "test_store"
otherStoreName := "test_otherstore"
// Make the provider report that it contains a 2nd storage implementation with the above name
mockProvider.GetProviderSchemaResponse.StateStores[otherStoreName] = mockProvider.GetProviderSchemaResponse.StateStores[storeName]
mockProviderAddress := addrs.NewDefaultProvider("test")
providerSource, close := newMockProviderSource(t, map[string][]string{
"hashicorp/test": {"1.2.3"}, // Matches provider version in backend state file fixture
})
defer close()

{
log.Printf("[TRACE] TestInit_stateStore_unset: beginning first init")

ui := cli.NewMockUi()
view, done := testView(t)
c := &InitCommand{
Meta: Meta{
testingOverrides: &testingOverrides{
Providers: map[addrs.Provider]providers.Factory{
mockProviderAddress: providers.FactoryFixed(mockProvider),
},
},
ProviderSource: providerSource,
Ui: ui,
View: view,
AllowExperimentalFeatures: true,
},
}

// Init
args := []string{
"-enable-pluggable-state-storage-experiment=true",
}
code := c.Run(args)
testOutput := done(t)
if code != 0 {
t.Fatalf("bad: \n%s", testOutput.All())
}
log.Printf("[TRACE] TestInit_stateStore_unset: first init complete")
t.Logf("First run output:\n%s", testOutput.Stdout())
t.Logf("First run errors:\n%s", testOutput.Stderr())

if _, err := os.Stat(filepath.Join(DefaultDataDir, DefaultStateFilename)); err != nil {
t.Fatalf("err: %s", err)
}
}

{
log.Printf("[TRACE] TestInit_stateStore_unset: beginning second init")

// Unset
if err := os.WriteFile("main.tf", []byte(""), 0644); err != nil {
t.Fatalf("err: %s", err)
}

ui := cli.NewMockUi()
view, done := testView(t)
c := &InitCommand{
Meta: Meta{
testingOverrides: &testingOverrides{
Providers: map[addrs.Provider]providers.Factory{
mockProviderAddress: providers.FactoryFixed(mockProvider),
},
},
ProviderSource: providerSource,
Ui: ui,
View: view,
AllowExperimentalFeatures: true,
},
}

args := []string{
"-enable-pluggable-state-storage-experiment=true",
"-force-copy",
}
code := c.Run(args)
testOutput := done(t)
if code != 0 {
t.Fatalf("bad: \n%s", testOutput.All())
}
log.Printf("[TRACE] TestInit_stateStore_unset: second init complete")
t.Logf("Second run output:\n%s", testOutput.Stdout())
t.Logf("Second run errors:\n%s", testOutput.Stderr())

s := testDataStateRead(t, filepath.Join(DefaultDataDir, DefaultStateFilename))
if !s.StateStore.Empty() {
t.Fatal("should not have StateStore config")
}
}
}

func TestInit_stateStore_unset_withoutProviderRequirements(t *testing.T) {
// Create a temporary working directory that is empty
td := t.TempDir()
testCopyDir(t, testFixturePath("init-state-store"), td)
t.Chdir(td)

mockProvider := mockPluggableStateStorageProvider()
storeName := "test_store"
otherStoreName := "test_otherstore"
// Make the provider report that it contains a 2nd storage implementation with the above name
mockProvider.GetProviderSchemaResponse.StateStores[otherStoreName] = mockProvider.GetProviderSchemaResponse.StateStores[storeName]
mockProviderAddress := addrs.NewDefaultProvider("test")
providerSource, close := newMockProviderSource(t, map[string][]string{
"hashicorp/test": {"1.2.3"}, // Matches provider version in backend state file fixture
})
defer close()

{
log.Printf("[TRACE] TestInit_stateStore_unset_withoutProviderRequirements: beginning first init")

ui := cli.NewMockUi()
view, done := testView(t)
c := &InitCommand{
Meta: Meta{
testingOverrides: &testingOverrides{
Providers: map[addrs.Provider]providers.Factory{
mockProviderAddress: providers.FactoryFixed(mockProvider),
},
},
ProviderSource: providerSource,
Ui: ui,
View: view,
AllowExperimentalFeatures: true,
},
}

// Init
args := []string{
"-enable-pluggable-state-storage-experiment=true",
}
code := c.Run(args)
testOutput := done(t)
if code != 0 {
t.Fatalf("bad: \n%s", testOutput.All())
}
log.Printf("[TRACE] TestInit_stateStore_unset_withoutProviderRequirements: first init complete")
t.Logf("First run output:\n%s", testOutput.Stdout())
t.Logf("First run errors:\n%s", testOutput.Stderr())

if _, err := os.Stat(filepath.Join(DefaultDataDir, DefaultStateFilename)); err != nil {
t.Fatalf("err: %s", err)
}
}
{
log.Printf("[TRACE] TestInit_stateStore_unset_withoutProviderRequirements: beginning second init")
// Unset state store and provider requirements
if err := os.WriteFile("main.tf", []byte(""), 0644); err != nil {
t.Fatalf("err: %s", err)
}
if err := os.WriteFile("providers.tf", []byte(""), 0644); err != nil {
t.Fatalf("err: %s", err)
}

ui := cli.NewMockUi()
view, done := testView(t)
c := &InitCommand{
Meta: Meta{
testingOverrides: &testingOverrides{
Providers: map[addrs.Provider]providers.Factory{
mockProviderAddress: providers.FactoryFixed(mockProvider),
},
},
ProviderSource: providerSource,
Ui: ui,
View: view,
AllowExperimentalFeatures: true,
},
}

args := []string{
"-enable-pluggable-state-storage-experiment=true",
"-force-copy",
}
code := c.Run(args)
testOutput := done(t)
if code != 0 {
t.Fatalf("bad: \n%s", testOutput.All())
}
log.Printf("[TRACE] TestInit_stateStore_unset_withoutProviderRequirements: second init complete")
t.Logf("Second run output:\n%s", testOutput.Stdout())
t.Logf("Second run errors:\n%s", testOutput.Stderr())

s := testDataStateRead(t, filepath.Join(DefaultDataDir, DefaultStateFilename))
if !s.StateStore.Empty() {
t.Fatal("should not have StateStore config")
}
}
}

// newMockProviderSource is a helper to succinctly construct a mock provider
// source that contains a set of packages matching the given provider versions
// that are available for installation (from temporary local files).
Expand Down
Loading