github.com/muratcelep/terraform@v1.1.0-beta2-not-internal-4/not-internal/command/state_rm_test.go (about)

     1  package command
     2  
     3  import (
     4  	"os"
     5  	"path/filepath"
     6  	"strings"
     7  	"testing"
     8  
     9  	"github.com/mitchellh/cli"
    10  
    11  	"github.com/muratcelep/terraform/not-internal/addrs"
    12  	"github.com/muratcelep/terraform/not-internal/states"
    13  )
    14  
    15  func TestStateRm(t *testing.T) {
    16  	state := states.BuildState(func(s *states.SyncState) {
    17  		s.SetResourceInstanceCurrent(
    18  			addrs.Resource{
    19  				Mode: addrs.ManagedResourceMode,
    20  				Type: "test_instance",
    21  				Name: "foo",
    22  			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
    23  			&states.ResourceInstanceObjectSrc{
    24  				AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`),
    25  				Status:    states.ObjectReady,
    26  			},
    27  			addrs.AbsProviderConfig{
    28  				Provider: addrs.NewDefaultProvider("test"),
    29  				Module:   addrs.RootModule,
    30  			},
    31  		)
    32  		s.SetResourceInstanceCurrent(
    33  			addrs.Resource{
    34  				Mode: addrs.ManagedResourceMode,
    35  				Type: "test_instance",
    36  				Name: "bar",
    37  			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
    38  			&states.ResourceInstanceObjectSrc{
    39  				AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`),
    40  				Status:    states.ObjectReady,
    41  			},
    42  			addrs.AbsProviderConfig{
    43  				Provider: addrs.NewDefaultProvider("test"),
    44  				Module:   addrs.RootModule,
    45  			},
    46  		)
    47  	})
    48  	statePath := testStateFile(t, state)
    49  
    50  	p := testProvider()
    51  	ui := new(cli.MockUi)
    52  	view, _ := testView(t)
    53  	c := &StateRmCommand{
    54  		StateMeta{
    55  			Meta: Meta{
    56  				testingOverrides: metaOverridesForProvider(p),
    57  				Ui:               ui,
    58  				View:             view,
    59  			},
    60  		},
    61  	}
    62  
    63  	args := []string{
    64  		"-state", statePath,
    65  		"test_instance.foo",
    66  	}
    67  	if code := c.Run(args); code != 0 {
    68  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
    69  	}
    70  
    71  	// Test it is correct
    72  	testStateOutput(t, statePath, testStateRmOutput)
    73  
    74  	// Test we have backups
    75  	backups := testStateBackups(t, filepath.Dir(statePath))
    76  	if len(backups) != 1 {
    77  		t.Fatalf("bad: %#v", backups)
    78  	}
    79  	testStateOutput(t, backups[0], testStateRmOutputOriginal)
    80  }
    81  
    82  func TestStateRmNotChildModule(t *testing.T) {
    83  	state := states.BuildState(func(s *states.SyncState) {
    84  		s.SetResourceInstanceCurrent(
    85  			addrs.Resource{
    86  				Mode: addrs.ManagedResourceMode,
    87  				Type: "test_instance",
    88  				Name: "foo",
    89  			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
    90  			&states.ResourceInstanceObjectSrc{
    91  				AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`),
    92  				Status:    states.ObjectReady,
    93  			},
    94  			addrs.AbsProviderConfig{
    95  				Provider: addrs.NewDefaultProvider("test"),
    96  				Module:   addrs.RootModule,
    97  			},
    98  		)
    99  		// This second instance has the same local address as the first but
   100  		// is in a child module. Older versions of Terraform would incorrectly
   101  		// remove this one too, since they failed to check the module address.
   102  		s.SetResourceInstanceCurrent(
   103  			addrs.Resource{
   104  				Mode: addrs.ManagedResourceMode,
   105  				Type: "test_instance",
   106  				Name: "foo",
   107  			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance.Child("child", addrs.NoKey)),
   108  			&states.ResourceInstanceObjectSrc{
   109  				AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`),
   110  				Status:    states.ObjectReady,
   111  			},
   112  			addrs.AbsProviderConfig{
   113  				Provider: addrs.NewDefaultProvider("test"),
   114  				Module:   addrs.RootModule,
   115  			},
   116  		)
   117  	})
   118  	statePath := testStateFile(t, state)
   119  
   120  	p := testProvider()
   121  	ui := new(cli.MockUi)
   122  	view, _ := testView(t)
   123  	c := &StateRmCommand{
   124  		StateMeta{
   125  			Meta: Meta{
   126  				testingOverrides: metaOverridesForProvider(p),
   127  				Ui:               ui,
   128  				View:             view,
   129  			},
   130  		},
   131  	}
   132  
   133  	args := []string{
   134  		"-state", statePath,
   135  		"test_instance.foo",
   136  	}
   137  	if code := c.Run(args); code != 0 {
   138  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   139  	}
   140  
   141  	// Test it is correct
   142  	testStateOutput(t, statePath, `
   143  <no state>
   144  module.child:
   145    test_instance.foo:
   146      ID = foo
   147      provider = provider["registry.terraform.io/hashicorp/test"]
   148      bar = value
   149      foo = value
   150  `)
   151  
   152  	// Test we have backups
   153  	backups := testStateBackups(t, filepath.Dir(statePath))
   154  	if len(backups) != 1 {
   155  		t.Fatalf("bad: %#v", backups)
   156  	}
   157  	testStateOutput(t, backups[0], `
   158  test_instance.foo:
   159    ID = bar
   160    provider = provider["registry.terraform.io/hashicorp/test"]
   161    bar = value
   162    foo = value
   163  
   164  module.child:
   165    test_instance.foo:
   166      ID = foo
   167      provider = provider["registry.terraform.io/hashicorp/test"]
   168      bar = value
   169      foo = value
   170  `)
   171  }
   172  
   173  func TestStateRmNoArgs(t *testing.T) {
   174  	state := states.BuildState(func(s *states.SyncState) {
   175  		s.SetResourceInstanceCurrent(
   176  			addrs.Resource{
   177  				Mode: addrs.ManagedResourceMode,
   178  				Type: "test_instance",
   179  				Name: "foo",
   180  			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
   181  			&states.ResourceInstanceObjectSrc{
   182  				AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`),
   183  				Status:    states.ObjectReady,
   184  			},
   185  			addrs.AbsProviderConfig{
   186  				Provider: addrs.NewDefaultProvider("test"),
   187  				Module:   addrs.RootModule,
   188  			},
   189  		)
   190  		s.SetResourceInstanceCurrent(
   191  			addrs.Resource{
   192  				Mode: addrs.ManagedResourceMode,
   193  				Type: "test_instance",
   194  				Name: "bar",
   195  			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
   196  			&states.ResourceInstanceObjectSrc{
   197  				AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`),
   198  				Status:    states.ObjectReady,
   199  			},
   200  			addrs.AbsProviderConfig{
   201  				Provider: addrs.NewDefaultProvider("test"),
   202  				Module:   addrs.RootModule,
   203  			},
   204  		)
   205  	})
   206  	statePath := testStateFile(t, state)
   207  
   208  	p := testProvider()
   209  	ui := new(cli.MockUi)
   210  	view, _ := testView(t)
   211  	c := &StateRmCommand{
   212  		StateMeta{
   213  			Meta: Meta{
   214  				testingOverrides: metaOverridesForProvider(p),
   215  				Ui:               ui,
   216  				View:             view,
   217  			},
   218  		},
   219  	}
   220  
   221  	args := []string{
   222  		"-state", statePath,
   223  	}
   224  	if code := c.Run(args); code == 0 {
   225  		t.Errorf("expected non-zero exit code, got: %d", code)
   226  	}
   227  
   228  	if msg := ui.ErrorWriter.String(); !strings.Contains(msg, "At least one address") {
   229  		t.Errorf("not the error we were looking for:\n%s", msg)
   230  	}
   231  
   232  }
   233  
   234  func TestStateRmNonExist(t *testing.T) {
   235  	state := states.BuildState(func(s *states.SyncState) {
   236  		s.SetResourceInstanceCurrent(
   237  			addrs.Resource{
   238  				Mode: addrs.ManagedResourceMode,
   239  				Type: "test_instance",
   240  				Name: "foo",
   241  			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
   242  			&states.ResourceInstanceObjectSrc{
   243  				AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`),
   244  				Status:    states.ObjectReady,
   245  			},
   246  			addrs.AbsProviderConfig{
   247  				Provider: addrs.NewDefaultProvider("test"),
   248  				Module:   addrs.RootModule,
   249  			},
   250  		)
   251  		s.SetResourceInstanceCurrent(
   252  			addrs.Resource{
   253  				Mode: addrs.ManagedResourceMode,
   254  				Type: "test_instance",
   255  				Name: "bar",
   256  			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
   257  			&states.ResourceInstanceObjectSrc{
   258  				AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`),
   259  				Status:    states.ObjectReady,
   260  			},
   261  			addrs.AbsProviderConfig{
   262  				Provider: addrs.NewDefaultProvider("test"),
   263  				Module:   addrs.RootModule,
   264  			},
   265  		)
   266  	})
   267  	statePath := testStateFile(t, state)
   268  
   269  	p := testProvider()
   270  	ui := new(cli.MockUi)
   271  	view, _ := testView(t)
   272  	c := &StateRmCommand{
   273  		StateMeta{
   274  			Meta: Meta{
   275  				testingOverrides: metaOverridesForProvider(p),
   276  				Ui:               ui,
   277  				View:             view,
   278  			},
   279  		},
   280  	}
   281  
   282  	args := []string{
   283  		"-state", statePath,
   284  		"test_instance.baz", // doesn't exist in the state constructed above
   285  	}
   286  	if code := c.Run(args); code != 1 {
   287  		t.Fatalf("expected exit status %d, got: %d", 1, code)
   288  	}
   289  }
   290  
   291  func TestStateRm_backupExplicit(t *testing.T) {
   292  	state := states.BuildState(func(s *states.SyncState) {
   293  		s.SetResourceInstanceCurrent(
   294  			addrs.Resource{
   295  				Mode: addrs.ManagedResourceMode,
   296  				Type: "test_instance",
   297  				Name: "foo",
   298  			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
   299  			&states.ResourceInstanceObjectSrc{
   300  				AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`),
   301  				Status:    states.ObjectReady,
   302  			},
   303  			addrs.AbsProviderConfig{
   304  				Provider: addrs.NewDefaultProvider("test"),
   305  				Module:   addrs.RootModule,
   306  			},
   307  		)
   308  		s.SetResourceInstanceCurrent(
   309  			addrs.Resource{
   310  				Mode: addrs.ManagedResourceMode,
   311  				Type: "test_instance",
   312  				Name: "bar",
   313  			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
   314  			&states.ResourceInstanceObjectSrc{
   315  				AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`),
   316  				Status:    states.ObjectReady,
   317  			},
   318  			addrs.AbsProviderConfig{
   319  				Provider: addrs.NewDefaultProvider("test"),
   320  				Module:   addrs.RootModule,
   321  			},
   322  		)
   323  	})
   324  	statePath := testStateFile(t, state)
   325  	backupPath := statePath + ".backup.test"
   326  
   327  	p := testProvider()
   328  	ui := new(cli.MockUi)
   329  	view, _ := testView(t)
   330  	c := &StateRmCommand{
   331  		StateMeta{
   332  			Meta: Meta{
   333  				testingOverrides: metaOverridesForProvider(p),
   334  				Ui:               ui,
   335  				View:             view,
   336  			},
   337  		},
   338  	}
   339  
   340  	args := []string{
   341  		"-backup", backupPath,
   342  		"-state", statePath,
   343  		"test_instance.foo",
   344  	}
   345  	if code := c.Run(args); code != 0 {
   346  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   347  	}
   348  
   349  	// Test it is correct
   350  	testStateOutput(t, statePath, testStateRmOutput)
   351  
   352  	// Test backup
   353  	testStateOutput(t, backupPath, testStateRmOutputOriginal)
   354  }
   355  
   356  func TestStateRm_noState(t *testing.T) {
   357  	tmp, cwd := testCwd(t)
   358  	defer testFixCwd(t, tmp, cwd)
   359  
   360  	p := testProvider()
   361  	ui := new(cli.MockUi)
   362  	view, _ := testView(t)
   363  	c := &StateRmCommand{
   364  		StateMeta{
   365  			Meta: Meta{
   366  				testingOverrides: metaOverridesForProvider(p),
   367  				Ui:               ui,
   368  				View:             view,
   369  			},
   370  		},
   371  	}
   372  
   373  	args := []string{"foo"}
   374  	if code := c.Run(args); code != 1 {
   375  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   376  	}
   377  }
   378  
   379  func TestStateRm_needsInit(t *testing.T) {
   380  	td := tempDir(t)
   381  	testCopyDir(t, testFixturePath("backend-change"), td)
   382  	defer os.RemoveAll(td)
   383  	defer testChdir(t, td)()
   384  
   385  	p := testProvider()
   386  	ui := new(cli.MockUi)
   387  	view, _ := testView(t)
   388  	c := &StateRmCommand{
   389  		StateMeta{
   390  			Meta: Meta{
   391  				testingOverrides: metaOverridesForProvider(p),
   392  				Ui:               ui,
   393  				View:             view,
   394  			},
   395  		},
   396  	}
   397  
   398  	args := []string{"foo"}
   399  	if code := c.Run(args); code == 0 {
   400  		t.Fatalf("expected error output, got:\n%s", ui.OutputWriter.String())
   401  	}
   402  
   403  	if !strings.Contains(ui.ErrorWriter.String(), "Backend initialization") {
   404  		t.Fatalf("expected initialization error, got:\n%s", ui.ErrorWriter.String())
   405  	}
   406  }
   407  
   408  func TestStateRm_backendState(t *testing.T) {
   409  	td := tempDir(t)
   410  	testCopyDir(t, testFixturePath("backend-unchanged"), td)
   411  	defer os.RemoveAll(td)
   412  	defer testChdir(t, td)()
   413  
   414  	state := states.BuildState(func(s *states.SyncState) {
   415  		s.SetResourceInstanceCurrent(
   416  			addrs.Resource{
   417  				Mode: addrs.ManagedResourceMode,
   418  				Type: "test_instance",
   419  				Name: "foo",
   420  			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
   421  			&states.ResourceInstanceObjectSrc{
   422  				AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`),
   423  				Status:    states.ObjectReady,
   424  			},
   425  			addrs.AbsProviderConfig{
   426  				Provider: addrs.NewDefaultProvider("test"),
   427  				Module:   addrs.RootModule,
   428  			},
   429  		)
   430  		s.SetResourceInstanceCurrent(
   431  			addrs.Resource{
   432  				Mode: addrs.ManagedResourceMode,
   433  				Type: "test_instance",
   434  				Name: "bar",
   435  			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
   436  			&states.ResourceInstanceObjectSrc{
   437  				AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`),
   438  				Status:    states.ObjectReady,
   439  			},
   440  			addrs.AbsProviderConfig{
   441  				Provider: addrs.NewDefaultProvider("test"),
   442  				Module:   addrs.RootModule,
   443  			},
   444  		)
   445  	})
   446  
   447  	statePath := "local-state.tfstate"
   448  	backupPath := "local-state.backup"
   449  
   450  	f, err := os.Create(statePath)
   451  	if err != nil {
   452  		t.Fatalf("failed to create state file %s: %s", statePath, err)
   453  	}
   454  	defer f.Close()
   455  
   456  	err = writeStateForTesting(state, f)
   457  	if err != nil {
   458  		t.Fatalf("failed to write state to file %s: %s", statePath, err)
   459  	}
   460  
   461  	p := testProvider()
   462  	ui := new(cli.MockUi)
   463  	view, _ := testView(t)
   464  	c := &StateRmCommand{
   465  		StateMeta{
   466  			Meta: Meta{
   467  				testingOverrides: metaOverridesForProvider(p),
   468  				Ui:               ui,
   469  				View:             view,
   470  			},
   471  		},
   472  	}
   473  
   474  	args := []string{
   475  		"-backup", backupPath,
   476  		"test_instance.foo",
   477  	}
   478  	if code := c.Run(args); code != 0 {
   479  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   480  	}
   481  
   482  	// Test it is correct
   483  	testStateOutput(t, statePath, testStateRmOutput)
   484  
   485  	// Test backup
   486  	testStateOutput(t, backupPath, testStateRmOutputOriginal)
   487  }
   488  
   489  const testStateRmOutputOriginal = `
   490  test_instance.bar:
   491    ID = foo
   492    provider = provider["registry.terraform.io/hashicorp/test"]
   493    bar = value
   494    foo = value
   495  test_instance.foo:
   496    ID = bar
   497    provider = provider["registry.terraform.io/hashicorp/test"]
   498    bar = value
   499    foo = value
   500  `
   501  
   502  const testStateRmOutput = `
   503  test_instance.bar:
   504    ID = foo
   505    provider = provider["registry.terraform.io/hashicorp/test"]
   506    bar = value
   507    foo = value
   508  `