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