github.com/paultyng/terraform@v0.6.11-0.20180227224804-66ff8f8bed40/command/state_mv_test.go (about)

     1  package command
     2  
     3  import (
     4  	"os"
     5  	"path/filepath"
     6  	"testing"
     7  
     8  	"github.com/hashicorp/terraform/helper/copy"
     9  	"github.com/hashicorp/terraform/terraform"
    10  	"github.com/mitchellh/cli"
    11  )
    12  
    13  func TestStateMv(t *testing.T) {
    14  	state := &terraform.State{
    15  		Modules: []*terraform.ModuleState{
    16  			&terraform.ModuleState{
    17  				Path: []string{"root"},
    18  				Resources: map[string]*terraform.ResourceState{
    19  					"test_instance.foo": &terraform.ResourceState{
    20  						Type: "test_instance",
    21  						Primary: &terraform.InstanceState{
    22  							ID: "bar",
    23  							Attributes: map[string]string{
    24  								"foo": "value",
    25  								"bar": "value",
    26  							},
    27  						},
    28  					},
    29  
    30  					"test_instance.baz": &terraform.ResourceState{
    31  						Type: "test_instance",
    32  						Primary: &terraform.InstanceState{
    33  							ID: "foo",
    34  							Attributes: map[string]string{
    35  								"foo": "value",
    36  								"bar": "value",
    37  							},
    38  						},
    39  					},
    40  				},
    41  			},
    42  		},
    43  	}
    44  
    45  	statePath := testStateFile(t, state)
    46  
    47  	p := testProvider()
    48  	ui := new(cli.MockUi)
    49  	c := &StateMvCommand{
    50  		StateMeta{
    51  			Meta: Meta{
    52  				testingOverrides: metaOverridesForProvider(p),
    53  				Ui:               ui,
    54  			},
    55  		},
    56  	}
    57  
    58  	args := []string{
    59  		"-state", statePath,
    60  		"test_instance.foo",
    61  		"test_instance.bar",
    62  	}
    63  	if code := c.Run(args); code != 0 {
    64  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
    65  	}
    66  
    67  	// Test it is correct
    68  	testStateOutput(t, statePath, testStateMvOutput)
    69  
    70  	// Test we have backups
    71  	backups := testStateBackups(t, filepath.Dir(statePath))
    72  	if len(backups) != 1 {
    73  		t.Fatalf("bad: %#v", backups)
    74  	}
    75  	testStateOutput(t, backups[0], testStateMvOutputOriginal)
    76  }
    77  
    78  // don't modify backend state is we supply a -state flag
    79  func TestStateMv_explicitWithBackend(t *testing.T) {
    80  	td := tempDir(t)
    81  	copy.CopyDir(testFixturePath("init-backend"), td)
    82  	defer os.RemoveAll(td)
    83  	defer testChdir(t, td)()
    84  
    85  	backupPath := filepath.Join(td, "backup")
    86  
    87  	state := &terraform.State{
    88  		Modules: []*terraform.ModuleState{
    89  			&terraform.ModuleState{
    90  				Path: []string{"root"},
    91  				Resources: map[string]*terraform.ResourceState{
    92  					"test_instance.foo": &terraform.ResourceState{
    93  						Type: "test_instance",
    94  						Primary: &terraform.InstanceState{
    95  							ID: "bar",
    96  							Attributes: map[string]string{
    97  								"foo": "value",
    98  								"bar": "value",
    99  							},
   100  						},
   101  					},
   102  
   103  					"test_instance.baz": &terraform.ResourceState{
   104  						Type: "test_instance",
   105  						Primary: &terraform.InstanceState{
   106  							ID: "foo",
   107  							Attributes: map[string]string{
   108  								"foo": "value",
   109  								"bar": "value",
   110  							},
   111  						},
   112  					},
   113  				},
   114  			},
   115  		},
   116  	}
   117  
   118  	statePath := testStateFile(t, state)
   119  
   120  	// init our backend
   121  	ui := new(cli.MockUi)
   122  	ic := &InitCommand{
   123  		Meta: Meta{
   124  			testingOverrides: metaOverridesForProvider(testProvider()),
   125  			Ui:               ui,
   126  		},
   127  	}
   128  
   129  	args := []string{}
   130  	if code := ic.Run(args); code != 0 {
   131  		t.Fatalf("bad: \n%s", ui.ErrorWriter.String())
   132  	}
   133  
   134  	// only modify statePath
   135  	p := testProvider()
   136  	ui = new(cli.MockUi)
   137  	c := &StateMvCommand{
   138  		StateMeta{
   139  			Meta: Meta{
   140  				testingOverrides: metaOverridesForProvider(p),
   141  				Ui:               ui,
   142  			},
   143  		},
   144  	}
   145  
   146  	args = []string{
   147  		"-backup", backupPath,
   148  		"-state", statePath,
   149  		"test_instance.foo",
   150  		"test_instance.bar",
   151  	}
   152  	if code := c.Run(args); code != 0 {
   153  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   154  	}
   155  
   156  	// Test it is correct
   157  	testStateOutput(t, statePath, testStateMvOutput)
   158  }
   159  
   160  func TestStateMv_backupExplicit(t *testing.T) {
   161  	td := tempDir(t)
   162  	defer os.RemoveAll(td)
   163  	backupPath := filepath.Join(td, "backup")
   164  
   165  	state := &terraform.State{
   166  		Modules: []*terraform.ModuleState{
   167  			&terraform.ModuleState{
   168  				Path: []string{"root"},
   169  				Resources: map[string]*terraform.ResourceState{
   170  					"test_instance.foo": &terraform.ResourceState{
   171  						Type: "test_instance",
   172  						Primary: &terraform.InstanceState{
   173  							ID: "bar",
   174  							Attributes: map[string]string{
   175  								"foo": "value",
   176  								"bar": "value",
   177  							},
   178  						},
   179  					},
   180  
   181  					"test_instance.baz": &terraform.ResourceState{
   182  						Type: "test_instance",
   183  						Primary: &terraform.InstanceState{
   184  							ID: "foo",
   185  							Attributes: map[string]string{
   186  								"foo": "value",
   187  								"bar": "value",
   188  							},
   189  						},
   190  					},
   191  				},
   192  			},
   193  		},
   194  	}
   195  
   196  	statePath := testStateFile(t, state)
   197  
   198  	p := testProvider()
   199  	ui := new(cli.MockUi)
   200  	c := &StateMvCommand{
   201  		StateMeta{
   202  			Meta: Meta{
   203  				testingOverrides: metaOverridesForProvider(p),
   204  				Ui:               ui,
   205  			},
   206  		},
   207  	}
   208  
   209  	args := []string{
   210  		"-backup", backupPath,
   211  		"-state", statePath,
   212  		"test_instance.foo",
   213  		"test_instance.bar",
   214  	}
   215  	if code := c.Run(args); code != 0 {
   216  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   217  	}
   218  
   219  	// Test it is correct
   220  	testStateOutput(t, statePath, testStateMvOutput)
   221  
   222  	// Test backup
   223  	testStateOutput(t, backupPath, testStateMvOutputOriginal)
   224  }
   225  
   226  func TestStateMv_stateOutNew(t *testing.T) {
   227  	state := &terraform.State{
   228  		Modules: []*terraform.ModuleState{
   229  			&terraform.ModuleState{
   230  				Path: []string{"root"},
   231  				Resources: map[string]*terraform.ResourceState{
   232  					"test_instance.foo": &terraform.ResourceState{
   233  						Type: "test_instance",
   234  						Primary: &terraform.InstanceState{
   235  							ID: "bar",
   236  							Attributes: map[string]string{
   237  								"foo": "value",
   238  								"bar": "value",
   239  							},
   240  						},
   241  					},
   242  				},
   243  			},
   244  		},
   245  	}
   246  
   247  	statePath := testStateFile(t, state)
   248  	stateOutPath := statePath + ".out"
   249  
   250  	p := testProvider()
   251  	ui := new(cli.MockUi)
   252  	c := &StateMvCommand{
   253  		StateMeta{
   254  			Meta: Meta{
   255  				testingOverrides: metaOverridesForProvider(p),
   256  				Ui:               ui,
   257  			},
   258  		},
   259  	}
   260  
   261  	args := []string{
   262  		"-state", statePath,
   263  		"-state-out", stateOutPath,
   264  		"test_instance.foo",
   265  		"test_instance.bar",
   266  	}
   267  	if code := c.Run(args); code != 0 {
   268  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   269  	}
   270  
   271  	// Test it is correct
   272  	testStateOutput(t, stateOutPath, testStateMvOutput_stateOut)
   273  	testStateOutput(t, statePath, testStateMvOutput_stateOutSrc)
   274  
   275  	// Test we have backups
   276  	backups := testStateBackups(t, filepath.Dir(statePath))
   277  	if len(backups) != 1 {
   278  		t.Fatalf("bad: %#v", backups)
   279  	}
   280  	testStateOutput(t, backups[0], testStateMvOutput_stateOutOriginal)
   281  }
   282  
   283  func TestStateMv_stateOutExisting(t *testing.T) {
   284  	stateSrc := &terraform.State{
   285  		Modules: []*terraform.ModuleState{
   286  			&terraform.ModuleState{
   287  				Path: []string{"root"},
   288  				Resources: map[string]*terraform.ResourceState{
   289  					"test_instance.foo": &terraform.ResourceState{
   290  						Type: "test_instance",
   291  						Primary: &terraform.InstanceState{
   292  							ID: "bar",
   293  							Attributes: map[string]string{
   294  								"foo": "value",
   295  								"bar": "value",
   296  							},
   297  						},
   298  					},
   299  				},
   300  			},
   301  		},
   302  	}
   303  
   304  	statePath := testStateFile(t, stateSrc)
   305  
   306  	stateDst := &terraform.State{
   307  		Modules: []*terraform.ModuleState{
   308  			&terraform.ModuleState{
   309  				Path: []string{"root"},
   310  				Resources: map[string]*terraform.ResourceState{
   311  					"test_instance.qux": &terraform.ResourceState{
   312  						Type: "test_instance",
   313  						Primary: &terraform.InstanceState{
   314  							ID: "bar",
   315  						},
   316  					},
   317  				},
   318  			},
   319  		},
   320  	}
   321  
   322  	stateOutPath := testStateFile(t, stateDst)
   323  
   324  	p := testProvider()
   325  	ui := new(cli.MockUi)
   326  	c := &StateMvCommand{
   327  		StateMeta{
   328  			Meta: Meta{
   329  				testingOverrides: metaOverridesForProvider(p),
   330  				Ui:               ui,
   331  			},
   332  		},
   333  	}
   334  
   335  	args := []string{
   336  		"-state", statePath,
   337  		"-state-out", stateOutPath,
   338  		"test_instance.foo",
   339  		"test_instance.bar",
   340  	}
   341  	if code := c.Run(args); code != 0 {
   342  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   343  	}
   344  
   345  	// Test it is correct
   346  	testStateOutput(t, stateOutPath, testStateMvExisting_stateDst)
   347  	testStateOutput(t, statePath, testStateMvExisting_stateSrc)
   348  
   349  	// Test we have backups
   350  	backups := testStateBackups(t, filepath.Dir(statePath))
   351  	if len(backups) != 1 {
   352  		t.Fatalf("bad: %#v", backups)
   353  	}
   354  	testStateOutput(t, backups[0], testStateMvExisting_stateSrcOriginal)
   355  
   356  	backups = testStateBackups(t, filepath.Dir(stateOutPath))
   357  	if len(backups) != 1 {
   358  		t.Fatalf("bad: %#v", backups)
   359  	}
   360  	testStateOutput(t, backups[0], testStateMvExisting_stateDstOriginal)
   361  }
   362  
   363  func TestStateMv_noState(t *testing.T) {
   364  	tmp, cwd := testCwd(t)
   365  	defer testFixCwd(t, tmp, cwd)
   366  
   367  	p := testProvider()
   368  	ui := new(cli.MockUi)
   369  	c := &StateMvCommand{
   370  		StateMeta{
   371  			Meta: Meta{
   372  				testingOverrides: metaOverridesForProvider(p),
   373  				Ui:               ui,
   374  			},
   375  		},
   376  	}
   377  
   378  	args := []string{"from", "to"}
   379  	if code := c.Run(args); code != 1 {
   380  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   381  	}
   382  }
   383  
   384  func TestStateMv_stateOutNew_count(t *testing.T) {
   385  	state := &terraform.State{
   386  		Modules: []*terraform.ModuleState{
   387  			&terraform.ModuleState{
   388  				Path: []string{"root"},
   389  				Resources: map[string]*terraform.ResourceState{
   390  					"test_instance.foo.0": &terraform.ResourceState{
   391  						Type: "test_instance",
   392  						Primary: &terraform.InstanceState{
   393  							ID: "foo",
   394  							Attributes: map[string]string{
   395  								"foo": "value",
   396  								"bar": "value",
   397  							},
   398  						},
   399  					},
   400  
   401  					"test_instance.foo.1": &terraform.ResourceState{
   402  						Type: "test_instance",
   403  						Primary: &terraform.InstanceState{
   404  							ID: "bar",
   405  							Attributes: map[string]string{
   406  								"foo": "value",
   407  								"bar": "value",
   408  							},
   409  						},
   410  					},
   411  
   412  					"test_instance.bar": &terraform.ResourceState{
   413  						Type: "test_instance",
   414  						Primary: &terraform.InstanceState{
   415  							ID: "bar",
   416  							Attributes: map[string]string{
   417  								"foo": "value",
   418  								"bar": "value",
   419  							},
   420  						},
   421  					},
   422  				},
   423  			},
   424  		},
   425  	}
   426  
   427  	statePath := testStateFile(t, state)
   428  	stateOutPath := statePath + ".out"
   429  
   430  	p := testProvider()
   431  	ui := new(cli.MockUi)
   432  	c := &StateMvCommand{
   433  		StateMeta{
   434  			Meta: Meta{
   435  				testingOverrides: metaOverridesForProvider(p),
   436  				Ui:               ui,
   437  			},
   438  		},
   439  	}
   440  
   441  	args := []string{
   442  		"-state", statePath,
   443  		"-state-out", stateOutPath,
   444  		"test_instance.foo",
   445  		"test_instance.bar",
   446  	}
   447  	if code := c.Run(args); code != 0 {
   448  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   449  	}
   450  
   451  	// Test it is correct
   452  	testStateOutput(t, stateOutPath, testStateMvCount_stateOut)
   453  	testStateOutput(t, statePath, testStateMvCount_stateOutSrc)
   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], testStateMvCount_stateOutOriginal)
   461  }
   462  
   463  // Modules with more than 10 resources were sorted lexically, causing the
   464  // indexes in the new location to change.
   465  func TestStateMv_stateOutNew_largeCount(t *testing.T) {
   466  	state := &terraform.State{
   467  		Modules: []*terraform.ModuleState{
   468  			&terraform.ModuleState{
   469  				Path: []string{"root"},
   470  				Resources: map[string]*terraform.ResourceState{
   471  					"test_instance.foo.0": &terraform.ResourceState{
   472  						Type: "test_instance",
   473  						Primary: &terraform.InstanceState{
   474  							ID: "foo0",
   475  							Attributes: map[string]string{
   476  								"foo": "value",
   477  								"bar": "value",
   478  							},
   479  						},
   480  					},
   481  
   482  					"test_instance.foo.1": &terraform.ResourceState{
   483  						Type: "test_instance",
   484  						Primary: &terraform.InstanceState{
   485  							ID: "foo1",
   486  							Attributes: map[string]string{
   487  								"foo": "value",
   488  								"bar": "value",
   489  							},
   490  						},
   491  					},
   492  
   493  					"test_instance.foo.2": &terraform.ResourceState{
   494  						Type: "test_instance",
   495  						Primary: &terraform.InstanceState{
   496  							ID: "foo2",
   497  							Attributes: map[string]string{
   498  								"foo": "value",
   499  								"bar": "value",
   500  							},
   501  						},
   502  					},
   503  
   504  					"test_instance.foo.3": &terraform.ResourceState{
   505  						Type: "test_instance",
   506  						Primary: &terraform.InstanceState{
   507  							ID: "foo3",
   508  							Attributes: map[string]string{
   509  								"foo": "value",
   510  								"bar": "value",
   511  							},
   512  						},
   513  					},
   514  
   515  					"test_instance.foo.4": &terraform.ResourceState{
   516  						Type: "test_instance",
   517  						Primary: &terraform.InstanceState{
   518  							ID: "foo4",
   519  							Attributes: map[string]string{
   520  								"foo": "value",
   521  								"bar": "value",
   522  							},
   523  						},
   524  					},
   525  
   526  					"test_instance.foo.5": &terraform.ResourceState{
   527  						Type: "test_instance",
   528  						Primary: &terraform.InstanceState{
   529  							ID: "foo5",
   530  							Attributes: map[string]string{
   531  								"foo": "value",
   532  								"bar": "value",
   533  							},
   534  						},
   535  					},
   536  
   537  					"test_instance.foo.6": &terraform.ResourceState{
   538  						Type: "test_instance",
   539  						Primary: &terraform.InstanceState{
   540  							ID: "foo6",
   541  							Attributes: map[string]string{
   542  								"foo": "value",
   543  								"bar": "value",
   544  							},
   545  						},
   546  					},
   547  
   548  					"test_instance.foo.7": &terraform.ResourceState{
   549  						Type: "test_instance",
   550  						Primary: &terraform.InstanceState{
   551  							ID: "foo7",
   552  							Attributes: map[string]string{
   553  								"foo": "value",
   554  								"bar": "value",
   555  							},
   556  						},
   557  					},
   558  
   559  					"test_instance.foo.8": &terraform.ResourceState{
   560  						Type: "test_instance",
   561  						Primary: &terraform.InstanceState{
   562  							ID: "foo8",
   563  							Attributes: map[string]string{
   564  								"foo": "value",
   565  								"bar": "value",
   566  							},
   567  						},
   568  					},
   569  
   570  					"test_instance.foo.9": &terraform.ResourceState{
   571  						Type: "test_instance",
   572  						Primary: &terraform.InstanceState{
   573  							ID: "foo9",
   574  							Attributes: map[string]string{
   575  								"foo": "value",
   576  								"bar": "value",
   577  							},
   578  						},
   579  					},
   580  
   581  					"test_instance.foo.10": &terraform.ResourceState{
   582  						Type: "test_instance",
   583  						Primary: &terraform.InstanceState{
   584  							ID: "foo10",
   585  							Attributes: map[string]string{
   586  								"foo": "value",
   587  								"bar": "value",
   588  							},
   589  						},
   590  					},
   591  
   592  					"test_instance.bar": &terraform.ResourceState{
   593  						Type: "test_instance",
   594  						Primary: &terraform.InstanceState{
   595  							ID: "bar",
   596  							Attributes: map[string]string{
   597  								"foo": "value",
   598  								"bar": "value",
   599  							},
   600  						},
   601  					},
   602  				},
   603  			},
   604  		},
   605  	}
   606  
   607  	statePath := testStateFile(t, state)
   608  	stateOutPath := statePath + ".out"
   609  
   610  	p := testProvider()
   611  	ui := new(cli.MockUi)
   612  	c := &StateMvCommand{
   613  		StateMeta{
   614  			Meta: Meta{
   615  				testingOverrides: metaOverridesForProvider(p),
   616  				Ui:               ui,
   617  			},
   618  		},
   619  	}
   620  
   621  	args := []string{
   622  		"-state", statePath,
   623  		"-state-out", stateOutPath,
   624  		"test_instance.foo",
   625  		"test_instance.bar",
   626  	}
   627  	if code := c.Run(args); code != 0 {
   628  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   629  	}
   630  
   631  	// Test it is correct
   632  	testStateOutput(t, stateOutPath, testStateMvLargeCount_stateOut)
   633  	testStateOutput(t, statePath, testStateMvLargeCount_stateOutSrc)
   634  
   635  	// Test we have backups
   636  	backups := testStateBackups(t, filepath.Dir(statePath))
   637  	if len(backups) != 1 {
   638  		t.Fatalf("bad: %#v", backups)
   639  	}
   640  	testStateOutput(t, backups[0], testStateMvLargeCount_stateOutOriginal)
   641  }
   642  
   643  func TestStateMv_stateOutNew_nestedModule(t *testing.T) {
   644  	state := &terraform.State{
   645  		Modules: []*terraform.ModuleState{
   646  			&terraform.ModuleState{
   647  				Path:      []string{"root"},
   648  				Resources: map[string]*terraform.ResourceState{},
   649  			},
   650  
   651  			&terraform.ModuleState{
   652  				Path:      []string{"root", "foo"},
   653  				Resources: map[string]*terraform.ResourceState{},
   654  			},
   655  
   656  			&terraform.ModuleState{
   657  				Path: []string{"root", "foo", "child1"},
   658  				Resources: map[string]*terraform.ResourceState{
   659  					"test_instance.foo": &terraform.ResourceState{
   660  						Type: "test_instance",
   661  						Primary: &terraform.InstanceState{
   662  							ID: "bar",
   663  							Attributes: map[string]string{
   664  								"foo": "value",
   665  								"bar": "value",
   666  							},
   667  						},
   668  					},
   669  				},
   670  			},
   671  
   672  			&terraform.ModuleState{
   673  				Path: []string{"root", "foo", "child2"},
   674  				Resources: map[string]*terraform.ResourceState{
   675  					"test_instance.foo": &terraform.ResourceState{
   676  						Type: "test_instance",
   677  						Primary: &terraform.InstanceState{
   678  							ID: "bar",
   679  							Attributes: map[string]string{
   680  								"foo": "value",
   681  								"bar": "value",
   682  							},
   683  						},
   684  					},
   685  				},
   686  			},
   687  		},
   688  	}
   689  
   690  	statePath := testStateFile(t, state)
   691  	stateOutPath := statePath + ".out"
   692  
   693  	p := testProvider()
   694  	ui := new(cli.MockUi)
   695  	c := &StateMvCommand{
   696  		StateMeta{
   697  			Meta: Meta{
   698  				testingOverrides: metaOverridesForProvider(p),
   699  				Ui:               ui,
   700  			},
   701  		},
   702  	}
   703  
   704  	args := []string{
   705  		"-state", statePath,
   706  		"-state-out", stateOutPath,
   707  		"module.foo",
   708  		"module.bar",
   709  	}
   710  	if code := c.Run(args); code != 0 {
   711  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   712  	}
   713  
   714  	// Test it is correct
   715  	testStateOutput(t, stateOutPath, testStateMvNestedModule_stateOut)
   716  	testStateOutput(t, statePath, testStateMvNestedModule_stateOutSrc)
   717  
   718  	// Test we have backups
   719  	backups := testStateBackups(t, filepath.Dir(statePath))
   720  	if len(backups) != 1 {
   721  		t.Fatalf("bad: %#v", backups)
   722  	}
   723  	testStateOutput(t, backups[0], testStateMvNestedModule_stateOutOriginal)
   724  }
   725  
   726  func TestStateMv_withinBackend(t *testing.T) {
   727  	td := tempDir(t)
   728  	copy.CopyDir(testFixturePath("backend-unchanged"), td)
   729  	defer os.RemoveAll(td)
   730  	defer testChdir(t, td)()
   731  
   732  	state := &terraform.State{
   733  		Modules: []*terraform.ModuleState{
   734  			&terraform.ModuleState{
   735  				Path: []string{"root"},
   736  				Resources: map[string]*terraform.ResourceState{
   737  					"test_instance.foo": &terraform.ResourceState{
   738  						Type: "test_instance",
   739  						Primary: &terraform.InstanceState{
   740  							ID: "bar",
   741  							Attributes: map[string]string{
   742  								"foo": "value",
   743  								"bar": "value",
   744  							},
   745  						},
   746  					},
   747  
   748  					"test_instance.baz": &terraform.ResourceState{
   749  						Type: "test_instance",
   750  						Primary: &terraform.InstanceState{
   751  							ID: "foo",
   752  							Attributes: map[string]string{
   753  								"foo": "value",
   754  								"bar": "value",
   755  							},
   756  						},
   757  					},
   758  				},
   759  			},
   760  		},
   761  	}
   762  
   763  	// the local backend state file is "foo"
   764  	statePath := "local-state.tfstate"
   765  	backupPath := "local-state.backup"
   766  
   767  	f, err := os.Create(statePath)
   768  	if err != nil {
   769  		t.Fatal(err)
   770  	}
   771  	defer f.Close()
   772  
   773  	if err := terraform.WriteState(state, f); err != nil {
   774  		t.Fatal(err)
   775  	}
   776  
   777  	p := testProvider()
   778  	ui := new(cli.MockUi)
   779  	c := &StateMvCommand{
   780  		StateMeta{
   781  			Meta: Meta{
   782  				testingOverrides: metaOverridesForProvider(p),
   783  				Ui:               ui,
   784  			},
   785  		},
   786  	}
   787  
   788  	args := []string{
   789  		"-backup", backupPath,
   790  		"test_instance.foo",
   791  		"test_instance.bar",
   792  	}
   793  	if code := c.Run(args); code != 0 {
   794  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   795  	}
   796  
   797  	testStateOutput(t, statePath, testStateMvOutput)
   798  	testStateOutput(t, backupPath, testStateMvOutputOriginal)
   799  }
   800  
   801  func TestStateMv_fromBackendToLocal(t *testing.T) {
   802  	td := tempDir(t)
   803  	copy.CopyDir(testFixturePath("backend-unchanged"), td)
   804  	defer os.RemoveAll(td)
   805  	defer testChdir(t, td)()
   806  
   807  	state := &terraform.State{
   808  		Modules: []*terraform.ModuleState{
   809  			&terraform.ModuleState{
   810  				Path: []string{"root"},
   811  				Resources: map[string]*terraform.ResourceState{
   812  					"test_instance.foo": &terraform.ResourceState{
   813  						Type: "test_instance",
   814  						Primary: &terraform.InstanceState{
   815  							ID: "bar",
   816  							Attributes: map[string]string{
   817  								"foo": "value",
   818  								"bar": "value",
   819  							},
   820  						},
   821  					},
   822  
   823  					"test_instance.baz": &terraform.ResourceState{
   824  						Type: "test_instance",
   825  						Primary: &terraform.InstanceState{
   826  							ID: "foo",
   827  							Attributes: map[string]string{
   828  								"foo": "value",
   829  								"bar": "value",
   830  							},
   831  						},
   832  					},
   833  				},
   834  			},
   835  		},
   836  	}
   837  
   838  	// the local backend state file is "foo"
   839  	statePath := "local-state.tfstate"
   840  
   841  	// real "local" state file
   842  	statePathOut := "real-local.tfstate"
   843  
   844  	f, err := os.Create(statePath)
   845  	if err != nil {
   846  		t.Fatal(err)
   847  	}
   848  	defer f.Close()
   849  
   850  	if err := terraform.WriteState(state, f); err != nil {
   851  		t.Fatal(err)
   852  	}
   853  
   854  	p := testProvider()
   855  	ui := new(cli.MockUi)
   856  	c := &StateMvCommand{
   857  		StateMeta{
   858  			Meta: Meta{
   859  				testingOverrides: metaOverridesForProvider(p),
   860  				Ui:               ui,
   861  			},
   862  		},
   863  	}
   864  
   865  	args := []string{
   866  		"-state-out", statePathOut,
   867  		"test_instance.foo",
   868  		"test_instance.bar",
   869  	}
   870  	if code := c.Run(args); code != 0 {
   871  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   872  	}
   873  
   874  	testStateOutput(t, statePathOut, testStateMvCount_stateOutSrc)
   875  
   876  	// the backend state should be left with only baz
   877  	testStateOutput(t, statePath, testStateMvOriginal_backend)
   878  }
   879  
   880  const testStateMvOutputOriginal = `
   881  test_instance.baz:
   882    ID = foo
   883    bar = value
   884    foo = value
   885  test_instance.foo:
   886    ID = bar
   887    bar = value
   888    foo = value
   889  `
   890  
   891  const testStateMvOutput = `
   892  test_instance.bar:
   893    ID = bar
   894    bar = value
   895    foo = value
   896  test_instance.baz:
   897    ID = foo
   898    bar = value
   899    foo = value
   900  `
   901  
   902  const testStateMvCount_stateOut = `
   903  test_instance.bar.0:
   904    ID = foo
   905    bar = value
   906    foo = value
   907  test_instance.bar.1:
   908    ID = bar
   909    bar = value
   910    foo = value
   911  `
   912  
   913  const testStateMvCount_stateOutSrc = `
   914  test_instance.bar:
   915    ID = bar
   916    bar = value
   917    foo = value
   918  `
   919  
   920  const testStateMvCount_stateOutOriginal = `
   921  test_instance.bar:
   922    ID = bar
   923    bar = value
   924    foo = value
   925  test_instance.foo.0:
   926    ID = foo
   927    bar = value
   928    foo = value
   929  test_instance.foo.1:
   930    ID = bar
   931    bar = value
   932    foo = value
   933  `
   934  
   935  const testStateMvLargeCount_stateOut = `
   936  test_instance.bar.0:
   937    ID = foo0
   938    bar = value
   939    foo = value
   940  test_instance.bar.1:
   941    ID = foo1
   942    bar = value
   943    foo = value
   944  test_instance.bar.2:
   945    ID = foo2
   946    bar = value
   947    foo = value
   948  test_instance.bar.3:
   949    ID = foo3
   950    bar = value
   951    foo = value
   952  test_instance.bar.4:
   953    ID = foo4
   954    bar = value
   955    foo = value
   956  test_instance.bar.5:
   957    ID = foo5
   958    bar = value
   959    foo = value
   960  test_instance.bar.6:
   961    ID = foo6
   962    bar = value
   963    foo = value
   964  test_instance.bar.7:
   965    ID = foo7
   966    bar = value
   967    foo = value
   968  test_instance.bar.8:
   969    ID = foo8
   970    bar = value
   971    foo = value
   972  test_instance.bar.9:
   973    ID = foo9
   974    bar = value
   975    foo = value
   976  test_instance.bar.10:
   977    ID = foo10
   978    bar = value
   979    foo = value
   980  `
   981  
   982  const testStateMvLargeCount_stateOutSrc = `
   983  test_instance.bar:
   984    ID = bar
   985    bar = value
   986    foo = value
   987  `
   988  
   989  const testStateMvLargeCount_stateOutOriginal = `
   990  test_instance.bar:
   991    ID = bar
   992    bar = value
   993    foo = value
   994  test_instance.foo.0:
   995    ID = foo0
   996    bar = value
   997    foo = value
   998  test_instance.foo.1:
   999    ID = foo1
  1000    bar = value
  1001    foo = value
  1002  test_instance.foo.2:
  1003    ID = foo2
  1004    bar = value
  1005    foo = value
  1006  test_instance.foo.3:
  1007    ID = foo3
  1008    bar = value
  1009    foo = value
  1010  test_instance.foo.4:
  1011    ID = foo4
  1012    bar = value
  1013    foo = value
  1014  test_instance.foo.5:
  1015    ID = foo5
  1016    bar = value
  1017    foo = value
  1018  test_instance.foo.6:
  1019    ID = foo6
  1020    bar = value
  1021    foo = value
  1022  test_instance.foo.7:
  1023    ID = foo7
  1024    bar = value
  1025    foo = value
  1026  test_instance.foo.8:
  1027    ID = foo8
  1028    bar = value
  1029    foo = value
  1030  test_instance.foo.9:
  1031    ID = foo9
  1032    bar = value
  1033    foo = value
  1034  test_instance.foo.10:
  1035    ID = foo10
  1036    bar = value
  1037    foo = value
  1038  `
  1039  
  1040  const testStateMvNestedModule_stateOut = `
  1041  <no state>
  1042  module.bar:
  1043    <no state>
  1044  module.bar.child1:
  1045    test_instance.foo:
  1046      ID = bar
  1047      bar = value
  1048      foo = value
  1049  module.bar.child2:
  1050    test_instance.foo:
  1051      ID = bar
  1052      bar = value
  1053      foo = value
  1054  `
  1055  
  1056  const testStateMvNestedModule_stateOutSrc = `
  1057  <no state>
  1058  `
  1059  
  1060  const testStateMvNestedModule_stateOutOriginal = `
  1061  <no state>
  1062  module.foo:
  1063    <no state>
  1064  module.foo.child1:
  1065    test_instance.foo:
  1066      ID = bar
  1067      bar = value
  1068      foo = value
  1069  module.foo.child2:
  1070    test_instance.foo:
  1071      ID = bar
  1072      bar = value
  1073      foo = value
  1074  `
  1075  
  1076  const testStateMvOutput_stateOut = `
  1077  test_instance.bar:
  1078    ID = bar
  1079    bar = value
  1080    foo = value
  1081  `
  1082  
  1083  const testStateMvOutput_stateOutSrc = `
  1084  <no state>
  1085  `
  1086  
  1087  const testStateMvOutput_stateOutOriginal = `
  1088  test_instance.foo:
  1089    ID = bar
  1090    bar = value
  1091    foo = value
  1092  `
  1093  
  1094  const testStateMvExisting_stateSrc = `
  1095  <no state>
  1096  `
  1097  
  1098  const testStateMvExisting_stateDst = `
  1099  test_instance.bar:
  1100    ID = bar
  1101    bar = value
  1102    foo = value
  1103  test_instance.qux:
  1104    ID = bar
  1105  `
  1106  
  1107  const testStateMvExisting_stateSrcOriginal = `
  1108  test_instance.foo:
  1109    ID = bar
  1110    bar = value
  1111    foo = value
  1112  `
  1113  
  1114  const testStateMvExisting_stateDstOriginal = `
  1115  test_instance.qux:
  1116    ID = bar
  1117  `
  1118  
  1119  const testStateMvOriginal_backend = `
  1120  test_instance.baz:
  1121    ID = foo
  1122    bar = value
  1123    foo = value
  1124  `