github.com/pulumi/terraform@v1.4.0/pkg/command/meta_backend_test.go (about)

     1  package command
     2  
     3  import (
     4  	"io/ioutil"
     5  	"os"
     6  	"path/filepath"
     7  	"reflect"
     8  	"sort"
     9  	"strings"
    10  	"testing"
    11  
    12  	"github.com/pulumi/terraform/pkg/addrs"
    13  	"github.com/pulumi/terraform/pkg/backend"
    14  	"github.com/pulumi/terraform/pkg/configs"
    15  	"github.com/pulumi/terraform/pkg/copy"
    16  	"github.com/pulumi/terraform/pkg/plans"
    17  	"github.com/pulumi/terraform/pkg/states"
    18  	"github.com/pulumi/terraform/pkg/states/statefile"
    19  	"github.com/pulumi/terraform/pkg/states/statemgr"
    20  	"github.com/mitchellh/cli"
    21  	"github.com/zclconf/go-cty/cty"
    22  
    23  	backendInit "github.com/pulumi/terraform/pkg/backend/init"
    24  	backendLocal "github.com/pulumi/terraform/pkg/backend/local"
    25  	backendInmem "github.com/pulumi/terraform/pkg/backend/remote-state/inmem"
    26  )
    27  
    28  // Test empty directory with no config/state creates a local state.
    29  func TestMetaBackend_emptyDir(t *testing.T) {
    30  	// Create a temporary working directory that is empty
    31  	td := t.TempDir()
    32  	os.MkdirAll(td, 0755)
    33  	defer testChdir(t, td)()
    34  
    35  	// Get the backend
    36  	m := testMetaBackend(t, nil)
    37  	b, diags := m.Backend(&BackendOpts{Init: true})
    38  	if diags.HasErrors() {
    39  		t.Fatal(diags.Err())
    40  	}
    41  
    42  	// Write some state
    43  	s, err := b.StateMgr(backend.DefaultStateName)
    44  	if err != nil {
    45  		t.Fatalf("unexpected error: %s", err)
    46  	}
    47  	s.WriteState(testState())
    48  	if err := s.PersistState(nil); err != nil {
    49  		t.Fatalf("unexpected error: %s", err)
    50  	}
    51  
    52  	// Verify it exists where we expect it to
    53  	if isEmptyState(DefaultStateFilename) {
    54  		t.Fatalf("no state was written")
    55  	}
    56  
    57  	// Verify no backup since it was empty to start
    58  	if !isEmptyState(DefaultStateFilename + DefaultBackupExtension) {
    59  		t.Fatal("backup state should be empty")
    60  	}
    61  
    62  	// Verify no backend state was made
    63  	if !isEmptyState(filepath.Join(m.DataDir(), DefaultStateFilename)) {
    64  		t.Fatal("backend state should be empty")
    65  	}
    66  }
    67  
    68  // check for no state. Either the file doesn't exist, or is empty
    69  func isEmptyState(path string) bool {
    70  	fi, err := os.Stat(path)
    71  	if os.IsNotExist(err) {
    72  		return true
    73  	}
    74  
    75  	if fi.Size() == 0 {
    76  		return true
    77  	}
    78  
    79  	return false
    80  }
    81  
    82  // Test a directory with a legacy state and no config continues to
    83  // use the legacy state.
    84  func TestMetaBackend_emptyWithDefaultState(t *testing.T) {
    85  	// Create a temporary working directory that is empty
    86  	td := t.TempDir()
    87  	os.MkdirAll(td, 0755)
    88  	defer testChdir(t, td)()
    89  
    90  	// Write the legacy state
    91  	statePath := DefaultStateFilename
    92  	{
    93  		f, err := os.Create(statePath)
    94  		if err != nil {
    95  			t.Fatalf("err: %s", err)
    96  		}
    97  		err = writeStateForTesting(testState(), f)
    98  		f.Close()
    99  		if err != nil {
   100  			t.Fatalf("err: %s", err)
   101  		}
   102  	}
   103  
   104  	// Get the backend
   105  	m := testMetaBackend(t, nil)
   106  	b, diags := m.Backend(&BackendOpts{Init: true})
   107  	if diags.HasErrors() {
   108  		t.Fatal(diags.Err())
   109  	}
   110  
   111  	// Check the state
   112  	s, err := b.StateMgr(backend.DefaultStateName)
   113  	if err != nil {
   114  		t.Fatalf("unexpected error: %s", err)
   115  	}
   116  	if err := s.RefreshState(); err != nil {
   117  		t.Fatalf("err: %s", err)
   118  	}
   119  	if actual := s.State().String(); actual != testState().String() {
   120  		t.Fatalf("bad: %s", actual)
   121  	}
   122  
   123  	// Verify it exists where we expect it to
   124  	if _, err := os.Stat(DefaultStateFilename); err != nil {
   125  		t.Fatalf("err: %s", err)
   126  	}
   127  
   128  	stateName := filepath.Join(m.DataDir(), DefaultStateFilename)
   129  	if !isEmptyState(stateName) {
   130  		t.Fatal("expected no state at", stateName)
   131  	}
   132  
   133  	// Write some state
   134  	next := testState()
   135  	next.RootModule().SetOutputValue("foo", cty.StringVal("bar"), false)
   136  	s.WriteState(next)
   137  	if err := s.PersistState(nil); err != nil {
   138  		t.Fatalf("unexpected error: %s", err)
   139  	}
   140  
   141  	// Verify a backup was made since we're modifying a pre-existing state
   142  	if isEmptyState(DefaultStateFilename + DefaultBackupExtension) {
   143  		t.Fatal("backup state should not be empty")
   144  	}
   145  }
   146  
   147  // Test an empty directory with an explicit state path (outside the dir)
   148  func TestMetaBackend_emptyWithExplicitState(t *testing.T) {
   149  	// Create a temporary working directory that is empty
   150  	td := t.TempDir()
   151  	os.MkdirAll(td, 0755)
   152  	defer testChdir(t, td)()
   153  
   154  	// Create another directory to store our state
   155  	stateDir := t.TempDir()
   156  	os.MkdirAll(stateDir, 0755)
   157  
   158  	// Write the legacy state
   159  	statePath := filepath.Join(stateDir, "foo")
   160  	{
   161  		f, err := os.Create(statePath)
   162  		if err != nil {
   163  			t.Fatalf("err: %s", err)
   164  		}
   165  		err = writeStateForTesting(testState(), f)
   166  		f.Close()
   167  		if err != nil {
   168  			t.Fatalf("err: %s", err)
   169  		}
   170  	}
   171  
   172  	// Setup the meta
   173  	m := testMetaBackend(t, nil)
   174  	m.statePath = statePath
   175  
   176  	// Get the backend
   177  	b, diags := m.Backend(&BackendOpts{Init: true})
   178  	if diags.HasErrors() {
   179  		t.Fatal(diags.Err())
   180  	}
   181  
   182  	// Check the state
   183  	s, err := b.StateMgr(backend.DefaultStateName)
   184  	if err != nil {
   185  		t.Fatalf("unexpected error: %s", err)
   186  	}
   187  	if err := s.RefreshState(); err != nil {
   188  		t.Fatalf("err: %s", err)
   189  	}
   190  	if actual := s.State().String(); actual != testState().String() {
   191  		t.Fatalf("bad: %s", actual)
   192  	}
   193  
   194  	// Verify neither defaults exist
   195  	if _, err := os.Stat(DefaultStateFilename); err == nil {
   196  		t.Fatal("file should not exist")
   197  	}
   198  
   199  	stateName := filepath.Join(m.DataDir(), DefaultStateFilename)
   200  	if !isEmptyState(stateName) {
   201  		t.Fatal("expected no state at", stateName)
   202  	}
   203  
   204  	// Write some state
   205  	next := testState()
   206  	markStateForMatching(next, "bar") // just any change so it shows as different than before
   207  	s.WriteState(next)
   208  	if err := s.PersistState(nil); err != nil {
   209  		t.Fatalf("unexpected error: %s", err)
   210  	}
   211  
   212  	// Verify a backup was made since we're modifying a pre-existing state
   213  	if isEmptyState(statePath + DefaultBackupExtension) {
   214  		t.Fatal("backup state should not be empty")
   215  	}
   216  }
   217  
   218  // Verify that interpolations result in an error
   219  func TestMetaBackend_configureInterpolation(t *testing.T) {
   220  	// Create a temporary working directory that is empty
   221  	td := t.TempDir()
   222  	testCopyDir(t, testFixturePath("backend-new-interp"), td)
   223  	defer testChdir(t, td)()
   224  
   225  	// Setup the meta
   226  	m := testMetaBackend(t, nil)
   227  
   228  	// Get the backend
   229  	_, err := m.Backend(&BackendOpts{Init: true})
   230  	if err == nil {
   231  		t.Fatal("should error")
   232  	}
   233  }
   234  
   235  // Newly configured backend
   236  func TestMetaBackend_configureNew(t *testing.T) {
   237  	td := t.TempDir()
   238  	testCopyDir(t, testFixturePath("backend-new"), td)
   239  	defer testChdir(t, td)()
   240  
   241  	// Setup the meta
   242  	m := testMetaBackend(t, nil)
   243  
   244  	// Get the backend
   245  	b, diags := m.Backend(&BackendOpts{Init: true})
   246  	if diags.HasErrors() {
   247  		t.Fatal(diags.Err())
   248  	}
   249  
   250  	// Check the state
   251  	s, err := b.StateMgr(backend.DefaultStateName)
   252  	if err != nil {
   253  		t.Fatalf("unexpected error: %s", err)
   254  	}
   255  	if err := s.RefreshState(); err != nil {
   256  		t.Fatalf("unexpected error: %s", err)
   257  	}
   258  	state := s.State()
   259  	if state != nil {
   260  		t.Fatal("state should be nil")
   261  	}
   262  
   263  	// Write some state
   264  	state = states.NewState()
   265  	mark := markStateForMatching(state, "changing")
   266  
   267  	s.WriteState(state)
   268  	if err := s.PersistState(nil); err != nil {
   269  		t.Fatalf("unexpected error: %s", err)
   270  	}
   271  
   272  	// Verify the state is where we expect
   273  	{
   274  		f, err := os.Open("local-state.tfstate")
   275  		if err != nil {
   276  			t.Fatalf("err: %s", err)
   277  		}
   278  		actual, err := statefile.Read(f)
   279  		f.Close()
   280  		if err != nil {
   281  			t.Fatalf("err: %s", err)
   282  		}
   283  
   284  		assertStateHasMarker(t, actual.State, mark)
   285  	}
   286  
   287  	// Verify the default paths don't exist
   288  	if _, err := os.Stat(DefaultStateFilename); err == nil {
   289  		t.Fatal("file should not exist")
   290  	}
   291  
   292  	// Verify a backup doesn't exist
   293  	if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil {
   294  		t.Fatal("file should not exist")
   295  	}
   296  }
   297  
   298  // Newly configured backend with prior local state and no remote state
   299  func TestMetaBackend_configureNewWithState(t *testing.T) {
   300  	// Create a temporary working directory that is empty
   301  	td := t.TempDir()
   302  	testCopyDir(t, testFixturePath("backend-new-migrate"), td)
   303  	defer testChdir(t, td)()
   304  
   305  	// Ask input
   306  	defer testInteractiveInput(t, []string{"yes"})()
   307  
   308  	// Setup the meta
   309  	m := testMetaBackend(t, nil)
   310  
   311  	// This combination should not require the extra -migrate-state flag, since
   312  	// there is no existing backend config
   313  	m.migrateState = false
   314  
   315  	// Get the backend
   316  	b, diags := m.Backend(&BackendOpts{Init: true})
   317  	if diags.HasErrors() {
   318  		t.Fatal(diags.Err())
   319  	}
   320  
   321  	// Check the state
   322  	s, err := b.StateMgr(backend.DefaultStateName)
   323  	if err != nil {
   324  		t.Fatalf("unexpected error: %s", err)
   325  	}
   326  	state, err := statemgr.RefreshAndRead(s)
   327  	if err != nil {
   328  		t.Fatalf("unexpected error: %s", err)
   329  	}
   330  	if state == nil {
   331  		t.Fatal("state is nil")
   332  	}
   333  
   334  	if got, want := testStateMgrCurrentLineage(s), "backend-new-migrate"; got != want {
   335  		t.Fatalf("lineage changed during migration\nnow: %s\nwas: %s", got, want)
   336  	}
   337  
   338  	// Write some state
   339  	state = states.NewState()
   340  	mark := markStateForMatching(state, "changing")
   341  
   342  	if err := statemgr.WriteAndPersist(s, state, nil); err != nil {
   343  		t.Fatalf("unexpected error: %s", err)
   344  	}
   345  
   346  	// Verify the state is where we expect
   347  	{
   348  		f, err := os.Open("local-state.tfstate")
   349  		if err != nil {
   350  			t.Fatalf("err: %s", err)
   351  		}
   352  		actual, err := statefile.Read(f)
   353  		f.Close()
   354  		if err != nil {
   355  			t.Fatalf("err: %s", err)
   356  		}
   357  
   358  		assertStateHasMarker(t, actual.State, mark)
   359  	}
   360  
   361  	// Verify the default paths don't exist
   362  	if !isEmptyState(DefaultStateFilename) {
   363  		data, _ := ioutil.ReadFile(DefaultStateFilename)
   364  
   365  		t.Fatal("state should not exist, but contains:\n", string(data))
   366  	}
   367  
   368  	// Verify a backup does exist
   369  	if isEmptyState(DefaultStateFilename + DefaultBackupExtension) {
   370  		t.Fatal("backup state is empty or missing")
   371  	}
   372  }
   373  
   374  // Newly configured backend with matching local and remote state doesn't prompt
   375  // for copy.
   376  func TestMetaBackend_configureNewWithoutCopy(t *testing.T) {
   377  	// Create a temporary working directory that is empty
   378  	td := t.TempDir()
   379  	testCopyDir(t, testFixturePath("backend-new-migrate"), td)
   380  	defer testChdir(t, td)()
   381  
   382  	if err := copy.CopyFile(DefaultStateFilename, "local-state.tfstate"); err != nil {
   383  		t.Fatal(err)
   384  	}
   385  
   386  	// Setup the meta
   387  	m := testMetaBackend(t, nil)
   388  	m.input = false
   389  
   390  	// init the backend
   391  	_, diags := m.Backend(&BackendOpts{Init: true})
   392  	if diags.HasErrors() {
   393  		t.Fatal(diags.Err())
   394  	}
   395  
   396  	// Verify the state is where we expect
   397  	f, err := os.Open("local-state.tfstate")
   398  	if err != nil {
   399  		t.Fatalf("err: %s", err)
   400  	}
   401  	actual, err := statefile.Read(f)
   402  	f.Close()
   403  	if err != nil {
   404  		t.Fatalf("err: %s", err)
   405  	}
   406  
   407  	if actual.Lineage != "backend-new-migrate" {
   408  		t.Fatalf("incorrect state lineage: %q", actual.Lineage)
   409  	}
   410  
   411  	// Verify the default paths don't exist
   412  	if !isEmptyState(DefaultStateFilename) {
   413  		data, _ := ioutil.ReadFile(DefaultStateFilename)
   414  
   415  		t.Fatal("state should not exist, but contains:\n", string(data))
   416  	}
   417  
   418  	// Verify a backup does exist
   419  	if isEmptyState(DefaultStateFilename + DefaultBackupExtension) {
   420  		t.Fatal("backup state is empty or missing")
   421  	}
   422  }
   423  
   424  // Newly configured backend with prior local state and no remote state,
   425  // but opting to not migrate.
   426  func TestMetaBackend_configureNewWithStateNoMigrate(t *testing.T) {
   427  	// Create a temporary working directory that is empty
   428  	td := t.TempDir()
   429  	testCopyDir(t, testFixturePath("backend-new-migrate"), td)
   430  	defer testChdir(t, td)()
   431  
   432  	// Ask input
   433  	defer testInteractiveInput(t, []string{"no"})()
   434  
   435  	// Setup the meta
   436  	m := testMetaBackend(t, nil)
   437  
   438  	// Get the backend
   439  	b, diags := m.Backend(&BackendOpts{Init: true})
   440  	if diags.HasErrors() {
   441  		t.Fatal(diags.Err())
   442  	}
   443  
   444  	// Check the state
   445  	s, err := b.StateMgr(backend.DefaultStateName)
   446  	if err != nil {
   447  		t.Fatalf("unexpected error: %s", err)
   448  	}
   449  	if err := s.RefreshState(); err != nil {
   450  		t.Fatalf("unexpected error: %s", err)
   451  	}
   452  	if state := s.State(); state != nil {
   453  		t.Fatal("state is not nil")
   454  	}
   455  
   456  	// Verify the default paths don't exist
   457  	if !isEmptyState(DefaultStateFilename) {
   458  		data, _ := ioutil.ReadFile(DefaultStateFilename)
   459  
   460  		t.Fatal("state should not exist, but contains:\n", string(data))
   461  	}
   462  
   463  	// Verify a backup does exist
   464  	if isEmptyState(DefaultStateFilename + DefaultBackupExtension) {
   465  		t.Fatal("backup state is empty or missing")
   466  	}
   467  }
   468  
   469  // Newly configured backend with prior local state and remote state
   470  func TestMetaBackend_configureNewWithStateExisting(t *testing.T) {
   471  	// Create a temporary working directory that is empty
   472  	td := t.TempDir()
   473  	testCopyDir(t, testFixturePath("backend-new-migrate-existing"), td)
   474  	defer testChdir(t, td)()
   475  
   476  	// Setup the meta
   477  	m := testMetaBackend(t, nil)
   478  	// suppress input
   479  	m.forceInitCopy = true
   480  
   481  	// Get the backend
   482  	b, diags := m.Backend(&BackendOpts{Init: true})
   483  	if diags.HasErrors() {
   484  		t.Fatal(diags.Err())
   485  	}
   486  
   487  	// Check the state
   488  	s, err := b.StateMgr(backend.DefaultStateName)
   489  	if err != nil {
   490  		t.Fatalf("unexpected error: %s", err)
   491  	}
   492  	if err := s.RefreshState(); err != nil {
   493  		t.Fatalf("unexpected error: %s", err)
   494  	}
   495  	state := s.State()
   496  	if state == nil {
   497  		t.Fatal("state is nil")
   498  	}
   499  	if got, want := testStateMgrCurrentLineage(s), "local"; got != want {
   500  		t.Fatalf("wrong lineage %q; want %q", got, want)
   501  	}
   502  
   503  	// Write some state
   504  	state = states.NewState()
   505  	mark := markStateForMatching(state, "changing")
   506  
   507  	s.WriteState(state)
   508  	if err := s.PersistState(nil); err != nil {
   509  		t.Fatalf("unexpected error: %s", err)
   510  	}
   511  
   512  	// Verify the state is where we expect
   513  	{
   514  		f, err := os.Open("local-state.tfstate")
   515  		if err != nil {
   516  			t.Fatalf("err: %s", err)
   517  		}
   518  		actual, err := statefile.Read(f)
   519  		f.Close()
   520  		if err != nil {
   521  			t.Fatalf("err: %s", err)
   522  		}
   523  
   524  		assertStateHasMarker(t, actual.State, mark)
   525  	}
   526  
   527  	// Verify the default paths don't exist
   528  	if !isEmptyState(DefaultStateFilename) {
   529  		data, _ := ioutil.ReadFile(DefaultStateFilename)
   530  
   531  		t.Fatal("state should not exist, but contains:\n", string(data))
   532  	}
   533  
   534  	// Verify a backup does exist
   535  	if isEmptyState(DefaultStateFilename + DefaultBackupExtension) {
   536  		t.Fatal("backup state is empty or missing")
   537  	}
   538  }
   539  
   540  // Newly configured backend with prior local state and remote state
   541  func TestMetaBackend_configureNewWithStateExistingNoMigrate(t *testing.T) {
   542  	// Create a temporary working directory that is empty
   543  	td := t.TempDir()
   544  	testCopyDir(t, testFixturePath("backend-new-migrate-existing"), td)
   545  	defer testChdir(t, td)()
   546  
   547  	// Ask input
   548  	defer testInteractiveInput(t, []string{"no"})()
   549  
   550  	// Setup the meta
   551  	m := testMetaBackend(t, nil)
   552  
   553  	// Get the backend
   554  	b, diags := m.Backend(&BackendOpts{Init: true})
   555  	if diags.HasErrors() {
   556  		t.Fatal(diags.Err())
   557  	}
   558  
   559  	// Check the state
   560  	s, err := b.StateMgr(backend.DefaultStateName)
   561  	if err != nil {
   562  		t.Fatalf("unexpected error: %s", err)
   563  	}
   564  	if err := s.RefreshState(); err != nil {
   565  		t.Fatalf("unexpected error: %s", err)
   566  	}
   567  	state := s.State()
   568  	if state == nil {
   569  		t.Fatal("state is nil")
   570  	}
   571  	if testStateMgrCurrentLineage(s) != "remote" {
   572  		t.Fatalf("bad: %#v", state)
   573  	}
   574  
   575  	// Write some state
   576  	state = states.NewState()
   577  	mark := markStateForMatching(state, "changing")
   578  	s.WriteState(state)
   579  	if err := s.PersistState(nil); err != nil {
   580  		t.Fatalf("unexpected error: %s", err)
   581  	}
   582  
   583  	// Verify the state is where we expect
   584  	{
   585  		f, err := os.Open("local-state.tfstate")
   586  		if err != nil {
   587  			t.Fatalf("err: %s", err)
   588  		}
   589  		actual, err := statefile.Read(f)
   590  		f.Close()
   591  		if err != nil {
   592  			t.Fatalf("err: %s", err)
   593  		}
   594  
   595  		assertStateHasMarker(t, actual.State, mark)
   596  	}
   597  
   598  	// Verify the default paths don't exist
   599  	if !isEmptyState(DefaultStateFilename) {
   600  		data, _ := ioutil.ReadFile(DefaultStateFilename)
   601  
   602  		t.Fatal("state should not exist, but contains:\n", string(data))
   603  	}
   604  
   605  	// Verify a backup does exist
   606  	if isEmptyState(DefaultStateFilename + DefaultBackupExtension) {
   607  		t.Fatal("backup state is empty or missing")
   608  	}
   609  }
   610  
   611  // Saved backend state matching config
   612  func TestMetaBackend_configuredUnchanged(t *testing.T) {
   613  	defer testChdir(t, testFixturePath("backend-unchanged"))()
   614  
   615  	// Setup the meta
   616  	m := testMetaBackend(t, nil)
   617  
   618  	// Get the backend
   619  	b, diags := m.Backend(&BackendOpts{Init: true})
   620  	if diags.HasErrors() {
   621  		t.Fatal(diags.Err())
   622  	}
   623  
   624  	// Check the state
   625  	s, err := b.StateMgr(backend.DefaultStateName)
   626  	if err != nil {
   627  		t.Fatalf("unexpected error: %s", err)
   628  	}
   629  	if err := s.RefreshState(); err != nil {
   630  		t.Fatalf("unexpected error: %s", err)
   631  	}
   632  	state := s.State()
   633  	if state == nil {
   634  		t.Fatal("nil state")
   635  	}
   636  	if testStateMgrCurrentLineage(s) != "configuredUnchanged" {
   637  		t.Fatalf("bad: %#v", state)
   638  	}
   639  
   640  	// Verify the default paths don't exist
   641  	if _, err := os.Stat(DefaultStateFilename); err == nil {
   642  		t.Fatal("file should not exist")
   643  	}
   644  
   645  	// Verify a backup doesn't exist
   646  	if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil {
   647  		t.Fatal("file should not exist")
   648  	}
   649  }
   650  
   651  // Changing a configured backend
   652  func TestMetaBackend_configuredChange(t *testing.T) {
   653  	// Create a temporary working directory that is empty
   654  	td := t.TempDir()
   655  	testCopyDir(t, testFixturePath("backend-change"), td)
   656  	defer testChdir(t, td)()
   657  
   658  	// Ask input
   659  	defer testInteractiveInput(t, []string{"no"})()
   660  
   661  	// Setup the meta
   662  	m := testMetaBackend(t, nil)
   663  
   664  	// Get the backend
   665  	b, diags := m.Backend(&BackendOpts{Init: true})
   666  	if diags.HasErrors() {
   667  		t.Fatal(diags.Err())
   668  	}
   669  
   670  	// Check the state
   671  	s, err := b.StateMgr(backend.DefaultStateName)
   672  	if err != nil {
   673  		t.Fatalf("unexpected error: %s", err)
   674  	}
   675  	if err := s.RefreshState(); err != nil {
   676  		t.Fatalf("unexpected error: %s", err)
   677  	}
   678  	state := s.State()
   679  	if state != nil {
   680  		t.Fatal("state should be nil")
   681  	}
   682  
   683  	// Verify the default paths don't exist
   684  	if _, err := os.Stat(DefaultStateFilename); err == nil {
   685  		t.Fatal("file should not exist")
   686  	}
   687  
   688  	// Verify a backup doesn't exist
   689  	if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil {
   690  		t.Fatal("file should not exist")
   691  	}
   692  
   693  	// Write some state
   694  	state = states.NewState()
   695  	mark := markStateForMatching(state, "changing")
   696  
   697  	s.WriteState(state)
   698  	if err := s.PersistState(nil); err != nil {
   699  		t.Fatalf("unexpected error: %s", err)
   700  	}
   701  
   702  	// Verify the state is where we expect
   703  	{
   704  		f, err := os.Open("local-state-2.tfstate")
   705  		if err != nil {
   706  			t.Fatalf("err: %s", err)
   707  		}
   708  		actual, err := statefile.Read(f)
   709  		f.Close()
   710  		if err != nil {
   711  			t.Fatalf("err: %s", err)
   712  		}
   713  
   714  		assertStateHasMarker(t, actual.State, mark)
   715  	}
   716  
   717  	// Verify no local state
   718  	if _, err := os.Stat(DefaultStateFilename); err == nil {
   719  		t.Fatal("file should not exist")
   720  	}
   721  
   722  	// Verify no local backup
   723  	if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil {
   724  		t.Fatal("file should not exist")
   725  	}
   726  }
   727  
   728  // Reconfiguring with an already configured backend.
   729  // This should ignore the existing backend config, and configure the new
   730  // backend is if this is the first time.
   731  func TestMetaBackend_reconfigureChange(t *testing.T) {
   732  	// Create a temporary working directory that is empty
   733  	td := t.TempDir()
   734  	testCopyDir(t, testFixturePath("backend-change-single-to-single"), td)
   735  	defer testChdir(t, td)()
   736  
   737  	// Register the single-state backend
   738  	backendInit.Set("local-single", backendLocal.TestNewLocalSingle)
   739  	defer backendInit.Set("local-single", nil)
   740  
   741  	// Setup the meta
   742  	m := testMetaBackend(t, nil)
   743  
   744  	// this should not ask for input
   745  	m.input = false
   746  
   747  	// cli flag -reconfigure
   748  	m.reconfigure = true
   749  
   750  	// Get the backend
   751  	b, diags := m.Backend(&BackendOpts{Init: true})
   752  	if diags.HasErrors() {
   753  		t.Fatal(diags.Err())
   754  	}
   755  
   756  	// Check the state
   757  	s, err := b.StateMgr(backend.DefaultStateName)
   758  	if err != nil {
   759  		t.Fatalf("unexpected error: %s", err)
   760  	}
   761  	if err := s.RefreshState(); err != nil {
   762  		t.Fatalf("unexpected error: %s", err)
   763  	}
   764  	newState := s.State()
   765  	if newState != nil || !newState.Empty() {
   766  		t.Fatal("state should be nil/empty after forced reconfiguration")
   767  	}
   768  
   769  	// verify that the old state is still there
   770  	s = statemgr.NewFilesystem("local-state.tfstate")
   771  	if err := s.RefreshState(); err != nil {
   772  		t.Fatal(err)
   773  	}
   774  	oldState := s.State()
   775  	if oldState == nil || oldState.Empty() {
   776  		t.Fatal("original state should be untouched")
   777  	}
   778  }
   779  
   780  // Initializing a backend which supports workspaces and does *not* have
   781  // the currently selected workspace should prompt the user with a list of
   782  // workspaces to choose from to select a valid one, if more than one workspace
   783  // is available.
   784  func TestMetaBackend_initSelectedWorkspaceDoesNotExist(t *testing.T) {
   785  	// Create a temporary working directory that is empty
   786  	td := t.TempDir()
   787  	testCopyDir(t, testFixturePath("init-backend-selected-workspace-doesnt-exist-multi"), td)
   788  	defer testChdir(t, td)()
   789  
   790  	// Setup the meta
   791  	m := testMetaBackend(t, nil)
   792  
   793  	defer testInputMap(t, map[string]string{
   794  		"select-workspace": "2",
   795  	})()
   796  
   797  	// Get the backend
   798  	_, diags := m.Backend(&BackendOpts{Init: true})
   799  	if diags.HasErrors() {
   800  		t.Fatal(diags.Err())
   801  	}
   802  
   803  	expected := "foo"
   804  	actual, err := m.Workspace()
   805  	if err != nil {
   806  		t.Fatal(err)
   807  	}
   808  
   809  	if actual != expected {
   810  		t.Fatalf("expected selected workspace to be %q, but was %q", expected, actual)
   811  	}
   812  }
   813  
   814  // Initializing a backend which supports workspaces and does *not* have the
   815  // currently selected workspace - and which only has a single workspace - should
   816  // automatically select that single workspace.
   817  func TestMetaBackend_initSelectedWorkspaceDoesNotExistAutoSelect(t *testing.T) {
   818  	// Create a temporary working directory that is empty
   819  	td := t.TempDir()
   820  	testCopyDir(t, testFixturePath("init-backend-selected-workspace-doesnt-exist-single"), td)
   821  	defer testChdir(t, td)()
   822  
   823  	// Setup the meta
   824  	m := testMetaBackend(t, nil)
   825  
   826  	// this should not ask for input
   827  	m.input = false
   828  
   829  	// Assert test precondition: The current selected workspace is "bar"
   830  	previousName, err := m.Workspace()
   831  	if err != nil {
   832  		t.Fatal(err)
   833  	}
   834  
   835  	if previousName != "bar" {
   836  		t.Fatalf("expected test fixture to start with 'bar' as the current selected workspace")
   837  	}
   838  
   839  	// Get the backend
   840  	_, diags := m.Backend(&BackendOpts{Init: true})
   841  	if diags.HasErrors() {
   842  		t.Fatal(diags.Err())
   843  	}
   844  
   845  	expected := "default"
   846  	actual, err := m.Workspace()
   847  	if err != nil {
   848  		t.Fatal(err)
   849  	}
   850  
   851  	if actual != expected {
   852  		t.Fatalf("expected selected workspace to be %q, but was %q", expected, actual)
   853  	}
   854  }
   855  
   856  // Initializing a backend which supports workspaces and does *not* have
   857  // the currently selected workspace with input=false should fail.
   858  func TestMetaBackend_initSelectedWorkspaceDoesNotExistInputFalse(t *testing.T) {
   859  	// Create a temporary working directory that is empty
   860  	td := t.TempDir()
   861  	testCopyDir(t, testFixturePath("init-backend-selected-workspace-doesnt-exist-multi"), td)
   862  	defer testChdir(t, td)()
   863  
   864  	// Setup the meta
   865  	m := testMetaBackend(t, nil)
   866  	m.input = false
   867  
   868  	// Get the backend
   869  	_, diags := m.Backend(&BackendOpts{Init: true})
   870  
   871  	// Should fail immediately
   872  	if got, want := diags.ErrWithWarnings().Error(), `Currently selected workspace "bar" does not exist`; !strings.Contains(got, want) {
   873  		t.Fatalf("wrong error\ngot:  %s\nwant: %s", got, want)
   874  	}
   875  }
   876  
   877  // Changing a configured backend, copying state
   878  func TestMetaBackend_configuredChangeCopy(t *testing.T) {
   879  	// Create a temporary working directory that is empty
   880  	td := t.TempDir()
   881  	testCopyDir(t, testFixturePath("backend-change"), td)
   882  	defer testChdir(t, td)()
   883  
   884  	// Ask input
   885  	defer testInteractiveInput(t, []string{"yes", "yes"})()
   886  
   887  	// Setup the meta
   888  	m := testMetaBackend(t, nil)
   889  
   890  	// Get the backend
   891  	b, diags := m.Backend(&BackendOpts{Init: true})
   892  	if diags.HasErrors() {
   893  		t.Fatal(diags.Err())
   894  	}
   895  
   896  	// Check the state
   897  	s, err := b.StateMgr(backend.DefaultStateName)
   898  	if err != nil {
   899  		t.Fatalf("unexpected error: %s", err)
   900  	}
   901  	if err := s.RefreshState(); err != nil {
   902  		t.Fatalf("unexpected error: %s", err)
   903  	}
   904  	state := s.State()
   905  	if state == nil {
   906  		t.Fatal("state should not be nil")
   907  	}
   908  	if testStateMgrCurrentLineage(s) != "backend-change" {
   909  		t.Fatalf("bad: %#v", state)
   910  	}
   911  
   912  	// Verify no local state
   913  	if _, err := os.Stat(DefaultStateFilename); err == nil {
   914  		t.Fatal("file should not exist")
   915  	}
   916  
   917  	// Verify no local backup
   918  	if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil {
   919  		t.Fatal("file should not exist")
   920  	}
   921  }
   922  
   923  // Changing a configured backend that supports only single states to another
   924  // backend that only supports single states.
   925  func TestMetaBackend_configuredChangeCopy_singleState(t *testing.T) {
   926  	// Create a temporary working directory that is empty
   927  	td := t.TempDir()
   928  	testCopyDir(t, testFixturePath("backend-change-single-to-single"), td)
   929  	defer testChdir(t, td)()
   930  
   931  	// Register the single-state backend
   932  	backendInit.Set("local-single", backendLocal.TestNewLocalSingle)
   933  	defer backendInit.Set("local-single", nil)
   934  
   935  	// Ask input
   936  	defer testInputMap(t, map[string]string{
   937  		"backend-migrate-copy-to-empty": "yes",
   938  	})()
   939  
   940  	// Setup the meta
   941  	m := testMetaBackend(t, nil)
   942  
   943  	// Get the backend
   944  	b, diags := m.Backend(&BackendOpts{Init: true})
   945  	if diags.HasErrors() {
   946  		t.Fatal(diags.Err())
   947  	}
   948  
   949  	// Check the state
   950  	s, err := b.StateMgr(backend.DefaultStateName)
   951  	if err != nil {
   952  		t.Fatalf("unexpected error: %s", err)
   953  	}
   954  	if err := s.RefreshState(); err != nil {
   955  		t.Fatalf("unexpected error: %s", err)
   956  	}
   957  	state := s.State()
   958  	if state == nil {
   959  		t.Fatal("state should not be nil")
   960  	}
   961  	if testStateMgrCurrentLineage(s) != "backend-change" {
   962  		t.Fatalf("bad: %#v", state)
   963  	}
   964  
   965  	// Verify no local state
   966  	if _, err := os.Stat(DefaultStateFilename); err == nil {
   967  		t.Fatal("file should not exist")
   968  	}
   969  
   970  	// Verify no local backup
   971  	if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil {
   972  		t.Fatal("file should not exist")
   973  	}
   974  }
   975  
   976  // Changing a configured backend that supports multi-state to a
   977  // backend that only supports single states. The multi-state only has
   978  // a default state.
   979  func TestMetaBackend_configuredChangeCopy_multiToSingleDefault(t *testing.T) {
   980  	// Create a temporary working directory that is empty
   981  	td := t.TempDir()
   982  	testCopyDir(t, testFixturePath("backend-change-multi-default-to-single"), td)
   983  	defer testChdir(t, td)()
   984  
   985  	// Register the single-state backend
   986  	backendInit.Set("local-single", backendLocal.TestNewLocalSingle)
   987  	defer backendInit.Set("local-single", nil)
   988  
   989  	// Ask input
   990  	defer testInputMap(t, map[string]string{
   991  		"backend-migrate-copy-to-empty": "yes",
   992  	})()
   993  
   994  	// Setup the meta
   995  	m := testMetaBackend(t, nil)
   996  
   997  	// Get the backend
   998  	b, diags := m.Backend(&BackendOpts{Init: true})
   999  	if diags.HasErrors() {
  1000  		t.Fatal(diags.Err())
  1001  	}
  1002  
  1003  	// Check the state
  1004  	s, err := b.StateMgr(backend.DefaultStateName)
  1005  	if err != nil {
  1006  		t.Fatalf("unexpected error: %s", err)
  1007  	}
  1008  	if err := s.RefreshState(); err != nil {
  1009  		t.Fatalf("unexpected error: %s", err)
  1010  	}
  1011  	state := s.State()
  1012  	if state == nil {
  1013  		t.Fatal("state should not be nil")
  1014  	}
  1015  	if testStateMgrCurrentLineage(s) != "backend-change" {
  1016  		t.Fatalf("bad: %#v", state)
  1017  	}
  1018  
  1019  	// Verify no local state
  1020  	if _, err := os.Stat(DefaultStateFilename); err == nil {
  1021  		t.Fatal("file should not exist")
  1022  	}
  1023  
  1024  	// Verify no local backup
  1025  	if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil {
  1026  		t.Fatal("file should not exist")
  1027  	}
  1028  }
  1029  
  1030  // Changing a configured backend that supports multi-state to a
  1031  // backend that only supports single states.
  1032  func TestMetaBackend_configuredChangeCopy_multiToSingle(t *testing.T) {
  1033  	// Create a temporary working directory that is empty
  1034  	td := t.TempDir()
  1035  	testCopyDir(t, testFixturePath("backend-change-multi-to-single"), td)
  1036  	defer testChdir(t, td)()
  1037  
  1038  	// Register the single-state backend
  1039  	backendInit.Set("local-single", backendLocal.TestNewLocalSingle)
  1040  	defer backendInit.Set("local-single", nil)
  1041  
  1042  	// Ask input
  1043  	defer testInputMap(t, map[string]string{
  1044  		"backend-migrate-multistate-to-single": "yes",
  1045  		"backend-migrate-copy-to-empty":        "yes",
  1046  	})()
  1047  
  1048  	// Setup the meta
  1049  	m := testMetaBackend(t, nil)
  1050  
  1051  	// Get the backend
  1052  	b, diags := m.Backend(&BackendOpts{Init: true})
  1053  	if diags.HasErrors() {
  1054  		t.Fatal(diags.Err())
  1055  	}
  1056  
  1057  	// Check the state
  1058  	s, err := b.StateMgr(backend.DefaultStateName)
  1059  	if err != nil {
  1060  		t.Fatalf("unexpected error: %s", err)
  1061  	}
  1062  	if err := s.RefreshState(); err != nil {
  1063  		t.Fatalf("unexpected error: %s", err)
  1064  	}
  1065  	state := s.State()
  1066  	if state == nil {
  1067  		t.Fatal("state should not be nil")
  1068  	}
  1069  	if testStateMgrCurrentLineage(s) != "backend-change" {
  1070  		t.Fatalf("bad: %#v", state)
  1071  	}
  1072  
  1073  	// Verify no local state
  1074  	if _, err := os.Stat(DefaultStateFilename); err == nil {
  1075  		t.Fatal("file should not exist")
  1076  	}
  1077  
  1078  	// Verify no local backup
  1079  	if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil {
  1080  		t.Fatal("file should not exist")
  1081  	}
  1082  
  1083  	// Verify existing workspaces exist
  1084  	envPath := filepath.Join(backendLocal.DefaultWorkspaceDir, "env2", backendLocal.DefaultStateFilename)
  1085  	if _, err := os.Stat(envPath); err != nil {
  1086  		t.Fatal("env should exist")
  1087  	}
  1088  
  1089  	// Verify we are now in the default env, or we may not be able to access the new backend
  1090  	env, err := m.Workspace()
  1091  	if err != nil {
  1092  		t.Fatal(err)
  1093  	}
  1094  	if env != backend.DefaultStateName {
  1095  		t.Fatal("using non-default env with single-env backend")
  1096  	}
  1097  }
  1098  
  1099  // Changing a configured backend that supports multi-state to a
  1100  // backend that only supports single states.
  1101  func TestMetaBackend_configuredChangeCopy_multiToSingleCurrentEnv(t *testing.T) {
  1102  	// Create a temporary working directory that is empty
  1103  	td := t.TempDir()
  1104  	testCopyDir(t, testFixturePath("backend-change-multi-to-single"), td)
  1105  	defer testChdir(t, td)()
  1106  
  1107  	// Register the single-state backend
  1108  	backendInit.Set("local-single", backendLocal.TestNewLocalSingle)
  1109  	defer backendInit.Set("local-single", nil)
  1110  
  1111  	// Ask input
  1112  	defer testInputMap(t, map[string]string{
  1113  		"backend-migrate-multistate-to-single": "yes",
  1114  		"backend-migrate-copy-to-empty":        "yes",
  1115  	})()
  1116  
  1117  	// Setup the meta
  1118  	m := testMetaBackend(t, nil)
  1119  
  1120  	// Change env
  1121  	if err := m.SetWorkspace("env2"); err != nil {
  1122  		t.Fatalf("unexpected error: %s", err)
  1123  	}
  1124  
  1125  	// Get the backend
  1126  	b, diags := m.Backend(&BackendOpts{Init: true})
  1127  	if diags.HasErrors() {
  1128  		t.Fatal(diags.Err())
  1129  	}
  1130  
  1131  	// Check the state
  1132  	s, err := b.StateMgr(backend.DefaultStateName)
  1133  	if err != nil {
  1134  		t.Fatalf("unexpected error: %s", err)
  1135  	}
  1136  	if err := s.RefreshState(); err != nil {
  1137  		t.Fatalf("unexpected error: %s", err)
  1138  	}
  1139  	state := s.State()
  1140  	if state == nil {
  1141  		t.Fatal("state should not be nil")
  1142  	}
  1143  	if testStateMgrCurrentLineage(s) != "backend-change-env2" {
  1144  		t.Fatalf("bad: %#v", state)
  1145  	}
  1146  
  1147  	// Verify no local state
  1148  	if _, err := os.Stat(DefaultStateFilename); err == nil {
  1149  		t.Fatal("file should not exist")
  1150  	}
  1151  
  1152  	// Verify no local backup
  1153  	if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil {
  1154  		t.Fatal("file should not exist")
  1155  	}
  1156  
  1157  	// Verify existing workspaces exist
  1158  	envPath := filepath.Join(backendLocal.DefaultWorkspaceDir, "env2", backendLocal.DefaultStateFilename)
  1159  	if _, err := os.Stat(envPath); err != nil {
  1160  		t.Fatal("env should exist")
  1161  	}
  1162  }
  1163  
  1164  // Changing a configured backend that supports multi-state to a
  1165  // backend that also supports multi-state.
  1166  func TestMetaBackend_configuredChangeCopy_multiToMulti(t *testing.T) {
  1167  	// Create a temporary working directory that is empty
  1168  	td := t.TempDir()
  1169  	testCopyDir(t, testFixturePath("backend-change-multi-to-multi"), td)
  1170  	defer testChdir(t, td)()
  1171  
  1172  	// Ask input
  1173  	defer testInputMap(t, map[string]string{
  1174  		"backend-migrate-multistate-to-multistate": "yes",
  1175  	})()
  1176  
  1177  	// Setup the meta
  1178  	m := testMetaBackend(t, nil)
  1179  
  1180  	// Get the backend
  1181  	b, diags := m.Backend(&BackendOpts{Init: true})
  1182  	if diags.HasErrors() {
  1183  		t.Fatal(diags.Err())
  1184  	}
  1185  
  1186  	// Check resulting states
  1187  	workspaces, err := b.Workspaces()
  1188  	if err != nil {
  1189  		t.Fatalf("unexpected error: %s", err)
  1190  	}
  1191  
  1192  	sort.Strings(workspaces)
  1193  	expected := []string{"default", "env2"}
  1194  	if !reflect.DeepEqual(workspaces, expected) {
  1195  		t.Fatalf("bad: %#v", workspaces)
  1196  	}
  1197  
  1198  	{
  1199  		// Check the default state
  1200  		s, err := b.StateMgr(backend.DefaultStateName)
  1201  		if err != nil {
  1202  			t.Fatalf("unexpected error: %s", err)
  1203  		}
  1204  		if err := s.RefreshState(); err != nil {
  1205  			t.Fatalf("unexpected error: %s", err)
  1206  		}
  1207  		state := s.State()
  1208  		if state == nil {
  1209  			t.Fatal("state should not be nil")
  1210  		}
  1211  		if testStateMgrCurrentLineage(s) != "backend-change" {
  1212  			t.Fatalf("bad: %#v", state)
  1213  		}
  1214  	}
  1215  
  1216  	{
  1217  		// Check the other state
  1218  		s, err := b.StateMgr("env2")
  1219  		if err != nil {
  1220  			t.Fatalf("unexpected error: %s", err)
  1221  		}
  1222  		if err := s.RefreshState(); err != nil {
  1223  			t.Fatalf("unexpected error: %s", err)
  1224  		}
  1225  		state := s.State()
  1226  		if state == nil {
  1227  			t.Fatal("state should not be nil")
  1228  		}
  1229  		if testStateMgrCurrentLineage(s) != "backend-change-env2" {
  1230  			t.Fatalf("bad: %#v", state)
  1231  		}
  1232  	}
  1233  
  1234  	// Verify no local backup
  1235  	if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil {
  1236  		t.Fatal("file should not exist")
  1237  	}
  1238  
  1239  	{
  1240  		// Verify existing workspaces exist
  1241  		envPath := filepath.Join(backendLocal.DefaultWorkspaceDir, "env2", backendLocal.DefaultStateFilename)
  1242  		if _, err := os.Stat(envPath); err != nil {
  1243  			t.Fatalf("%s should exist, but does not", envPath)
  1244  		}
  1245  	}
  1246  
  1247  	{
  1248  		// Verify new workspaces exist
  1249  		envPath := filepath.Join("envdir-new", "env2", backendLocal.DefaultStateFilename)
  1250  		if _, err := os.Stat(envPath); err != nil {
  1251  			t.Fatalf("%s should exist, but does not", envPath)
  1252  		}
  1253  	}
  1254  }
  1255  
  1256  // Changing a configured backend that supports multi-state to a
  1257  // backend that also supports multi-state, but doesn't allow a
  1258  // default state while the default state is non-empty.
  1259  func TestMetaBackend_configuredChangeCopy_multiToNoDefaultWithDefault(t *testing.T) {
  1260  	// Create a temporary working directory that is empty
  1261  	td := t.TempDir()
  1262  	testCopyDir(t, testFixturePath("backend-change-multi-to-no-default-with-default"), td)
  1263  	defer testChdir(t, td)()
  1264  
  1265  	// Register the single-state backend
  1266  	backendInit.Set("local-no-default", backendLocal.TestNewLocalNoDefault)
  1267  	defer backendInit.Set("local-no-default", nil)
  1268  
  1269  	// Ask input
  1270  	defer testInputMap(t, map[string]string{
  1271  		"backend-migrate-multistate-to-multistate": "yes",
  1272  		"new-state-name": "env1",
  1273  	})()
  1274  
  1275  	// Setup the meta
  1276  	m := testMetaBackend(t, nil)
  1277  
  1278  	// Get the backend
  1279  	b, diags := m.Backend(&BackendOpts{Init: true})
  1280  	if diags.HasErrors() {
  1281  		t.Fatal(diags.Err())
  1282  	}
  1283  
  1284  	// Check resulting states
  1285  	workspaces, err := b.Workspaces()
  1286  	if err != nil {
  1287  		t.Fatalf("unexpected error: %s", err)
  1288  	}
  1289  
  1290  	sort.Strings(workspaces)
  1291  	expected := []string{"env1", "env2"}
  1292  	if !reflect.DeepEqual(workspaces, expected) {
  1293  		t.Fatalf("bad: %#v", workspaces)
  1294  	}
  1295  
  1296  	{
  1297  		// Check the renamed default state
  1298  		s, err := b.StateMgr("env1")
  1299  		if err != nil {
  1300  			t.Fatalf("unexpected error: %s", err)
  1301  		}
  1302  		if err := s.RefreshState(); err != nil {
  1303  			t.Fatalf("unexpected error: %s", err)
  1304  		}
  1305  		state := s.State()
  1306  		if state == nil {
  1307  			t.Fatal("state should not be nil")
  1308  		}
  1309  		if testStateMgrCurrentLineage(s) != "backend-change-env1" {
  1310  			t.Fatalf("bad: %#v", state)
  1311  		}
  1312  	}
  1313  
  1314  	{
  1315  		// Verify existing workspaces exist
  1316  		envPath := filepath.Join(backendLocal.DefaultWorkspaceDir, "env2", backendLocal.DefaultStateFilename)
  1317  		if _, err := os.Stat(envPath); err != nil {
  1318  			t.Fatal("env should exist")
  1319  		}
  1320  	}
  1321  
  1322  	{
  1323  		// Verify new workspaces exist
  1324  		envPath := filepath.Join("envdir-new", "env2", backendLocal.DefaultStateFilename)
  1325  		if _, err := os.Stat(envPath); err != nil {
  1326  			t.Fatal("env should exist")
  1327  		}
  1328  	}
  1329  }
  1330  
  1331  // Changing a configured backend that supports multi-state to a
  1332  // backend that also supports multi-state, but doesn't allow a
  1333  // default state while the default state is empty.
  1334  func TestMetaBackend_configuredChangeCopy_multiToNoDefaultWithoutDefault(t *testing.T) {
  1335  	// Create a temporary working directory that is empty
  1336  	td := t.TempDir()
  1337  	testCopyDir(t, testFixturePath("backend-change-multi-to-no-default-without-default"), td)
  1338  	defer testChdir(t, td)()
  1339  
  1340  	// Register the single-state backend
  1341  	backendInit.Set("local-no-default", backendLocal.TestNewLocalNoDefault)
  1342  	defer backendInit.Set("local-no-default", nil)
  1343  
  1344  	// Ask input
  1345  	defer testInputMap(t, map[string]string{
  1346  		"backend-migrate-multistate-to-multistate": "yes",
  1347  	})()
  1348  
  1349  	// Setup the meta
  1350  	m := testMetaBackend(t, nil)
  1351  
  1352  	// Get the backend
  1353  	b, diags := m.Backend(&BackendOpts{Init: true})
  1354  	if diags.HasErrors() {
  1355  		t.Fatal(diags.Err())
  1356  	}
  1357  
  1358  	// Check resulting states
  1359  	workspaces, err := b.Workspaces()
  1360  	if err != nil {
  1361  		t.Fatalf("unexpected error: %s", err)
  1362  	}
  1363  
  1364  	sort.Strings(workspaces)
  1365  	expected := []string{"env2"} // default is skipped because it is absent in the source backend
  1366  	if !reflect.DeepEqual(workspaces, expected) {
  1367  		t.Fatalf("wrong workspaces\ngot:  %#v\nwant: %#v", workspaces, expected)
  1368  	}
  1369  
  1370  	{
  1371  		// Check the named state
  1372  		s, err := b.StateMgr("env2")
  1373  		if err != nil {
  1374  			t.Fatalf("unexpected error: %s", err)
  1375  		}
  1376  		if err := s.RefreshState(); err != nil {
  1377  			t.Fatalf("unexpected error: %s", err)
  1378  		}
  1379  		state := s.State()
  1380  		if state == nil {
  1381  			t.Fatal("state should not be nil")
  1382  		}
  1383  		if testStateMgrCurrentLineage(s) != "backend-change-env2" {
  1384  			t.Fatalf("bad: %#v", state)
  1385  		}
  1386  	}
  1387  
  1388  	{
  1389  		// Verify existing workspaces exist
  1390  		envPath := filepath.Join(backendLocal.DefaultWorkspaceDir, "env2", backendLocal.DefaultStateFilename)
  1391  		if _, err := os.Stat(envPath); err != nil {
  1392  			t.Fatalf("%s should exist, but does not", envPath)
  1393  		}
  1394  	}
  1395  
  1396  	{
  1397  		// Verify new workspaces exist
  1398  		envPath := filepath.Join("envdir-new", "env2", backendLocal.DefaultStateFilename)
  1399  		if _, err := os.Stat(envPath); err != nil {
  1400  			t.Fatalf("%s should exist, but does not", envPath)
  1401  		}
  1402  	}
  1403  }
  1404  
  1405  // Unsetting a saved backend
  1406  func TestMetaBackend_configuredUnset(t *testing.T) {
  1407  	// Create a temporary working directory that is empty
  1408  	td := t.TempDir()
  1409  	testCopyDir(t, testFixturePath("backend-unset"), td)
  1410  	defer testChdir(t, td)()
  1411  
  1412  	// Ask input
  1413  	defer testInteractiveInput(t, []string{"no"})()
  1414  
  1415  	// Setup the meta
  1416  	m := testMetaBackend(t, nil)
  1417  
  1418  	// Get the backend
  1419  	b, diags := m.Backend(&BackendOpts{Init: true})
  1420  	if diags.HasErrors() {
  1421  		t.Fatal(diags.Err())
  1422  	}
  1423  
  1424  	// Check the state
  1425  	s, err := b.StateMgr(backend.DefaultStateName)
  1426  	if err != nil {
  1427  		t.Fatalf("unexpected error: %s", err)
  1428  	}
  1429  	if err := s.RefreshState(); err != nil {
  1430  		t.Fatalf("unexpected error: %s", err)
  1431  	}
  1432  	state := s.State()
  1433  	if state != nil {
  1434  		t.Fatal("state should be nil")
  1435  	}
  1436  
  1437  	// Verify the default paths don't exist
  1438  	if !isEmptyState(DefaultStateFilename) {
  1439  		data, _ := ioutil.ReadFile(DefaultStateFilename)
  1440  		t.Fatal("state should not exist, but contains:\n", string(data))
  1441  	}
  1442  
  1443  	// Verify a backup doesn't exist
  1444  	if !isEmptyState(DefaultStateFilename + DefaultBackupExtension) {
  1445  		data, _ := ioutil.ReadFile(DefaultStateFilename + DefaultBackupExtension)
  1446  		t.Fatal("backup should not exist, but contains:\n", string(data))
  1447  	}
  1448  
  1449  	// Write some state
  1450  	s.WriteState(testState())
  1451  	if err := s.PersistState(nil); err != nil {
  1452  		t.Fatalf("unexpected error: %s", err)
  1453  	}
  1454  
  1455  	// Verify it exists where we expect it to
  1456  	if isEmptyState(DefaultStateFilename) {
  1457  		t.Fatal(DefaultStateFilename, "is empty")
  1458  	}
  1459  
  1460  	// Verify no backup since it was empty to start
  1461  	if !isEmptyState(DefaultStateFilename + DefaultBackupExtension) {
  1462  		data, _ := ioutil.ReadFile(DefaultStateFilename + DefaultBackupExtension)
  1463  		t.Fatal("backup state should be empty, but contains:\n", string(data))
  1464  	}
  1465  }
  1466  
  1467  // Unsetting a saved backend and copying the remote state
  1468  func TestMetaBackend_configuredUnsetCopy(t *testing.T) {
  1469  	// Create a temporary working directory that is empty
  1470  	td := t.TempDir()
  1471  	testCopyDir(t, testFixturePath("backend-unset"), td)
  1472  	defer testChdir(t, td)()
  1473  
  1474  	// Ask input
  1475  	defer testInteractiveInput(t, []string{"yes", "yes"})()
  1476  
  1477  	// Setup the meta
  1478  	m := testMetaBackend(t, nil)
  1479  
  1480  	// Get the backend
  1481  	b, diags := m.Backend(&BackendOpts{Init: true})
  1482  	if diags.HasErrors() {
  1483  		t.Fatal(diags.Err())
  1484  	}
  1485  
  1486  	// Check the state
  1487  	s, err := b.StateMgr(backend.DefaultStateName)
  1488  	if err != nil {
  1489  		t.Fatalf("unexpected error: %s", err)
  1490  	}
  1491  	if err := s.RefreshState(); err != nil {
  1492  		t.Fatalf("unexpected error: %s", err)
  1493  	}
  1494  	state := s.State()
  1495  	if state == nil {
  1496  		t.Fatal("state is nil")
  1497  	}
  1498  	if got, want := testStateMgrCurrentLineage(s), "configuredUnset"; got != want {
  1499  		t.Fatalf("wrong state lineage %q; want %q", got, want)
  1500  	}
  1501  
  1502  	// Verify a backup doesn't exist
  1503  	if !isEmptyState(DefaultStateFilename + DefaultBackupExtension) {
  1504  		t.Fatalf("backup state should be empty")
  1505  	}
  1506  
  1507  	// Write some state
  1508  	s.WriteState(testState())
  1509  	if err := s.PersistState(nil); err != nil {
  1510  		t.Fatalf("unexpected error: %s", err)
  1511  	}
  1512  
  1513  	// Verify it exists where we expect it to
  1514  	if _, err := os.Stat(DefaultStateFilename); err != nil {
  1515  		t.Fatalf("err: %s", err)
  1516  	}
  1517  
  1518  	// Verify a backup since it wasn't empty to start
  1519  	if isEmptyState(DefaultStateFilename + DefaultBackupExtension) {
  1520  		t.Fatal("backup is empty")
  1521  	}
  1522  }
  1523  
  1524  // A plan that has uses the local backend
  1525  func TestMetaBackend_planLocal(t *testing.T) {
  1526  	// Create a temporary working directory that is empty
  1527  	td := t.TempDir()
  1528  	testCopyDir(t, testFixturePath("backend-plan-local"), td)
  1529  	defer testChdir(t, td)()
  1530  
  1531  	backendConfigBlock := cty.ObjectVal(map[string]cty.Value{
  1532  		"path":          cty.NullVal(cty.String),
  1533  		"workspace_dir": cty.NullVal(cty.String),
  1534  	})
  1535  	backendConfigRaw, err := plans.NewDynamicValue(backendConfigBlock, backendConfigBlock.Type())
  1536  	if err != nil {
  1537  		t.Fatal(err)
  1538  	}
  1539  	backendConfig := plans.Backend{
  1540  		Type:      "local",
  1541  		Config:    backendConfigRaw,
  1542  		Workspace: "default",
  1543  	}
  1544  
  1545  	// Setup the meta
  1546  	m := testMetaBackend(t, nil)
  1547  
  1548  	// Get the backend
  1549  	b, diags := m.BackendForPlan(backendConfig)
  1550  	if diags.HasErrors() {
  1551  		t.Fatal(diags.Err())
  1552  	}
  1553  
  1554  	// Check the state
  1555  	s, err := b.StateMgr(backend.DefaultStateName)
  1556  	if err != nil {
  1557  		t.Fatalf("unexpected error: %s", err)
  1558  	}
  1559  	if err := s.RefreshState(); err != nil {
  1560  		t.Fatalf("unexpected error: %s", err)
  1561  	}
  1562  	state := s.State()
  1563  	if state != nil {
  1564  		t.Fatalf("state should be nil: %#v", state)
  1565  	}
  1566  
  1567  	// The default state file should not exist yet
  1568  	if !isEmptyState(DefaultStateFilename) {
  1569  		t.Fatal("expected empty state")
  1570  	}
  1571  
  1572  	// A backup file shouldn't exist yet either.
  1573  	if !isEmptyState(DefaultStateFilename + DefaultBackupExtension) {
  1574  		t.Fatal("expected empty backup")
  1575  	}
  1576  
  1577  	// Verify we have no configured backend
  1578  	path := filepath.Join(m.DataDir(), DefaultStateFilename)
  1579  	if _, err := os.Stat(path); err == nil {
  1580  		t.Fatalf("should not have backend configured")
  1581  	}
  1582  
  1583  	// Write some state
  1584  	state = states.NewState()
  1585  	mark := markStateForMatching(state, "changing")
  1586  
  1587  	s.WriteState(state)
  1588  	if err := s.PersistState(nil); err != nil {
  1589  		t.Fatalf("unexpected error: %s", err)
  1590  	}
  1591  
  1592  	// Verify the state is where we expect
  1593  	{
  1594  		f, err := os.Open(DefaultStateFilename)
  1595  		if err != nil {
  1596  			t.Fatalf("err: %s", err)
  1597  		}
  1598  		actual, err := statefile.Read(f)
  1599  		f.Close()
  1600  		if err != nil {
  1601  			t.Fatalf("err: %s", err)
  1602  		}
  1603  
  1604  		assertStateHasMarker(t, actual.State, mark)
  1605  	}
  1606  
  1607  	// Verify no local backup
  1608  	if !isEmptyState(DefaultStateFilename + DefaultBackupExtension) {
  1609  		t.Fatalf("backup state should be empty")
  1610  	}
  1611  }
  1612  
  1613  // A plan with a custom state save path
  1614  func TestMetaBackend_planLocalStatePath(t *testing.T) {
  1615  	td := t.TempDir()
  1616  	testCopyDir(t, testFixturePath("backend-plan-local"), td)
  1617  	defer testChdir(t, td)()
  1618  
  1619  	original := testState()
  1620  	markStateForMatching(original, "hello")
  1621  
  1622  	backendConfigBlock := cty.ObjectVal(map[string]cty.Value{
  1623  		"path":          cty.NullVal(cty.String),
  1624  		"workspace_dir": cty.NullVal(cty.String),
  1625  	})
  1626  	backendConfigRaw, err := plans.NewDynamicValue(backendConfigBlock, backendConfigBlock.Type())
  1627  	if err != nil {
  1628  		t.Fatal(err)
  1629  	}
  1630  	plannedBackend := plans.Backend{
  1631  		Type:      "local",
  1632  		Config:    backendConfigRaw,
  1633  		Workspace: "default",
  1634  	}
  1635  
  1636  	// Create an alternate output path
  1637  	statePath := "foo.tfstate"
  1638  
  1639  	// put an initial state there that needs to be backed up
  1640  	err = (statemgr.NewFilesystem(statePath)).WriteState(original)
  1641  	if err != nil {
  1642  		t.Fatal(err)
  1643  	}
  1644  
  1645  	// Setup the meta
  1646  	m := testMetaBackend(t, nil)
  1647  	m.stateOutPath = statePath
  1648  
  1649  	// Get the backend
  1650  	b, diags := m.BackendForPlan(plannedBackend)
  1651  	if diags.HasErrors() {
  1652  		t.Fatal(diags.Err())
  1653  	}
  1654  
  1655  	// Check the state
  1656  	s, err := b.StateMgr(backend.DefaultStateName)
  1657  	if err != nil {
  1658  		t.Fatalf("unexpected error: %s", err)
  1659  	}
  1660  	if err := s.RefreshState(); err != nil {
  1661  		t.Fatalf("unexpected error: %s", err)
  1662  	}
  1663  	state := s.State()
  1664  	if state != nil {
  1665  		t.Fatal("default workspace state is not nil, but should be because we've not put anything there")
  1666  	}
  1667  
  1668  	// Verify the default path doesn't exist
  1669  	if _, err := os.Stat(DefaultStateFilename); err == nil {
  1670  		t.Fatalf("err: %s", err)
  1671  	}
  1672  
  1673  	// Verify a backup doesn't exists
  1674  	if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil {
  1675  		t.Fatal("file should not exist")
  1676  	}
  1677  
  1678  	// Verify we have no configured backend/legacy
  1679  	path := filepath.Join(m.DataDir(), DefaultStateFilename)
  1680  	if _, err := os.Stat(path); err == nil {
  1681  		t.Fatalf("should not have backend configured")
  1682  	}
  1683  
  1684  	// Write some state
  1685  	state = states.NewState()
  1686  	mark := markStateForMatching(state, "changing")
  1687  
  1688  	s.WriteState(state)
  1689  	if err := s.PersistState(nil); err != nil {
  1690  		t.Fatalf("unexpected error: %s", err)
  1691  	}
  1692  
  1693  	// Verify the state is where we expect
  1694  	{
  1695  		f, err := os.Open(statePath)
  1696  		if err != nil {
  1697  			t.Fatalf("err: %s", err)
  1698  		}
  1699  		actual, err := statefile.Read(f)
  1700  		f.Close()
  1701  		if err != nil {
  1702  			t.Fatalf("err: %s", err)
  1703  		}
  1704  
  1705  		assertStateHasMarker(t, actual.State, mark)
  1706  	}
  1707  
  1708  	// Verify we have a backup
  1709  	if isEmptyState(statePath + DefaultBackupExtension) {
  1710  		t.Fatal("backup is empty")
  1711  	}
  1712  }
  1713  
  1714  // A plan that has no backend config, matching local state
  1715  func TestMetaBackend_planLocalMatch(t *testing.T) {
  1716  	// Create a temporary working directory that is empty
  1717  	td := t.TempDir()
  1718  	testCopyDir(t, testFixturePath("backend-plan-local-match"), td)
  1719  	defer testChdir(t, td)()
  1720  
  1721  	backendConfigBlock := cty.ObjectVal(map[string]cty.Value{
  1722  		"path":          cty.NullVal(cty.String),
  1723  		"workspace_dir": cty.NullVal(cty.String),
  1724  	})
  1725  	backendConfigRaw, err := plans.NewDynamicValue(backendConfigBlock, backendConfigBlock.Type())
  1726  	if err != nil {
  1727  		t.Fatal(err)
  1728  	}
  1729  	backendConfig := plans.Backend{
  1730  		Type:      "local",
  1731  		Config:    backendConfigRaw,
  1732  		Workspace: "default",
  1733  	}
  1734  
  1735  	// Setup the meta
  1736  	m := testMetaBackend(t, nil)
  1737  
  1738  	// Get the backend
  1739  	b, diags := m.BackendForPlan(backendConfig)
  1740  	if diags.HasErrors() {
  1741  		t.Fatal(diags.Err())
  1742  	}
  1743  
  1744  	// Check the state
  1745  	s, err := b.StateMgr(backend.DefaultStateName)
  1746  	if err != nil {
  1747  		t.Fatalf("unexpected error: %s", err)
  1748  	}
  1749  	if err := s.RefreshState(); err != nil {
  1750  		t.Fatalf("unexpected error: %s", err)
  1751  	}
  1752  	state := s.State()
  1753  	if state == nil {
  1754  		t.Fatal("should is nil")
  1755  	}
  1756  	if testStateMgrCurrentLineage(s) != "hello" {
  1757  		t.Fatalf("bad: %#v", state)
  1758  	}
  1759  
  1760  	// Verify the default path
  1761  	if isEmptyState(DefaultStateFilename) {
  1762  		t.Fatal("state is empty")
  1763  	}
  1764  
  1765  	// Verify we have no configured backend/legacy
  1766  	path := filepath.Join(m.DataDir(), DefaultStateFilename)
  1767  	if _, err := os.Stat(path); err == nil {
  1768  		t.Fatalf("should not have backend configured")
  1769  	}
  1770  
  1771  	// Write some state
  1772  	state = states.NewState()
  1773  	mark := markStateForMatching(state, "changing")
  1774  
  1775  	s.WriteState(state)
  1776  	if err := s.PersistState(nil); err != nil {
  1777  		t.Fatalf("unexpected error: %s", err)
  1778  	}
  1779  
  1780  	// Verify the state is where we expect
  1781  	{
  1782  		f, err := os.Open(DefaultStateFilename)
  1783  		if err != nil {
  1784  			t.Fatalf("err: %s", err)
  1785  		}
  1786  		actual, err := statefile.Read(f)
  1787  		f.Close()
  1788  		if err != nil {
  1789  			t.Fatalf("err: %s", err)
  1790  		}
  1791  
  1792  		assertStateHasMarker(t, actual.State, mark)
  1793  	}
  1794  
  1795  	// Verify local backup
  1796  	if isEmptyState(DefaultStateFilename + DefaultBackupExtension) {
  1797  		t.Fatal("backup is empty")
  1798  	}
  1799  }
  1800  
  1801  // init a backend using -backend-config options multiple times
  1802  func TestMetaBackend_configureWithExtra(t *testing.T) {
  1803  	// Create a temporary working directory that is empty
  1804  	td := t.TempDir()
  1805  	testCopyDir(t, testFixturePath("init-backend-empty"), td)
  1806  	defer testChdir(t, td)()
  1807  
  1808  	extras := map[string]cty.Value{"path": cty.StringVal("hello")}
  1809  	m := testMetaBackend(t, nil)
  1810  	opts := &BackendOpts{
  1811  		ConfigOverride: configs.SynthBody("synth", extras),
  1812  		Init:           true,
  1813  	}
  1814  
  1815  	_, cHash, err := m.backendConfig(opts)
  1816  	if err != nil {
  1817  		t.Fatal(err)
  1818  	}
  1819  
  1820  	// init the backend
  1821  	_, diags := m.Backend(&BackendOpts{
  1822  		ConfigOverride: configs.SynthBody("synth", extras),
  1823  		Init:           true,
  1824  	})
  1825  	if diags.HasErrors() {
  1826  		t.Fatal(diags.Err())
  1827  	}
  1828  
  1829  	// Check the state
  1830  	s := testDataStateRead(t, filepath.Join(DefaultDataDir, backendLocal.DefaultStateFilename))
  1831  	if s.Backend.Hash != uint64(cHash) {
  1832  		t.Fatal("mismatched state and config backend hashes")
  1833  	}
  1834  
  1835  	// init the backend again with the same options
  1836  	m = testMetaBackend(t, nil)
  1837  	_, err = m.Backend(&BackendOpts{
  1838  		ConfigOverride: configs.SynthBody("synth", extras),
  1839  		Init:           true,
  1840  	})
  1841  	if err != nil {
  1842  		t.Fatalf("unexpected error: %s", err)
  1843  	}
  1844  
  1845  	// Check the state
  1846  	s = testDataStateRead(t, filepath.Join(DefaultDataDir, backendLocal.DefaultStateFilename))
  1847  	if s.Backend.Hash != uint64(cHash) {
  1848  		t.Fatal("mismatched state and config backend hashes")
  1849  	}
  1850  }
  1851  
  1852  // when configuring a default local state, don't delete local state
  1853  func TestMetaBackend_localDoesNotDeleteLocal(t *testing.T) {
  1854  	// Create a temporary working directory that is empty
  1855  	td := t.TempDir()
  1856  	testCopyDir(t, testFixturePath("init-backend-empty"), td)
  1857  	defer testChdir(t, td)()
  1858  
  1859  	// // create our local state
  1860  	orig := states.NewState()
  1861  	orig.Module(addrs.RootModuleInstance).SetOutputValue("foo", cty.StringVal("bar"), false)
  1862  	testStateFileDefault(t, orig)
  1863  
  1864  	m := testMetaBackend(t, nil)
  1865  	m.forceInitCopy = true
  1866  	// init the backend
  1867  	_, diags := m.Backend(&BackendOpts{Init: true})
  1868  	if diags.HasErrors() {
  1869  		t.Fatal(diags.Err())
  1870  	}
  1871  
  1872  	// check that we can read the state
  1873  	s := testStateRead(t, DefaultStateFilename)
  1874  	if s.Empty() {
  1875  		t.Fatal("our state was deleted")
  1876  	}
  1877  }
  1878  
  1879  // move options from config to -backend-config
  1880  func TestMetaBackend_configToExtra(t *testing.T) {
  1881  	// Create a temporary working directory that is empty
  1882  	td := t.TempDir()
  1883  	testCopyDir(t, testFixturePath("init-backend"), td)
  1884  	defer testChdir(t, td)()
  1885  
  1886  	// init the backend
  1887  	m := testMetaBackend(t, nil)
  1888  	_, err := m.Backend(&BackendOpts{
  1889  		Init: true,
  1890  	})
  1891  	if err != nil {
  1892  		t.Fatalf("unexpected error: %s", err)
  1893  	}
  1894  
  1895  	// Check the state
  1896  	s := testDataStateRead(t, filepath.Join(DefaultDataDir, backendLocal.DefaultStateFilename))
  1897  	backendHash := s.Backend.Hash
  1898  
  1899  	// init again but remove the path option from the config
  1900  	cfg := "terraform {\n  backend \"local\" {}\n}\n"
  1901  	if err := ioutil.WriteFile("main.tf", []byte(cfg), 0644); err != nil {
  1902  		t.Fatal(err)
  1903  	}
  1904  
  1905  	// init the backend again with the  options
  1906  	extras := map[string]cty.Value{"path": cty.StringVal("hello")}
  1907  	m = testMetaBackend(t, nil)
  1908  	m.forceInitCopy = true
  1909  	_, diags := m.Backend(&BackendOpts{
  1910  		ConfigOverride: configs.SynthBody("synth", extras),
  1911  		Init:           true,
  1912  	})
  1913  	if diags.HasErrors() {
  1914  		t.Fatal(diags.Err())
  1915  	}
  1916  
  1917  	s = testDataStateRead(t, filepath.Join(DefaultDataDir, backendLocal.DefaultStateFilename))
  1918  
  1919  	if s.Backend.Hash == backendHash {
  1920  		t.Fatal("state.Backend.Hash was not updated")
  1921  	}
  1922  }
  1923  
  1924  // no config; return inmem backend stored in state
  1925  func TestBackendFromState(t *testing.T) {
  1926  	wd := tempWorkingDirFixture(t, "backend-from-state")
  1927  	defer testChdir(t, wd.RootModuleDir())()
  1928  
  1929  	// Setup the meta
  1930  	m := testMetaBackend(t, nil)
  1931  	m.WorkingDir = wd
  1932  	// terraform caches a small "state" file that stores the backend config.
  1933  	// This test must override m.dataDir so it loads the "terraform.tfstate" file in the
  1934  	// test directory as the backend config cache. This fixture is really a
  1935  	// fixture for the data dir rather than the module dir, so we'll override
  1936  	// them to match just for this test.
  1937  	wd.OverrideDataDir(".")
  1938  
  1939  	stateBackend, diags := m.backendFromState()
  1940  	if diags.HasErrors() {
  1941  		t.Fatal(diags.Err())
  1942  	}
  1943  
  1944  	if _, ok := stateBackend.(*backendInmem.Backend); !ok {
  1945  		t.Fatal("did not get expected inmem backend")
  1946  	}
  1947  }
  1948  
  1949  func testMetaBackend(t *testing.T, args []string) *Meta {
  1950  	var m Meta
  1951  	m.Ui = new(cli.MockUi)
  1952  	view, _ := testView(t)
  1953  	m.View = view
  1954  	m.process(args)
  1955  	f := m.extendedFlagSet("test")
  1956  	if err := f.Parse(args); err != nil {
  1957  		t.Fatalf("unexpected error: %s", err)
  1958  	}
  1959  
  1960  	// metaBackend tests are verifying migrate actions
  1961  	m.migrateState = true
  1962  
  1963  	return &m
  1964  }