github.com/terramate-io/tf@v0.0.0-20230830114523-fce866b4dfcd/command/meta_backend_test.go (about)

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