kubeform.dev/terraform-backend-sdk@v0.0.0-20220310143633-45f07fe731c5/command/state_mv_test.go (about)

     1  package command
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"path/filepath"
     7  	"strings"
     8  	"testing"
     9  
    10  	"github.com/google/go-cmp/cmp"
    11  	"github.com/mitchellh/cli"
    12  
    13  	"kubeform.dev/terraform-backend-sdk/addrs"
    14  	"kubeform.dev/terraform-backend-sdk/states"
    15  )
    16  
    17  func TestStateMv(t *testing.T) {
    18  	state := states.BuildState(func(s *states.SyncState) {
    19  		s.SetResourceInstanceCurrent(
    20  			addrs.Resource{
    21  				Mode: addrs.ManagedResourceMode,
    22  				Type: "test_instance",
    23  				Name: "foo",
    24  			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
    25  			&states.ResourceInstanceObjectSrc{
    26  				AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`),
    27  				Status:    states.ObjectReady,
    28  			},
    29  			addrs.AbsProviderConfig{
    30  				Provider: addrs.NewDefaultProvider("test"),
    31  				Module:   addrs.RootModule,
    32  			},
    33  		)
    34  		s.SetResourceInstanceCurrent(
    35  			addrs.Resource{
    36  				Mode: addrs.ManagedResourceMode,
    37  				Type: "test_instance",
    38  				Name: "baz",
    39  			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
    40  			&states.ResourceInstanceObjectSrc{
    41  				AttrsJSON:    []byte(`{"id":"foo","foo":"value","bar":"value"}`),
    42  				Status:       states.ObjectReady,
    43  				Dependencies: []addrs.ConfigResource{mustResourceAddr("test_instance.foo")},
    44  			},
    45  			addrs.AbsProviderConfig{
    46  				Provider: addrs.NewDefaultProvider("test"),
    47  				Module:   addrs.RootModule,
    48  			},
    49  		)
    50  	})
    51  	statePath := testStateFile(t, state)
    52  
    53  	p := testProvider()
    54  	ui := new(cli.MockUi)
    55  	view, _ := testView(t)
    56  	c := &StateMvCommand{
    57  		StateMeta{
    58  			Meta: Meta{
    59  				testingOverrides: metaOverridesForProvider(p),
    60  				Ui:               ui,
    61  				View:             view,
    62  			},
    63  		},
    64  	}
    65  
    66  	args := []string{
    67  		"-state", statePath,
    68  		"test_instance.foo",
    69  		"test_instance.bar",
    70  	}
    71  	if code := c.Run(args); code != 0 {
    72  		t.Fatalf("return code: %d\n\n%s", code, ui.ErrorWriter.String())
    73  	}
    74  
    75  	// Test it is correct
    76  	testStateOutput(t, statePath, testStateMvOutput)
    77  
    78  	// Test we have backups
    79  	backups := testStateBackups(t, filepath.Dir(statePath))
    80  	if len(backups) != 1 {
    81  		t.Fatalf("bad: %#v", backups)
    82  	}
    83  	testStateOutput(t, backups[0], testStateMvOutputOriginal)
    84  
    85  	// Change the single instance to a counted instance
    86  	args = []string{
    87  		"-state", statePath,
    88  		"test_instance.bar",
    89  		"test_instance.bar[0]",
    90  	}
    91  	if code := c.Run(args); code != 0 {
    92  		t.Fatalf("return code: %d\n\n%s", code, ui.ErrorWriter.String())
    93  	}
    94  
    95  	// extract the resource and verify the mode
    96  	s := testStateRead(t, statePath)
    97  	addr, diags := addrs.ParseAbsResourceStr("test_instance.bar")
    98  	if diags.HasErrors() {
    99  		t.Fatal(diags.Err())
   100  	}
   101  	for key := range s.Resource(addr).Instances {
   102  		if _, ok := key.(addrs.IntKey); !ok {
   103  			t.Fatalf("expected each mode List, got key %q", key)
   104  		}
   105  	}
   106  
   107  	// change from list to map
   108  	args = []string{
   109  		"-state", statePath,
   110  		"test_instance.bar[0]",
   111  		"test_instance.bar[\"baz\"]",
   112  	}
   113  	if code := c.Run(args); code != 0 {
   114  		t.Fatalf("return code: %d\n\n%s", code, ui.ErrorWriter.String())
   115  	}
   116  
   117  	// extract the resource and verify the mode
   118  	s = testStateRead(t, statePath)
   119  	addr, diags = addrs.ParseAbsResourceStr("test_instance.bar")
   120  	if diags.HasErrors() {
   121  		t.Fatal(diags.Err())
   122  	}
   123  	for key := range s.Resource(addr).Instances {
   124  		if _, ok := key.(addrs.StringKey); !ok {
   125  			t.Fatalf("expected each mode map, found key %q", key)
   126  		}
   127  	}
   128  
   129  	// change from from map back to single
   130  	args = []string{
   131  		"-state", statePath,
   132  		"test_instance.bar[\"baz\"]",
   133  		"test_instance.bar",
   134  	}
   135  	if code := c.Run(args); code != 0 {
   136  		t.Fatalf("return code: %d\n\n%s", code, ui.ErrorWriter.String())
   137  	}
   138  
   139  	// extract the resource and verify the mode
   140  	s = testStateRead(t, statePath)
   141  	addr, diags = addrs.ParseAbsResourceStr("test_instance.bar")
   142  	if diags.HasErrors() {
   143  		t.Fatal(diags.Err())
   144  	}
   145  	for key := range s.Resource(addr).Instances {
   146  		if key != addrs.NoKey {
   147  			t.Fatalf("expected no each mode, found key %q", key)
   148  		}
   149  	}
   150  
   151  }
   152  
   153  func TestStateMv_resourceToInstance(t *testing.T) {
   154  	// A single resource (no count defined)
   155  	state := states.BuildState(func(s *states.SyncState) {
   156  		s.SetResourceInstanceCurrent(
   157  			addrs.Resource{
   158  				Mode: addrs.ManagedResourceMode,
   159  				Type: "test_instance",
   160  				Name: "foo",
   161  			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
   162  			&states.ResourceInstanceObjectSrc{
   163  				AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`),
   164  				Status:    states.ObjectReady,
   165  			},
   166  			addrs.AbsProviderConfig{
   167  				Provider: addrs.NewDefaultProvider("test"),
   168  				Module:   addrs.RootModule,
   169  			},
   170  		)
   171  		s.SetResourceInstanceCurrent(
   172  			addrs.Resource{
   173  				Mode: addrs.ManagedResourceMode,
   174  				Type: "test_instance",
   175  				Name: "baz",
   176  			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
   177  			&states.ResourceInstanceObjectSrc{
   178  				AttrsJSON:    []byte(`{"id":"foo","foo":"value","bar":"value"}`),
   179  				Status:       states.ObjectReady,
   180  				Dependencies: []addrs.ConfigResource{mustResourceAddr("test_instance.foo")},
   181  			},
   182  			addrs.AbsProviderConfig{
   183  				Provider: addrs.NewDefaultProvider("test"),
   184  				Module:   addrs.RootModule,
   185  			},
   186  		)
   187  		s.SetResourceProvider(
   188  			addrs.Resource{
   189  				Mode: addrs.ManagedResourceMode,
   190  				Type: "test_instance",
   191  				Name: "bar",
   192  			}.Absolute(addrs.RootModuleInstance),
   193  			addrs.AbsProviderConfig{
   194  				Provider: addrs.NewDefaultProvider("test"),
   195  				Module:   addrs.RootModule,
   196  			},
   197  		)
   198  	})
   199  	statePath := testStateFile(t, state)
   200  
   201  	p := testProvider()
   202  	ui := new(cli.MockUi)
   203  	view, _ := testView(t)
   204  	c := &StateMvCommand{
   205  		StateMeta{
   206  			Meta: Meta{
   207  				testingOverrides: metaOverridesForProvider(p),
   208  				Ui:               ui,
   209  				View:             view,
   210  			},
   211  		},
   212  	}
   213  
   214  	args := []string{
   215  		"-state", statePath,
   216  		"test_instance.foo",
   217  		"test_instance.bar[0]",
   218  	}
   219  	if code := c.Run(args); code != 0 {
   220  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   221  	}
   222  
   223  	// Test it is correct
   224  	testStateOutput(t, statePath, `
   225  test_instance.bar.0:
   226    ID = bar
   227    provider = provider["registry.terraform.io/hashicorp/test"]
   228    bar = value
   229    foo = value
   230  test_instance.baz:
   231    ID = foo
   232    provider = provider["registry.terraform.io/hashicorp/test"]
   233    bar = value
   234    foo = value
   235  `)
   236  
   237  	// Test we have backups
   238  	backups := testStateBackups(t, filepath.Dir(statePath))
   239  	if len(backups) != 1 {
   240  		t.Fatalf("bad: %#v", backups)
   241  	}
   242  	testStateOutput(t, backups[0], testStateMvOutputOriginal)
   243  }
   244  
   245  func TestStateMv_resourceToInstanceErr(t *testing.T) {
   246  	state := states.BuildState(func(s *states.SyncState) {
   247  		s.SetResourceInstanceCurrent(
   248  			addrs.Resource{
   249  				Mode: addrs.ManagedResourceMode,
   250  				Type: "test_instance",
   251  				Name: "foo",
   252  			}.Instance(addrs.IntKey(0)).Absolute(addrs.RootModuleInstance),
   253  			&states.ResourceInstanceObjectSrc{
   254  				AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`),
   255  				Status:    states.ObjectReady,
   256  			},
   257  			addrs.AbsProviderConfig{
   258  				Provider: addrs.NewDefaultProvider("test"),
   259  				Module:   addrs.RootModule,
   260  			},
   261  		)
   262  		s.SetResourceProvider(
   263  			addrs.Resource{
   264  				Mode: addrs.ManagedResourceMode,
   265  				Type: "test_instance",
   266  				Name: "bar",
   267  			}.Absolute(addrs.RootModuleInstance),
   268  			addrs.AbsProviderConfig{
   269  				Provider: addrs.NewDefaultProvider("test"),
   270  				Module:   addrs.RootModule,
   271  			},
   272  		)
   273  	})
   274  	statePath := testStateFile(t, state)
   275  
   276  	p := testProvider()
   277  	ui := cli.NewMockUi()
   278  	view, _ := testView(t)
   279  
   280  	c := &StateMvCommand{
   281  		StateMeta{
   282  			Meta: Meta{
   283  				testingOverrides: metaOverridesForProvider(p),
   284  				Ui:               ui,
   285  				View:             view,
   286  			},
   287  		},
   288  	}
   289  
   290  	args := []string{
   291  		"-state", statePath,
   292  		"test_instance.foo",
   293  		"test_instance.bar[0]",
   294  	}
   295  
   296  	if code := c.Run(args); code == 0 {
   297  		t.Fatalf("expected error output, got:\n%s", ui.OutputWriter.String())
   298  	}
   299  
   300  	expectedErr := `
   301  Error: Invalid target address
   302  
   303  Cannot move test_instance.foo to test_instance.bar[0]: the source is a whole
   304  resource (not a resource instance) so the target must also be a whole
   305  resource.
   306  
   307  `
   308  	errOutput := ui.ErrorWriter.String()
   309  	if errOutput != expectedErr {
   310  		t.Errorf("wrong output\n%s", cmp.Diff(errOutput, expectedErr))
   311  	}
   312  }
   313  
   314  func TestStateMv_resourceToInstanceErrInAutomation(t *testing.T) {
   315  	state := states.BuildState(func(s *states.SyncState) {
   316  		s.SetResourceInstanceCurrent(
   317  			addrs.Resource{
   318  				Mode: addrs.ManagedResourceMode,
   319  				Type: "test_instance",
   320  				Name: "foo",
   321  			}.Instance(addrs.IntKey(0)).Absolute(addrs.RootModuleInstance),
   322  			&states.ResourceInstanceObjectSrc{
   323  				AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`),
   324  				Status:    states.ObjectReady,
   325  			},
   326  			addrs.AbsProviderConfig{
   327  				Provider: addrs.NewDefaultProvider("test"),
   328  				Module:   addrs.RootModule,
   329  			},
   330  		)
   331  		s.SetResourceProvider(
   332  			addrs.Resource{
   333  				Mode: addrs.ManagedResourceMode,
   334  				Type: "test_instance",
   335  				Name: "bar",
   336  			}.Absolute(addrs.RootModuleInstance),
   337  			addrs.AbsProviderConfig{
   338  				Provider: addrs.NewDefaultProvider("test"),
   339  				Module:   addrs.RootModule,
   340  			},
   341  		)
   342  	})
   343  	statePath := testStateFile(t, state)
   344  
   345  	p := testProvider()
   346  	ui := new(cli.MockUi)
   347  	view, _ := testView(t)
   348  	c := &StateMvCommand{
   349  		StateMeta{
   350  			Meta: Meta{
   351  				testingOverrides:    metaOverridesForProvider(p),
   352  				Ui:                  ui,
   353  				View:                view,
   354  				RunningInAutomation: true,
   355  			},
   356  		},
   357  	}
   358  
   359  	args := []string{
   360  		"-state", statePath,
   361  		"test_instance.foo",
   362  		"test_instance.bar[0]",
   363  	}
   364  
   365  	if code := c.Run(args); code == 0 {
   366  		t.Fatalf("expected error output, got:\n%s", ui.OutputWriter.String())
   367  	}
   368  
   369  	expectedErr := `
   370  Error: Invalid target address
   371  
   372  Cannot move test_instance.foo to test_instance.bar[0]: the source is a whole
   373  resource (not a resource instance) so the target must also be a whole
   374  resource.
   375  
   376  `
   377  	errOutput := ui.ErrorWriter.String()
   378  	if errOutput != expectedErr {
   379  		t.Errorf("Unexpected diff.\ngot:\n%s\nwant:\n%s\n", errOutput, expectedErr)
   380  		t.Errorf("%s", cmp.Diff(errOutput, expectedErr))
   381  	}
   382  }
   383  
   384  func TestStateMv_instanceToResource(t *testing.T) {
   385  	state := states.BuildState(func(s *states.SyncState) {
   386  		s.SetResourceInstanceCurrent(
   387  			addrs.Resource{
   388  				Mode: addrs.ManagedResourceMode,
   389  				Type: "test_instance",
   390  				Name: "foo",
   391  			}.Instance(addrs.IntKey(0)).Absolute(addrs.RootModuleInstance),
   392  			&states.ResourceInstanceObjectSrc{
   393  				AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`),
   394  				Status:    states.ObjectReady,
   395  			},
   396  			addrs.AbsProviderConfig{
   397  				Provider: addrs.NewDefaultProvider("test"),
   398  				Module:   addrs.RootModule,
   399  			},
   400  		)
   401  		s.SetResourceInstanceCurrent(
   402  			addrs.Resource{
   403  				Mode: addrs.ManagedResourceMode,
   404  				Type: "test_instance",
   405  				Name: "baz",
   406  			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
   407  			&states.ResourceInstanceObjectSrc{
   408  				AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`),
   409  				Status:    states.ObjectReady,
   410  			},
   411  			addrs.AbsProviderConfig{
   412  				Provider: addrs.NewDefaultProvider("test"),
   413  				Module:   addrs.RootModule,
   414  			},
   415  		)
   416  	})
   417  	statePath := testStateFile(t, state)
   418  
   419  	p := testProvider()
   420  	ui := new(cli.MockUi)
   421  	view, _ := testView(t)
   422  	c := &StateMvCommand{
   423  		StateMeta{
   424  			Meta: Meta{
   425  				testingOverrides: metaOverridesForProvider(p),
   426  				Ui:               ui,
   427  				View:             view,
   428  			},
   429  		},
   430  	}
   431  
   432  	args := []string{
   433  		"-state", statePath,
   434  		"test_instance.foo[0]",
   435  		"test_instance.bar",
   436  	}
   437  	if code := c.Run(args); code != 0 {
   438  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   439  	}
   440  
   441  	// Test it is correct
   442  	testStateOutput(t, statePath, `
   443  test_instance.bar:
   444    ID = bar
   445    provider = provider["registry.terraform.io/hashicorp/test"]
   446    bar = value
   447    foo = value
   448  test_instance.baz:
   449    ID = foo
   450    provider = provider["registry.terraform.io/hashicorp/test"]
   451    bar = value
   452    foo = value
   453  `)
   454  
   455  	// Test we have backups
   456  	backups := testStateBackups(t, filepath.Dir(statePath))
   457  	if len(backups) != 1 {
   458  		t.Fatalf("bad: %#v", backups)
   459  	}
   460  	testStateOutput(t, backups[0], `
   461  test_instance.baz:
   462    ID = foo
   463    provider = provider["registry.terraform.io/hashicorp/test"]
   464    bar = value
   465    foo = value
   466  test_instance.foo.0:
   467    ID = bar
   468    provider = provider["registry.terraform.io/hashicorp/test"]
   469    bar = value
   470    foo = value
   471  `)
   472  }
   473  
   474  func TestStateMv_instanceToNewResource(t *testing.T) {
   475  	state := states.BuildState(func(s *states.SyncState) {
   476  		s.SetResourceInstanceCurrent(
   477  			addrs.Resource{
   478  				Mode: addrs.ManagedResourceMode,
   479  				Type: "test_instance",
   480  				Name: "foo",
   481  			}.Instance(addrs.IntKey(0)).Absolute(addrs.RootModuleInstance),
   482  			&states.ResourceInstanceObjectSrc{
   483  				AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`),
   484  				Status:    states.ObjectReady,
   485  			},
   486  			addrs.AbsProviderConfig{
   487  				Provider: addrs.NewDefaultProvider("test"),
   488  				Module:   addrs.RootModule,
   489  			},
   490  		)
   491  	})
   492  	statePath := testStateFile(t, state)
   493  
   494  	p := testProvider()
   495  	ui := new(cli.MockUi)
   496  	view, _ := testView(t)
   497  	c := &StateMvCommand{
   498  		StateMeta{
   499  			Meta: Meta{
   500  				testingOverrides: metaOverridesForProvider(p),
   501  				Ui:               ui,
   502  				View:             view,
   503  			},
   504  		},
   505  	}
   506  
   507  	args := []string{
   508  		"-state", statePath,
   509  		"test_instance.foo[0]",
   510  		"test_instance.bar[\"new\"]",
   511  	}
   512  	if code := c.Run(args); code != 0 {
   513  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   514  	}
   515  
   516  	// Test it is correct
   517  	testStateOutput(t, statePath, `
   518  test_instance.bar["new"]:
   519    ID = bar
   520    provider = provider["registry.terraform.io/hashicorp/test"]
   521    bar = value
   522    foo = value
   523  `)
   524  
   525  	// now move the instance to a new resource in a new module
   526  	args = []string{
   527  		"-state", statePath,
   528  		"test_instance.bar[\"new\"]",
   529  		"module.test.test_instance.baz[\"new\"]",
   530  	}
   531  	if code := c.Run(args); code != 0 {
   532  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   533  	}
   534  
   535  	// Test it is correct
   536  	testStateOutput(t, statePath, `
   537  <no state>
   538  module.test:
   539    test_instance.baz["new"]:
   540      ID = bar
   541      provider = provider["registry.terraform.io/hashicorp/test"]
   542      bar = value
   543      foo = value
   544  `)
   545  }
   546  
   547  func TestStateMv_differentResourceTypes(t *testing.T) {
   548  	state := states.BuildState(func(s *states.SyncState) {
   549  		s.SetResourceInstanceCurrent(
   550  			addrs.Resource{
   551  				Mode: addrs.ManagedResourceMode,
   552  				Type: "test_instance",
   553  				Name: "foo",
   554  			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
   555  			&states.ResourceInstanceObjectSrc{
   556  				AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`),
   557  				Status:    states.ObjectReady,
   558  			},
   559  			addrs.AbsProviderConfig{
   560  				Provider: addrs.NewDefaultProvider("test"),
   561  				Module:   addrs.RootModule,
   562  			},
   563  		)
   564  	})
   565  	statePath := testStateFile(t, state)
   566  
   567  	p := testProvider()
   568  	ui := new(cli.MockUi)
   569  	view, _ := testView(t)
   570  	c := &StateMvCommand{
   571  		StateMeta{
   572  			Meta: Meta{
   573  				testingOverrides: metaOverridesForProvider(p),
   574  				Ui:               ui,
   575  				View:             view,
   576  			},
   577  		},
   578  	}
   579  
   580  	args := []string{
   581  		"-state", statePath,
   582  		"test_instance.foo",
   583  		"test_network.bar",
   584  	}
   585  	if code := c.Run(args); code == 0 {
   586  		t.Fatalf("expected error output, got:\n%s", ui.OutputWriter.String())
   587  	}
   588  
   589  	gotErr := ui.ErrorWriter.String()
   590  	wantErr := `
   591  Error: Invalid state move request
   592  
   593  Cannot move test_instance.foo to test_network.bar: resource types don't
   594  match.
   595  
   596  `
   597  	if gotErr != wantErr {
   598  		t.Fatalf("expected initialization error\ngot:\n%s\n\nwant:%s", gotErr, wantErr)
   599  	}
   600  }
   601  
   602  // don't modify backend state is we supply a -state flag
   603  func TestStateMv_explicitWithBackend(t *testing.T) {
   604  	td := tempDir(t)
   605  	testCopyDir(t, testFixturePath("init-backend"), td)
   606  	defer os.RemoveAll(td)
   607  	defer testChdir(t, td)()
   608  
   609  	backupPath := filepath.Join(td, "backup")
   610  
   611  	state := states.BuildState(func(s *states.SyncState) {
   612  		s.SetResourceInstanceCurrent(
   613  			addrs.Resource{
   614  				Mode: addrs.ManagedResourceMode,
   615  				Type: "test_instance",
   616  				Name: "foo",
   617  			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
   618  			&states.ResourceInstanceObjectSrc{
   619  				AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`),
   620  				Status:    states.ObjectReady,
   621  			},
   622  			addrs.AbsProviderConfig{
   623  				Provider: addrs.NewDefaultProvider("test"),
   624  				Module:   addrs.RootModule,
   625  			},
   626  		)
   627  		s.SetResourceInstanceCurrent(
   628  			addrs.Resource{
   629  				Mode: addrs.ManagedResourceMode,
   630  				Type: "test_instance",
   631  				Name: "baz",
   632  			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
   633  			&states.ResourceInstanceObjectSrc{
   634  				AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`),
   635  				Status:    states.ObjectReady,
   636  			},
   637  			addrs.AbsProviderConfig{
   638  				Provider: addrs.NewDefaultProvider("test"),
   639  				Module:   addrs.RootModule,
   640  			},
   641  		)
   642  	})
   643  	statePath := testStateFile(t, state)
   644  
   645  	// init our backend
   646  	ui := new(cli.MockUi)
   647  	view, _ := testView(t)
   648  	ic := &InitCommand{
   649  		Meta: Meta{
   650  			testingOverrides: metaOverridesForProvider(testProvider()),
   651  			Ui:               ui,
   652  			View:             view,
   653  		},
   654  	}
   655  
   656  	args := []string{}
   657  	if code := ic.Run(args); code != 0 {
   658  		t.Fatalf("bad: \n%s", ui.ErrorWriter.String())
   659  	}
   660  
   661  	// only modify statePath
   662  	p := testProvider()
   663  	ui = new(cli.MockUi)
   664  	c := &StateMvCommand{
   665  		StateMeta{
   666  			Meta: Meta{
   667  				testingOverrides: metaOverridesForProvider(p),
   668  				Ui:               ui,
   669  				View:             view,
   670  			},
   671  		},
   672  	}
   673  
   674  	args = []string{
   675  		"-backup", backupPath,
   676  		"-state", statePath,
   677  		"test_instance.foo",
   678  		"test_instance.bar",
   679  	}
   680  	if code := c.Run(args); code != 0 {
   681  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   682  	}
   683  
   684  	// Test it is correct
   685  	testStateOutput(t, statePath, testStateMvOutput)
   686  }
   687  
   688  func TestStateMv_backupExplicit(t *testing.T) {
   689  	state := states.BuildState(func(s *states.SyncState) {
   690  		s.SetResourceInstanceCurrent(
   691  			addrs.Resource{
   692  				Mode: addrs.ManagedResourceMode,
   693  				Type: "test_instance",
   694  				Name: "foo",
   695  			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
   696  			&states.ResourceInstanceObjectSrc{
   697  				AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`),
   698  				Status:    states.ObjectReady,
   699  			},
   700  			addrs.AbsProviderConfig{
   701  				Provider: addrs.NewDefaultProvider("test"),
   702  				Module:   addrs.RootModule,
   703  			},
   704  		)
   705  		s.SetResourceInstanceCurrent(
   706  			addrs.Resource{
   707  				Mode: addrs.ManagedResourceMode,
   708  				Type: "test_instance",
   709  				Name: "baz",
   710  			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
   711  			&states.ResourceInstanceObjectSrc{
   712  				AttrsJSON:    []byte(`{"id":"foo","foo":"value","bar":"value"}`),
   713  				Status:       states.ObjectReady,
   714  				Dependencies: []addrs.ConfigResource{mustResourceAddr("test_instance.foo")},
   715  			},
   716  			addrs.AbsProviderConfig{
   717  				Provider: addrs.NewDefaultProvider("test"),
   718  				Module:   addrs.RootModule,
   719  			},
   720  		)
   721  	})
   722  	statePath := testStateFile(t, state)
   723  	backupPath := statePath + ".backup.test"
   724  
   725  	p := testProvider()
   726  	ui := new(cli.MockUi)
   727  	view, _ := testView(t)
   728  	c := &StateMvCommand{
   729  		StateMeta{
   730  			Meta: Meta{
   731  				testingOverrides: metaOverridesForProvider(p),
   732  				Ui:               ui,
   733  				View:             view,
   734  			},
   735  		},
   736  	}
   737  
   738  	args := []string{
   739  		"-backup", backupPath,
   740  		"-state", statePath,
   741  		"test_instance.foo",
   742  		"test_instance.bar",
   743  	}
   744  	if code := c.Run(args); code != 0 {
   745  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   746  	}
   747  
   748  	// Test it is correct
   749  	testStateOutput(t, statePath, testStateMvOutput)
   750  
   751  	// Test backup
   752  	testStateOutput(t, backupPath, testStateMvOutputOriginal)
   753  }
   754  
   755  func TestStateMv_stateOutNew(t *testing.T) {
   756  	state := states.BuildState(func(s *states.SyncState) {
   757  		s.SetResourceInstanceCurrent(
   758  			addrs.Resource{
   759  				Mode: addrs.ManagedResourceMode,
   760  				Type: "test_instance",
   761  				Name: "foo",
   762  			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
   763  			&states.ResourceInstanceObjectSrc{
   764  				AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`),
   765  				Status:    states.ObjectReady,
   766  			},
   767  			addrs.AbsProviderConfig{
   768  				Provider: addrs.NewDefaultProvider("test"),
   769  				Module:   addrs.RootModule,
   770  			},
   771  		)
   772  	})
   773  	statePath := testStateFile(t, state)
   774  	stateOutPath := statePath + ".out"
   775  
   776  	p := testProvider()
   777  	ui := new(cli.MockUi)
   778  	view, _ := testView(t)
   779  	c := &StateMvCommand{
   780  		StateMeta{
   781  			Meta: Meta{
   782  				testingOverrides: metaOverridesForProvider(p),
   783  				Ui:               ui,
   784  				View:             view,
   785  			},
   786  		},
   787  	}
   788  
   789  	args := []string{
   790  		"-state", statePath,
   791  		"-state-out", stateOutPath,
   792  		"test_instance.foo",
   793  		"test_instance.bar",
   794  	}
   795  	if code := c.Run(args); code != 0 {
   796  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   797  	}
   798  
   799  	// Test it is correct
   800  	testStateOutput(t, stateOutPath, testStateMvOutput_stateOut)
   801  	testStateOutput(t, statePath, testStateMvOutput_stateOutSrc)
   802  
   803  	// Test we have backups
   804  	backups := testStateBackups(t, filepath.Dir(statePath))
   805  	if len(backups) != 1 {
   806  		t.Fatalf("bad: %#v", backups)
   807  	}
   808  	testStateOutput(t, backups[0], testStateMvOutput_stateOutOriginal)
   809  }
   810  
   811  func TestStateMv_stateOutExisting(t *testing.T) {
   812  	stateSrc := states.BuildState(func(s *states.SyncState) {
   813  		s.SetResourceInstanceCurrent(
   814  			addrs.Resource{
   815  				Mode: addrs.ManagedResourceMode,
   816  				Type: "test_instance",
   817  				Name: "foo",
   818  			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
   819  			&states.ResourceInstanceObjectSrc{
   820  				AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`),
   821  				Status:    states.ObjectReady,
   822  			},
   823  			addrs.AbsProviderConfig{
   824  				Provider: addrs.NewDefaultProvider("test"),
   825  				Module:   addrs.RootModule,
   826  			},
   827  		)
   828  	})
   829  	statePath := testStateFile(t, stateSrc)
   830  
   831  	stateDst := states.BuildState(func(s *states.SyncState) {
   832  		s.SetResourceInstanceCurrent(
   833  			addrs.Resource{
   834  				Mode: addrs.ManagedResourceMode,
   835  				Type: "test_instance",
   836  				Name: "qux",
   837  			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
   838  			&states.ResourceInstanceObjectSrc{
   839  				AttrsJSON: []byte(`{"id":"bar"}`),
   840  				Status:    states.ObjectReady,
   841  			},
   842  			addrs.AbsProviderConfig{
   843  				Provider: addrs.NewDefaultProvider("test"),
   844  				Module:   addrs.RootModule,
   845  			},
   846  		)
   847  	})
   848  	stateOutPath := testStateFile(t, stateDst)
   849  
   850  	p := testProvider()
   851  	ui := new(cli.MockUi)
   852  	view, _ := testView(t)
   853  	c := &StateMvCommand{
   854  		StateMeta{
   855  			Meta: Meta{
   856  				testingOverrides: metaOverridesForProvider(p),
   857  				Ui:               ui,
   858  				View:             view,
   859  			},
   860  		},
   861  	}
   862  
   863  	args := []string{
   864  		"-state", statePath,
   865  		"-state-out", stateOutPath,
   866  		"test_instance.foo",
   867  		"test_instance.bar",
   868  	}
   869  	if code := c.Run(args); code != 0 {
   870  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   871  	}
   872  
   873  	// Test it is correct
   874  	testStateOutput(t, stateOutPath, testStateMvExisting_stateDst)
   875  	testStateOutput(t, statePath, testStateMvExisting_stateSrc)
   876  
   877  	// Test we have backups
   878  	backups := testStateBackups(t, filepath.Dir(statePath))
   879  	if len(backups) != 1 {
   880  		t.Fatalf("bad: %#v", backups)
   881  	}
   882  	testStateOutput(t, backups[0], testStateMvExisting_stateSrcOriginal)
   883  
   884  	backups = testStateBackups(t, filepath.Dir(stateOutPath))
   885  	if len(backups) != 1 {
   886  		t.Fatalf("bad: %#v", backups)
   887  	}
   888  	testStateOutput(t, backups[0], testStateMvExisting_stateDstOriginal)
   889  }
   890  
   891  func TestStateMv_noState(t *testing.T) {
   892  	tmp, cwd := testCwd(t)
   893  	defer testFixCwd(t, tmp, cwd)
   894  
   895  	p := testProvider()
   896  	ui := new(cli.MockUi)
   897  	view, _ := testView(t)
   898  	c := &StateMvCommand{
   899  		StateMeta{
   900  			Meta: Meta{
   901  				testingOverrides: metaOverridesForProvider(p),
   902  				Ui:               ui,
   903  				View:             view,
   904  			},
   905  		},
   906  	}
   907  
   908  	args := []string{"from", "to"}
   909  	if code := c.Run(args); code != 1 {
   910  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   911  	}
   912  }
   913  
   914  func TestStateMv_stateOutNew_count(t *testing.T) {
   915  	state := states.BuildState(func(s *states.SyncState) {
   916  		s.SetResourceInstanceCurrent(
   917  			addrs.Resource{
   918  				Mode: addrs.ManagedResourceMode,
   919  				Type: "test_instance",
   920  				Name: "foo",
   921  			}.Instance(addrs.IntKey(0)).Absolute(addrs.RootModuleInstance),
   922  			&states.ResourceInstanceObjectSrc{
   923  				AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`),
   924  				Status:    states.ObjectReady,
   925  			},
   926  			addrs.AbsProviderConfig{
   927  				Provider: addrs.NewDefaultProvider("test"),
   928  				Module:   addrs.RootModule,
   929  			},
   930  		)
   931  		s.SetResourceInstanceCurrent(
   932  			addrs.Resource{
   933  				Mode: addrs.ManagedResourceMode,
   934  				Type: "test_instance",
   935  				Name: "foo",
   936  			}.Instance(addrs.IntKey(1)).Absolute(addrs.RootModuleInstance),
   937  			&states.ResourceInstanceObjectSrc{
   938  				AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`),
   939  				Status:    states.ObjectReady,
   940  			},
   941  			addrs.AbsProviderConfig{
   942  				Provider: addrs.NewDefaultProvider("test"),
   943  				Module:   addrs.RootModule,
   944  			},
   945  		)
   946  		s.SetResourceInstanceCurrent(
   947  			addrs.Resource{
   948  				Mode: addrs.ManagedResourceMode,
   949  				Type: "test_instance",
   950  				Name: "bar",
   951  			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
   952  			&states.ResourceInstanceObjectSrc{
   953  				AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`),
   954  				Status:    states.ObjectReady,
   955  			},
   956  			addrs.AbsProviderConfig{
   957  				Provider: addrs.NewDefaultProvider("test"),
   958  				Module:   addrs.RootModule,
   959  			},
   960  		)
   961  	})
   962  	statePath := testStateFile(t, state)
   963  	stateOutPath := statePath + ".out"
   964  
   965  	p := testProvider()
   966  	ui := new(cli.MockUi)
   967  	view, _ := testView(t)
   968  	c := &StateMvCommand{
   969  		StateMeta{
   970  			Meta: Meta{
   971  				testingOverrides: metaOverridesForProvider(p),
   972  				Ui:               ui,
   973  				View:             view,
   974  			},
   975  		},
   976  	}
   977  
   978  	args := []string{
   979  		"-state", statePath,
   980  		"-state-out", stateOutPath,
   981  		"test_instance.foo",
   982  		"test_instance.bar",
   983  	}
   984  	if code := c.Run(args); code != 0 {
   985  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   986  	}
   987  
   988  	// Test it is correct
   989  	testStateOutput(t, stateOutPath, testStateMvCount_stateOut)
   990  	testStateOutput(t, statePath, testStateMvCount_stateOutSrc)
   991  
   992  	// Test we have backups
   993  	backups := testStateBackups(t, filepath.Dir(statePath))
   994  	if len(backups) != 1 {
   995  		t.Fatalf("bad: %#v", backups)
   996  	}
   997  	testStateOutput(t, backups[0], testStateMvCount_stateOutOriginal)
   998  }
   999  
  1000  // Modules with more than 10 resources were sorted lexically, causing the
  1001  // indexes in the new location to change.
  1002  func TestStateMv_stateOutNew_largeCount(t *testing.T) {
  1003  	state := states.BuildState(func(s *states.SyncState) {
  1004  		// test_instance.foo has 11 instances, all the same except for their ids
  1005  		for i := 0; i < 11; i++ {
  1006  			s.SetResourceInstanceCurrent(
  1007  				addrs.Resource{
  1008  					Mode: addrs.ManagedResourceMode,
  1009  					Type: "test_instance",
  1010  					Name: "foo",
  1011  				}.Instance(addrs.IntKey(i)).Absolute(addrs.RootModuleInstance),
  1012  				&states.ResourceInstanceObjectSrc{
  1013  					AttrsJSON: []byte(fmt.Sprintf(`{"id":"foo%d","foo":"value","bar":"value"}`, i)),
  1014  					Status:    states.ObjectReady,
  1015  				},
  1016  				addrs.AbsProviderConfig{
  1017  					Provider: addrs.NewDefaultProvider("test"),
  1018  					Module:   addrs.RootModule,
  1019  				},
  1020  			)
  1021  		}
  1022  		s.SetResourceInstanceCurrent(
  1023  			addrs.Resource{
  1024  				Mode: addrs.ManagedResourceMode,
  1025  				Type: "test_instance",
  1026  				Name: "bar",
  1027  			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
  1028  			&states.ResourceInstanceObjectSrc{
  1029  				AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`),
  1030  				Status:    states.ObjectReady,
  1031  			},
  1032  			addrs.AbsProviderConfig{
  1033  				Provider: addrs.NewDefaultProvider("test"),
  1034  				Module:   addrs.RootModule,
  1035  			},
  1036  		)
  1037  	})
  1038  	statePath := testStateFile(t, state)
  1039  	stateOutPath := statePath + ".out"
  1040  
  1041  	p := testProvider()
  1042  	ui := new(cli.MockUi)
  1043  	view, _ := testView(t)
  1044  	c := &StateMvCommand{
  1045  		StateMeta{
  1046  			Meta: Meta{
  1047  				testingOverrides: metaOverridesForProvider(p),
  1048  				Ui:               ui,
  1049  				View:             view,
  1050  			},
  1051  		},
  1052  	}
  1053  
  1054  	args := []string{
  1055  		"-state", statePath,
  1056  		"-state-out", stateOutPath,
  1057  		"test_instance.foo",
  1058  		"test_instance.bar",
  1059  	}
  1060  	if code := c.Run(args); code != 0 {
  1061  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
  1062  	}
  1063  
  1064  	// Test it is correct
  1065  	testStateOutput(t, stateOutPath, testStateMvLargeCount_stateOut)
  1066  	testStateOutput(t, statePath, testStateMvLargeCount_stateOutSrc)
  1067  
  1068  	// Test we have backups
  1069  	backups := testStateBackups(t, filepath.Dir(statePath))
  1070  	if len(backups) != 1 {
  1071  		t.Fatalf("bad: %#v", backups)
  1072  	}
  1073  	testStateOutput(t, backups[0], testStateMvLargeCount_stateOutOriginal)
  1074  }
  1075  
  1076  func TestStateMv_stateOutNew_nestedModule(t *testing.T) {
  1077  	state := states.BuildState(func(s *states.SyncState) {
  1078  		s.SetResourceInstanceCurrent(
  1079  			addrs.Resource{
  1080  				Mode: addrs.ManagedResourceMode,
  1081  				Type: "test_instance",
  1082  				Name: "foo",
  1083  			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance.Child("foo", addrs.NoKey).Child("child1", addrs.NoKey)),
  1084  			&states.ResourceInstanceObjectSrc{
  1085  				AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`),
  1086  				Status:    states.ObjectReady,
  1087  			},
  1088  			addrs.AbsProviderConfig{
  1089  				Provider: addrs.NewDefaultProvider("test"),
  1090  				Module:   addrs.RootModule,
  1091  			},
  1092  		)
  1093  		s.SetResourceInstanceCurrent(
  1094  			addrs.Resource{
  1095  				Mode: addrs.ManagedResourceMode,
  1096  				Type: "test_instance",
  1097  				Name: "foo",
  1098  			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance.Child("foo", addrs.NoKey).Child("child2", addrs.NoKey)),
  1099  			&states.ResourceInstanceObjectSrc{
  1100  				AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`),
  1101  				Status:    states.ObjectReady,
  1102  			},
  1103  			addrs.AbsProviderConfig{
  1104  				Provider: addrs.NewDefaultProvider("test"),
  1105  				Module:   addrs.RootModule,
  1106  			},
  1107  		)
  1108  	})
  1109  
  1110  	statePath := testStateFile(t, state)
  1111  	stateOutPath := statePath + ".out"
  1112  
  1113  	p := testProvider()
  1114  	ui := new(cli.MockUi)
  1115  	view, _ := testView(t)
  1116  	c := &StateMvCommand{
  1117  		StateMeta{
  1118  			Meta: Meta{
  1119  				testingOverrides: metaOverridesForProvider(p),
  1120  				Ui:               ui,
  1121  				View:             view,
  1122  			},
  1123  		},
  1124  	}
  1125  
  1126  	args := []string{
  1127  		"-state", statePath,
  1128  		"-state-out", stateOutPath,
  1129  		"module.foo",
  1130  		"module.bar",
  1131  	}
  1132  	if code := c.Run(args); code != 0 {
  1133  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
  1134  	}
  1135  
  1136  	// Test it is correct
  1137  	testStateOutput(t, stateOutPath, testStateMvNestedModule_stateOut)
  1138  	testStateOutput(t, statePath, testStateMvNestedModule_stateOutSrc)
  1139  
  1140  	// Test we have backups
  1141  	backups := testStateBackups(t, filepath.Dir(statePath))
  1142  	if len(backups) != 1 {
  1143  		t.Fatalf("bad: %#v", backups)
  1144  	}
  1145  	testStateOutput(t, backups[0], testStateMvNestedModule_stateOutOriginal)
  1146  }
  1147  
  1148  func TestStateMv_toNewModule(t *testing.T) {
  1149  	state := states.BuildState(func(s *states.SyncState) {
  1150  		s.SetResourceInstanceCurrent(
  1151  			addrs.Resource{
  1152  				Mode: addrs.ManagedResourceMode,
  1153  				Type: "test_instance",
  1154  				Name: "bar",
  1155  			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
  1156  			&states.ResourceInstanceObjectSrc{
  1157  				AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`),
  1158  				Status:    states.ObjectReady,
  1159  			},
  1160  			addrs.AbsProviderConfig{
  1161  				Provider: addrs.NewDefaultProvider("test"),
  1162  				Module:   addrs.RootModule,
  1163  			},
  1164  		)
  1165  	})
  1166  
  1167  	statePath := testStateFile(t, state)
  1168  	stateOutPath1 := statePath + ".out1"
  1169  	stateOutPath2 := statePath + ".out2"
  1170  
  1171  	p := testProvider()
  1172  	ui := new(cli.MockUi)
  1173  	view, _ := testView(t)
  1174  	c := &StateMvCommand{
  1175  		StateMeta{
  1176  			Meta: Meta{
  1177  				testingOverrides: metaOverridesForProvider(p),
  1178  				Ui:               ui,
  1179  				View:             view,
  1180  			},
  1181  		},
  1182  	}
  1183  
  1184  	args := []string{
  1185  		"-state", statePath,
  1186  		"-state-out", stateOutPath1,
  1187  		"test_instance.bar",
  1188  		"module.bar.test_instance.bar",
  1189  	}
  1190  	if code := c.Run(args); code != 0 {
  1191  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
  1192  	}
  1193  
  1194  	// Test it is correct
  1195  	testStateOutput(t, stateOutPath1, testStateMvNewModule_stateOut)
  1196  	testStateOutput(t, statePath, testStateMvNestedModule_stateOutSrc)
  1197  
  1198  	// Test we have backups
  1199  	backups := testStateBackups(t, filepath.Dir(statePath))
  1200  	if len(backups) != 1 {
  1201  		t.Fatalf("bad: %#v", backups)
  1202  	}
  1203  	testStateOutput(t, backups[0], testStateMvNewModule_stateOutOriginal)
  1204  
  1205  	// now verify we can move the module itself
  1206  	args = []string{
  1207  		"-state", stateOutPath1,
  1208  		"-state-out", stateOutPath2,
  1209  		"module.bar",
  1210  		"module.foo",
  1211  	}
  1212  	if code := c.Run(args); code != 0 {
  1213  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
  1214  	}
  1215  	testStateOutput(t, stateOutPath2, testStateMvModuleNewModule_stateOut)
  1216  }
  1217  
  1218  func TestStateMv_withinBackend(t *testing.T) {
  1219  	td := tempDir(t)
  1220  	testCopyDir(t, testFixturePath("backend-unchanged"), td)
  1221  	defer os.RemoveAll(td)
  1222  	defer testChdir(t, td)()
  1223  
  1224  	state := states.BuildState(func(s *states.SyncState) {
  1225  		s.SetResourceInstanceCurrent(
  1226  			addrs.Resource{
  1227  				Mode: addrs.ManagedResourceMode,
  1228  				Type: "test_instance",
  1229  				Name: "foo",
  1230  			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
  1231  			&states.ResourceInstanceObjectSrc{
  1232  				AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`),
  1233  				Status:    states.ObjectReady,
  1234  			},
  1235  			addrs.AbsProviderConfig{
  1236  				Provider: addrs.NewDefaultProvider("test"),
  1237  				Module:   addrs.RootModule,
  1238  			},
  1239  		)
  1240  		s.SetResourceInstanceCurrent(
  1241  			addrs.Resource{
  1242  				Mode: addrs.ManagedResourceMode,
  1243  				Type: "test_instance",
  1244  				Name: "baz",
  1245  			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
  1246  			&states.ResourceInstanceObjectSrc{
  1247  				AttrsJSON:    []byte(`{"id":"foo","foo":"value","bar":"value"}`),
  1248  				Status:       states.ObjectReady,
  1249  				Dependencies: []addrs.ConfigResource{mustResourceAddr("test_instance.foo")},
  1250  			},
  1251  			addrs.AbsProviderConfig{
  1252  				Provider: addrs.NewDefaultProvider("test"),
  1253  				Module:   addrs.RootModule,
  1254  			},
  1255  		)
  1256  	})
  1257  
  1258  	// the local backend state file is "foo"
  1259  	statePath := "local-state.tfstate"
  1260  	backupPath := "local-state.backup"
  1261  
  1262  	f, err := os.Create(statePath)
  1263  	if err != nil {
  1264  		t.Fatal(err)
  1265  	}
  1266  	defer f.Close()
  1267  
  1268  	if err := writeStateForTesting(state, f); err != nil {
  1269  		t.Fatal(err)
  1270  	}
  1271  
  1272  	p := testProvider()
  1273  	ui := new(cli.MockUi)
  1274  	view, _ := testView(t)
  1275  	c := &StateMvCommand{
  1276  		StateMeta{
  1277  			Meta: Meta{
  1278  				testingOverrides: metaOverridesForProvider(p),
  1279  				Ui:               ui,
  1280  				View:             view,
  1281  			},
  1282  		},
  1283  	}
  1284  
  1285  	args := []string{
  1286  		"-backup", backupPath,
  1287  		"test_instance.foo",
  1288  		"test_instance.bar",
  1289  	}
  1290  	if code := c.Run(args); code != 0 {
  1291  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
  1292  	}
  1293  
  1294  	testStateOutput(t, statePath, testStateMvOutput)
  1295  	testStateOutput(t, backupPath, testStateMvOutputOriginal)
  1296  }
  1297  
  1298  func TestStateMv_fromBackendToLocal(t *testing.T) {
  1299  	td := tempDir(t)
  1300  	testCopyDir(t, testFixturePath("backend-unchanged"), td)
  1301  	defer os.RemoveAll(td)
  1302  	defer testChdir(t, td)()
  1303  
  1304  	state := states.NewState()
  1305  	state.Module(addrs.RootModuleInstance).SetResourceInstanceCurrent(
  1306  		mustResourceAddr("test_instance.foo").Resource.Instance(addrs.NoKey),
  1307  		&states.ResourceInstanceObjectSrc{
  1308  			AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`),
  1309  			Status:    states.ObjectReady,
  1310  		},
  1311  		addrs.AbsProviderConfig{
  1312  			Provider: addrs.NewDefaultProvider("test"),
  1313  			Module:   addrs.RootModule,
  1314  		},
  1315  	)
  1316  	state.Module(addrs.RootModuleInstance).SetResourceInstanceCurrent(
  1317  		mustResourceAddr("test_instance.baz").Resource.Instance(addrs.NoKey),
  1318  		&states.ResourceInstanceObjectSrc{
  1319  			AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`),
  1320  			Status:    states.ObjectReady,
  1321  		},
  1322  		addrs.AbsProviderConfig{
  1323  			Provider: addrs.NewDefaultProvider("test"),
  1324  			Module:   addrs.RootModule,
  1325  		},
  1326  	)
  1327  
  1328  	// the local backend state file is "foo"
  1329  	statePath := "local-state.tfstate"
  1330  
  1331  	// real "local" state file
  1332  	statePathOut := "real-local.tfstate"
  1333  
  1334  	f, err := os.Create(statePath)
  1335  	if err != nil {
  1336  		t.Fatal(err)
  1337  	}
  1338  	defer f.Close()
  1339  
  1340  	if err := writeStateForTesting(state, f); err != nil {
  1341  		t.Fatal(err)
  1342  	}
  1343  
  1344  	p := testProvider()
  1345  	ui := new(cli.MockUi)
  1346  	view, _ := testView(t)
  1347  	c := &StateMvCommand{
  1348  		StateMeta{
  1349  			Meta: Meta{
  1350  				testingOverrides: metaOverridesForProvider(p),
  1351  				Ui:               ui,
  1352  				View:             view,
  1353  			},
  1354  		},
  1355  	}
  1356  
  1357  	args := []string{
  1358  		"-state-out", statePathOut,
  1359  		"test_instance.foo",
  1360  		"test_instance.bar",
  1361  	}
  1362  	if code := c.Run(args); code != 0 {
  1363  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
  1364  	}
  1365  
  1366  	testStateOutput(t, statePathOut, testStateMvCount_stateOutSrc)
  1367  
  1368  	// the backend state should be left with only baz
  1369  	testStateOutput(t, statePath, testStateMvOriginal_backend)
  1370  }
  1371  
  1372  // This test covers moving the only resource in a module to a new address in
  1373  // that module, which triggers the maybePruneModule functionality. This caused
  1374  // a panic report: https://github.com/hashicorp/terraform/issues/25520
  1375  func TestStateMv_onlyResourceInModule(t *testing.T) {
  1376  	state := states.BuildState(func(s *states.SyncState) {
  1377  		s.SetResourceInstanceCurrent(
  1378  			addrs.Resource{
  1379  				Mode: addrs.ManagedResourceMode,
  1380  				Type: "test_instance",
  1381  				Name: "foo",
  1382  			}.Instance(addrs.IntKey(0)).Absolute(addrs.RootModuleInstance.Child("foo", addrs.NoKey)),
  1383  			&states.ResourceInstanceObjectSrc{
  1384  				AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`),
  1385  				Status:    states.ObjectReady,
  1386  			},
  1387  			addrs.AbsProviderConfig{
  1388  				Provider: addrs.NewDefaultProvider("test"),
  1389  				Module:   addrs.RootModule,
  1390  			},
  1391  		)
  1392  	})
  1393  
  1394  	statePath := testStateFile(t, state)
  1395  	testStateOutput(t, statePath, testStateMvOnlyResourceInModule_original)
  1396  
  1397  	p := testProvider()
  1398  	ui := new(cli.MockUi)
  1399  	view, _ := testView(t)
  1400  	c := &StateMvCommand{
  1401  		StateMeta{
  1402  			Meta: Meta{
  1403  				testingOverrides: metaOverridesForProvider(p),
  1404  				Ui:               ui,
  1405  				View:             view,
  1406  			},
  1407  		},
  1408  	}
  1409  
  1410  	args := []string{
  1411  		"-state", statePath,
  1412  		"module.foo.test_instance.foo",
  1413  		"module.foo.test_instance.bar",
  1414  	}
  1415  	if code := c.Run(args); code != 0 {
  1416  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
  1417  	}
  1418  
  1419  	// Test it is correct
  1420  	testStateOutput(t, statePath, testStateMvOnlyResourceInModule_output)
  1421  
  1422  	// Test we have backups
  1423  	backups := testStateBackups(t, filepath.Dir(statePath))
  1424  	if len(backups) != 1 {
  1425  		t.Fatalf("bad: %#v", backups)
  1426  	}
  1427  	testStateOutput(t, backups[0], testStateMvOnlyResourceInModule_original)
  1428  }
  1429  
  1430  func TestStateMvHelp(t *testing.T) {
  1431  	c := &StateMvCommand{}
  1432  	if strings.ContainsRune(c.Help(), '\t') {
  1433  		t.Fatal("help text contains tab character, which will result in poor formatting")
  1434  	}
  1435  }
  1436  
  1437  const testStateMvOutputOriginal = `
  1438  test_instance.baz:
  1439    ID = foo
  1440    provider = provider["registry.terraform.io/hashicorp/test"]
  1441    bar = value
  1442    foo = value
  1443  
  1444    Dependencies:
  1445      test_instance.foo
  1446  test_instance.foo:
  1447    ID = bar
  1448    provider = provider["registry.terraform.io/hashicorp/test"]
  1449    bar = value
  1450    foo = value
  1451  `
  1452  
  1453  const testStateMvOutput = `
  1454  test_instance.bar:
  1455    ID = bar
  1456    provider = provider["registry.terraform.io/hashicorp/test"]
  1457    bar = value
  1458    foo = value
  1459  test_instance.baz:
  1460    ID = foo
  1461    provider = provider["registry.terraform.io/hashicorp/test"]
  1462    bar = value
  1463    foo = value
  1464  `
  1465  
  1466  const testStateMvCount_stateOut = `
  1467  test_instance.bar.0:
  1468    ID = foo
  1469    provider = provider["registry.terraform.io/hashicorp/test"]
  1470    bar = value
  1471    foo = value
  1472  test_instance.bar.1:
  1473    ID = bar
  1474    provider = provider["registry.terraform.io/hashicorp/test"]
  1475    bar = value
  1476    foo = value
  1477  `
  1478  
  1479  const testStateMvCount_stateOutSrc = `
  1480  test_instance.bar:
  1481    ID = bar
  1482    provider = provider["registry.terraform.io/hashicorp/test"]
  1483    bar = value
  1484    foo = value
  1485  `
  1486  
  1487  const testStateMvCount_stateOutOriginal = `
  1488  test_instance.bar:
  1489    ID = bar
  1490    provider = provider["registry.terraform.io/hashicorp/test"]
  1491    bar = value
  1492    foo = value
  1493  test_instance.foo.0:
  1494    ID = foo
  1495    provider = provider["registry.terraform.io/hashicorp/test"]
  1496    bar = value
  1497    foo = value
  1498  test_instance.foo.1:
  1499    ID = bar
  1500    provider = provider["registry.terraform.io/hashicorp/test"]
  1501    bar = value
  1502    foo = value
  1503  `
  1504  
  1505  const testStateMvLargeCount_stateOut = `
  1506  test_instance.bar.0:
  1507    ID = foo0
  1508    provider = provider["registry.terraform.io/hashicorp/test"]
  1509    bar = value
  1510    foo = value
  1511  test_instance.bar.1:
  1512    ID = foo1
  1513    provider = provider["registry.terraform.io/hashicorp/test"]
  1514    bar = value
  1515    foo = value
  1516  test_instance.bar.2:
  1517    ID = foo2
  1518    provider = provider["registry.terraform.io/hashicorp/test"]
  1519    bar = value
  1520    foo = value
  1521  test_instance.bar.3:
  1522    ID = foo3
  1523    provider = provider["registry.terraform.io/hashicorp/test"]
  1524    bar = value
  1525    foo = value
  1526  test_instance.bar.4:
  1527    ID = foo4
  1528    provider = provider["registry.terraform.io/hashicorp/test"]
  1529    bar = value
  1530    foo = value
  1531  test_instance.bar.5:
  1532    ID = foo5
  1533    provider = provider["registry.terraform.io/hashicorp/test"]
  1534    bar = value
  1535    foo = value
  1536  test_instance.bar.6:
  1537    ID = foo6
  1538    provider = provider["registry.terraform.io/hashicorp/test"]
  1539    bar = value
  1540    foo = value
  1541  test_instance.bar.7:
  1542    ID = foo7
  1543    provider = provider["registry.terraform.io/hashicorp/test"]
  1544    bar = value
  1545    foo = value
  1546  test_instance.bar.8:
  1547    ID = foo8
  1548    provider = provider["registry.terraform.io/hashicorp/test"]
  1549    bar = value
  1550    foo = value
  1551  test_instance.bar.9:
  1552    ID = foo9
  1553    provider = provider["registry.terraform.io/hashicorp/test"]
  1554    bar = value
  1555    foo = value
  1556  test_instance.bar.10:
  1557    ID = foo10
  1558    provider = provider["registry.terraform.io/hashicorp/test"]
  1559    bar = value
  1560    foo = value
  1561  `
  1562  
  1563  const testStateMvLargeCount_stateOutSrc = `
  1564  test_instance.bar:
  1565    ID = bar
  1566    provider = provider["registry.terraform.io/hashicorp/test"]
  1567    bar = value
  1568    foo = value
  1569  `
  1570  
  1571  const testStateMvLargeCount_stateOutOriginal = `
  1572  test_instance.bar:
  1573    ID = bar
  1574    provider = provider["registry.terraform.io/hashicorp/test"]
  1575    bar = value
  1576    foo = value
  1577  test_instance.foo.0:
  1578    ID = foo0
  1579    provider = provider["registry.terraform.io/hashicorp/test"]
  1580    bar = value
  1581    foo = value
  1582  test_instance.foo.1:
  1583    ID = foo1
  1584    provider = provider["registry.terraform.io/hashicorp/test"]
  1585    bar = value
  1586    foo = value
  1587  test_instance.foo.2:
  1588    ID = foo2
  1589    provider = provider["registry.terraform.io/hashicorp/test"]
  1590    bar = value
  1591    foo = value
  1592  test_instance.foo.3:
  1593    ID = foo3
  1594    provider = provider["registry.terraform.io/hashicorp/test"]
  1595    bar = value
  1596    foo = value
  1597  test_instance.foo.4:
  1598    ID = foo4
  1599    provider = provider["registry.terraform.io/hashicorp/test"]
  1600    bar = value
  1601    foo = value
  1602  test_instance.foo.5:
  1603    ID = foo5
  1604    provider = provider["registry.terraform.io/hashicorp/test"]
  1605    bar = value
  1606    foo = value
  1607  test_instance.foo.6:
  1608    ID = foo6
  1609    provider = provider["registry.terraform.io/hashicorp/test"]
  1610    bar = value
  1611    foo = value
  1612  test_instance.foo.7:
  1613    ID = foo7
  1614    provider = provider["registry.terraform.io/hashicorp/test"]
  1615    bar = value
  1616    foo = value
  1617  test_instance.foo.8:
  1618    ID = foo8
  1619    provider = provider["registry.terraform.io/hashicorp/test"]
  1620    bar = value
  1621    foo = value
  1622  test_instance.foo.9:
  1623    ID = foo9
  1624    provider = provider["registry.terraform.io/hashicorp/test"]
  1625    bar = value
  1626    foo = value
  1627  test_instance.foo.10:
  1628    ID = foo10
  1629    provider = provider["registry.terraform.io/hashicorp/test"]
  1630    bar = value
  1631    foo = value
  1632  `
  1633  
  1634  const testStateMvNestedModule_stateOut = `
  1635  <no state>
  1636  module.bar.child1:
  1637    test_instance.foo:
  1638      ID = bar
  1639      provider = provider["registry.terraform.io/hashicorp/test"]
  1640      bar = value
  1641      foo = value
  1642  module.bar.child2:
  1643    test_instance.foo:
  1644      ID = bar
  1645      provider = provider["registry.terraform.io/hashicorp/test"]
  1646      bar = value
  1647      foo = value
  1648  `
  1649  
  1650  const testStateMvNewModule_stateOut = `
  1651  <no state>
  1652  module.bar:
  1653    test_instance.bar:
  1654      ID = bar
  1655      provider = provider["registry.terraform.io/hashicorp/test"]
  1656      bar = value
  1657      foo = value
  1658  `
  1659  
  1660  const testStateMvModuleNewModule_stateOut = `
  1661  <no state>
  1662  module.foo:
  1663    test_instance.bar:
  1664      ID = bar
  1665      provider = provider["registry.terraform.io/hashicorp/test"]
  1666      bar = value
  1667      foo = value
  1668  `
  1669  
  1670  const testStateMvNewModule_stateOutOriginal = `
  1671  test_instance.bar:
  1672    ID = bar
  1673    provider = provider["registry.terraform.io/hashicorp/test"]
  1674    bar = value
  1675    foo = value
  1676  `
  1677  
  1678  const testStateMvNestedModule_stateOutSrc = `
  1679  <no state>
  1680  `
  1681  
  1682  const testStateMvNestedModule_stateOutOriginal = `
  1683  <no state>
  1684  module.foo.child1:
  1685    test_instance.foo:
  1686      ID = bar
  1687      provider = provider["registry.terraform.io/hashicorp/test"]
  1688      bar = value
  1689      foo = value
  1690  module.foo.child2:
  1691    test_instance.foo:
  1692      ID = bar
  1693      provider = provider["registry.terraform.io/hashicorp/test"]
  1694      bar = value
  1695      foo = value
  1696  `
  1697  
  1698  const testStateMvOutput_stateOut = `
  1699  test_instance.bar:
  1700    ID = bar
  1701    provider = provider["registry.terraform.io/hashicorp/test"]
  1702    bar = value
  1703    foo = value
  1704  `
  1705  
  1706  const testStateMvOutput_stateOutSrc = `
  1707  <no state>
  1708  `
  1709  
  1710  const testStateMvOutput_stateOutOriginal = `
  1711  test_instance.foo:
  1712    ID = bar
  1713    provider = provider["registry.terraform.io/hashicorp/test"]
  1714    bar = value
  1715    foo = value
  1716  `
  1717  
  1718  const testStateMvExisting_stateSrc = `
  1719  <no state>
  1720  `
  1721  
  1722  const testStateMvExisting_stateDst = `
  1723  test_instance.bar:
  1724    ID = bar
  1725    provider = provider["registry.terraform.io/hashicorp/test"]
  1726    bar = value
  1727    foo = value
  1728  test_instance.qux:
  1729    ID = bar
  1730    provider = provider["registry.terraform.io/hashicorp/test"]
  1731  `
  1732  
  1733  const testStateMvExisting_stateSrcOriginal = `
  1734  test_instance.foo:
  1735    ID = bar
  1736    provider = provider["registry.terraform.io/hashicorp/test"]
  1737    bar = value
  1738    foo = value
  1739  `
  1740  
  1741  const testStateMvExisting_stateDstOriginal = `
  1742  test_instance.qux:
  1743    ID = bar
  1744    provider = provider["registry.terraform.io/hashicorp/test"]
  1745  `
  1746  
  1747  const testStateMvOriginal_backend = `
  1748  test_instance.baz:
  1749    ID = foo
  1750    provider = provider["registry.terraform.io/hashicorp/test"]
  1751    bar = value
  1752    foo = value
  1753  `
  1754  
  1755  const testStateMvOnlyResourceInModule_original = `
  1756  <no state>
  1757  module.foo:
  1758    test_instance.foo.0:
  1759      ID = bar
  1760      provider = provider["registry.terraform.io/hashicorp/test"]
  1761      bar = value
  1762      foo = value
  1763  `
  1764  
  1765  const testStateMvOnlyResourceInModule_output = `
  1766  <no state>
  1767  module.foo:
  1768    test_instance.bar.0:
  1769      ID = bar
  1770      provider = provider["registry.terraform.io/hashicorp/test"]
  1771      bar = value
  1772      foo = value
  1773  `