github.com/pulumi/terraform@v1.4.0/pkg/command/untaint_test.go (about)

     1  package command
     2  
     3  import (
     4  	"os"
     5  	"strings"
     6  	"testing"
     7  
     8  	"github.com/google/go-cmp/cmp"
     9  	"github.com/pulumi/terraform/pkg/addrs"
    10  	"github.com/pulumi/terraform/pkg/states"
    11  	"github.com/mitchellh/cli"
    12  )
    13  
    14  func TestUntaint(t *testing.T) {
    15  	state := states.BuildState(func(s *states.SyncState) {
    16  		s.SetResourceInstanceCurrent(
    17  			addrs.Resource{
    18  				Mode: addrs.ManagedResourceMode,
    19  				Type: "test_instance",
    20  				Name: "foo",
    21  			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
    22  			&states.ResourceInstanceObjectSrc{
    23  				AttrsJSON: []byte(`{"id":"bar"}`),
    24  				Status:    states.ObjectTainted,
    25  			},
    26  			addrs.AbsProviderConfig{
    27  				Provider: addrs.NewDefaultProvider("test"),
    28  				Module:   addrs.RootModule,
    29  			},
    30  		)
    31  	})
    32  	statePath := testStateFile(t, state)
    33  
    34  	ui := new(cli.MockUi)
    35  	view, _ := testView(t)
    36  	c := &UntaintCommand{
    37  		Meta: Meta{
    38  			Ui:   ui,
    39  			View: view,
    40  		},
    41  	}
    42  
    43  	args := []string{
    44  		"-state", statePath,
    45  		"test_instance.foo",
    46  	}
    47  	if code := c.Run(args); code != 0 {
    48  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
    49  	}
    50  
    51  	expected := strings.TrimSpace(`
    52  test_instance.foo:
    53    ID = bar
    54    provider = provider["registry.terraform.io/hashicorp/test"]
    55  	`)
    56  	testStateOutput(t, statePath, expected)
    57  }
    58  
    59  func TestUntaint_lockedState(t *testing.T) {
    60  	state := states.BuildState(func(s *states.SyncState) {
    61  		s.SetResourceInstanceCurrent(
    62  			addrs.Resource{
    63  				Mode: addrs.ManagedResourceMode,
    64  				Type: "test_instance",
    65  				Name: "foo",
    66  			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
    67  			&states.ResourceInstanceObjectSrc{
    68  				AttrsJSON: []byte(`{"id":"bar"}`),
    69  				Status:    states.ObjectTainted,
    70  			},
    71  			addrs.AbsProviderConfig{
    72  				Provider: addrs.NewDefaultProvider("test"),
    73  				Module:   addrs.RootModule,
    74  			},
    75  		)
    76  	})
    77  	statePath := testStateFile(t, state)
    78  	unlock, err := testLockState(t, testDataDir, statePath)
    79  	if err != nil {
    80  		t.Fatal(err)
    81  	}
    82  	defer unlock()
    83  
    84  	ui := new(cli.MockUi)
    85  	view, _ := testView(t)
    86  	c := &UntaintCommand{
    87  		Meta: Meta{
    88  			Ui:   ui,
    89  			View: view,
    90  		},
    91  	}
    92  
    93  	args := []string{
    94  		"-state", statePath,
    95  		"test_instance.foo",
    96  	}
    97  	if code := c.Run(args); code == 0 {
    98  		t.Fatal("expected error")
    99  	}
   100  
   101  	output := ui.ErrorWriter.String()
   102  	if !strings.Contains(output, "lock") {
   103  		t.Fatal("command output does not look like a lock error:", output)
   104  	}
   105  }
   106  
   107  func TestUntaint_backup(t *testing.T) {
   108  	// Get a temp cwd
   109  	testCwd(t)
   110  
   111  	// Write the temp state
   112  	state := states.BuildState(func(s *states.SyncState) {
   113  		s.SetResourceInstanceCurrent(
   114  			addrs.Resource{
   115  				Mode: addrs.ManagedResourceMode,
   116  				Type: "test_instance",
   117  				Name: "foo",
   118  			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
   119  			&states.ResourceInstanceObjectSrc{
   120  				AttrsJSON: []byte(`{"id":"bar"}`),
   121  				Status:    states.ObjectTainted,
   122  			},
   123  			addrs.AbsProviderConfig{
   124  				Provider: addrs.NewDefaultProvider("test"),
   125  				Module:   addrs.RootModule,
   126  			},
   127  		)
   128  	})
   129  	testStateFileDefault(t, state)
   130  
   131  	ui := new(cli.MockUi)
   132  	view, _ := testView(t)
   133  	c := &UntaintCommand{
   134  		Meta: Meta{
   135  			Ui:   ui,
   136  			View: view,
   137  		},
   138  	}
   139  
   140  	args := []string{
   141  		"test_instance.foo",
   142  	}
   143  	if code := c.Run(args); code != 0 {
   144  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   145  	}
   146  
   147  	// Backup is still tainted
   148  	testStateOutput(t, DefaultStateFilename+".backup", strings.TrimSpace(`
   149  test_instance.foo: (tainted)
   150    ID = bar
   151    provider = provider["registry.terraform.io/hashicorp/test"]
   152  	`))
   153  
   154  	// State is untainted
   155  	testStateOutput(t, DefaultStateFilename, strings.TrimSpace(`
   156  test_instance.foo:
   157    ID = bar
   158    provider = provider["registry.terraform.io/hashicorp/test"]
   159  	`))
   160  }
   161  
   162  func TestUntaint_backupDisable(t *testing.T) {
   163  	// Get a temp cwd
   164  	testCwd(t)
   165  
   166  	// Write the temp state
   167  	state := states.BuildState(func(s *states.SyncState) {
   168  		s.SetResourceInstanceCurrent(
   169  			addrs.Resource{
   170  				Mode: addrs.ManagedResourceMode,
   171  				Type: "test_instance",
   172  				Name: "foo",
   173  			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
   174  			&states.ResourceInstanceObjectSrc{
   175  				AttrsJSON: []byte(`{"id":"bar"}`),
   176  				Status:    states.ObjectTainted,
   177  			},
   178  			addrs.AbsProviderConfig{
   179  				Provider: addrs.NewDefaultProvider("test"),
   180  				Module:   addrs.RootModule,
   181  			},
   182  		)
   183  	})
   184  	testStateFileDefault(t, state)
   185  
   186  	ui := new(cli.MockUi)
   187  	view, _ := testView(t)
   188  	c := &UntaintCommand{
   189  		Meta: Meta{
   190  			Ui:   ui,
   191  			View: view,
   192  		},
   193  	}
   194  
   195  	args := []string{
   196  		"-backup", "-",
   197  		"test_instance.foo",
   198  	}
   199  	if code := c.Run(args); code != 0 {
   200  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   201  	}
   202  
   203  	if _, err := os.Stat(DefaultStateFilename + ".backup"); err == nil {
   204  		t.Fatal("backup path should not exist")
   205  	}
   206  
   207  	testStateOutput(t, DefaultStateFilename, strings.TrimSpace(`
   208  test_instance.foo:
   209    ID = bar
   210    provider = provider["registry.terraform.io/hashicorp/test"]
   211  	`))
   212  }
   213  
   214  func TestUntaint_badState(t *testing.T) {
   215  	ui := new(cli.MockUi)
   216  	view, _ := testView(t)
   217  	c := &UntaintCommand{
   218  		Meta: Meta{
   219  			Ui:   ui,
   220  			View: view,
   221  		},
   222  	}
   223  
   224  	args := []string{
   225  		"-state", "i-should-not-exist-ever",
   226  		"foo",
   227  	}
   228  	if code := c.Run(args); code != 1 {
   229  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   230  	}
   231  }
   232  
   233  func TestUntaint_defaultState(t *testing.T) {
   234  	// Get a temp cwd
   235  	testCwd(t)
   236  
   237  	// Write the temp state
   238  	state := states.BuildState(func(s *states.SyncState) {
   239  		s.SetResourceInstanceCurrent(
   240  			addrs.Resource{
   241  				Mode: addrs.ManagedResourceMode,
   242  				Type: "test_instance",
   243  				Name: "foo",
   244  			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
   245  			&states.ResourceInstanceObjectSrc{
   246  				AttrsJSON: []byte(`{"id":"bar"}`),
   247  				Status:    states.ObjectTainted,
   248  			},
   249  			addrs.AbsProviderConfig{
   250  				Provider: addrs.NewDefaultProvider("test"),
   251  				Module:   addrs.RootModule,
   252  			},
   253  		)
   254  	})
   255  	testStateFileDefault(t, state)
   256  
   257  	ui := new(cli.MockUi)
   258  	view, _ := testView(t)
   259  	c := &UntaintCommand{
   260  		Meta: Meta{
   261  			Ui:   ui,
   262  			View: view,
   263  		},
   264  	}
   265  
   266  	args := []string{
   267  		"test_instance.foo",
   268  	}
   269  	if code := c.Run(args); code != 0 {
   270  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   271  	}
   272  
   273  	testStateOutput(t, DefaultStateFilename, strings.TrimSpace(`
   274  test_instance.foo:
   275    ID = bar
   276    provider = provider["registry.terraform.io/hashicorp/test"]
   277  	`))
   278  }
   279  
   280  func TestUntaint_defaultWorkspaceState(t *testing.T) {
   281  	// Get a temp cwd
   282  	testCwd(t)
   283  
   284  	// Write the temp state
   285  	state := states.BuildState(func(s *states.SyncState) {
   286  		s.SetResourceInstanceCurrent(
   287  			addrs.Resource{
   288  				Mode: addrs.ManagedResourceMode,
   289  				Type: "test_instance",
   290  				Name: "foo",
   291  			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
   292  			&states.ResourceInstanceObjectSrc{
   293  				AttrsJSON: []byte(`{"id":"bar"}`),
   294  				Status:    states.ObjectTainted,
   295  			},
   296  			addrs.AbsProviderConfig{
   297  				Provider: addrs.NewDefaultProvider("test"),
   298  				Module:   addrs.RootModule,
   299  			},
   300  		)
   301  	})
   302  	testWorkspace := "development"
   303  	path := testStateFileWorkspaceDefault(t, testWorkspace, state)
   304  
   305  	ui := new(cli.MockUi)
   306  	view, _ := testView(t)
   307  	meta := Meta{Ui: ui, View: view}
   308  	meta.SetWorkspace(testWorkspace)
   309  	c := &UntaintCommand{
   310  		Meta: meta,
   311  	}
   312  
   313  	args := []string{
   314  		"test_instance.foo",
   315  	}
   316  	if code := c.Run(args); code != 0 {
   317  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   318  	}
   319  
   320  	testStateOutput(t, path, strings.TrimSpace(`
   321  test_instance.foo:
   322    ID = bar
   323    provider = provider["registry.terraform.io/hashicorp/test"]
   324  	`))
   325  }
   326  
   327  func TestUntaint_missing(t *testing.T) {
   328  	state := states.BuildState(func(s *states.SyncState) {
   329  		s.SetResourceInstanceCurrent(
   330  			addrs.Resource{
   331  				Mode: addrs.ManagedResourceMode,
   332  				Type: "test_instance",
   333  				Name: "foo",
   334  			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
   335  			&states.ResourceInstanceObjectSrc{
   336  				AttrsJSON: []byte(`{"id":"bar"}`),
   337  				Status:    states.ObjectTainted,
   338  			},
   339  			addrs.AbsProviderConfig{
   340  				Provider: addrs.NewDefaultProvider("test"),
   341  				Module:   addrs.RootModule,
   342  			},
   343  		)
   344  	})
   345  	statePath := testStateFile(t, state)
   346  
   347  	ui := new(cli.MockUi)
   348  	view, _ := testView(t)
   349  	c := &UntaintCommand{
   350  		Meta: Meta{
   351  			Ui:   ui,
   352  			View: view,
   353  		},
   354  	}
   355  
   356  	args := []string{
   357  		"-state", statePath,
   358  		"test_instance.bar",
   359  	}
   360  	if code := c.Run(args); code == 0 {
   361  		t.Fatalf("bad: %d\n\n%s", code, ui.OutputWriter.String())
   362  	}
   363  }
   364  
   365  func TestUntaint_missingAllow(t *testing.T) {
   366  	state := states.BuildState(func(s *states.SyncState) {
   367  		s.SetResourceInstanceCurrent(
   368  			addrs.Resource{
   369  				Mode: addrs.ManagedResourceMode,
   370  				Type: "test_instance",
   371  				Name: "foo",
   372  			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
   373  			&states.ResourceInstanceObjectSrc{
   374  				AttrsJSON: []byte(`{"id":"bar"}`),
   375  				Status:    states.ObjectTainted,
   376  			},
   377  			addrs.AbsProviderConfig{
   378  				Provider: addrs.NewDefaultProvider("test"),
   379  				Module:   addrs.RootModule,
   380  			},
   381  		)
   382  	})
   383  	statePath := testStateFile(t, state)
   384  
   385  	ui := new(cli.MockUi)
   386  	view, _ := testView(t)
   387  	c := &UntaintCommand{
   388  		Meta: Meta{
   389  			Ui:   ui,
   390  			View: view,
   391  		},
   392  	}
   393  
   394  	args := []string{
   395  		"-allow-missing",
   396  		"-state", statePath,
   397  		"test_instance.bar",
   398  	}
   399  	if code := c.Run(args); code != 0 {
   400  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   401  	}
   402  
   403  	// Check for the warning
   404  	actual := strings.TrimSpace(ui.ErrorWriter.String())
   405  	expected := strings.TrimSpace(`
   406  Warning: No such resource instance
   407  
   408  Resource instance test_instance.bar was not found, but this is not an error
   409  because -allow-missing was set.
   410  
   411  `)
   412  	if diff := cmp.Diff(expected, actual); diff != "" {
   413  		t.Fatalf("wrong output\n%s", diff)
   414  	}
   415  }
   416  
   417  func TestUntaint_stateOut(t *testing.T) {
   418  	// Get a temp cwd
   419  	testCwd(t)
   420  
   421  	// Write the temp state
   422  	state := states.BuildState(func(s *states.SyncState) {
   423  		s.SetResourceInstanceCurrent(
   424  			addrs.Resource{
   425  				Mode: addrs.ManagedResourceMode,
   426  				Type: "test_instance",
   427  				Name: "foo",
   428  			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
   429  			&states.ResourceInstanceObjectSrc{
   430  				AttrsJSON: []byte(`{"id":"bar"}`),
   431  				Status:    states.ObjectTainted,
   432  			},
   433  			addrs.AbsProviderConfig{
   434  				Provider: addrs.NewDefaultProvider("test"),
   435  				Module:   addrs.RootModule,
   436  			},
   437  		)
   438  	})
   439  	testStateFileDefault(t, state)
   440  
   441  	ui := new(cli.MockUi)
   442  	view, _ := testView(t)
   443  	c := &UntaintCommand{
   444  		Meta: Meta{
   445  			Ui:   ui,
   446  			View: view,
   447  		},
   448  	}
   449  
   450  	args := []string{
   451  		"-state-out", "foo",
   452  		"test_instance.foo",
   453  	}
   454  	if code := c.Run(args); code != 0 {
   455  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   456  	}
   457  
   458  	testStateOutput(t, DefaultStateFilename, strings.TrimSpace(`
   459  test_instance.foo: (tainted)
   460    ID = bar
   461    provider = provider["registry.terraform.io/hashicorp/test"]
   462  	`))
   463  	testStateOutput(t, "foo", strings.TrimSpace(`
   464  test_instance.foo:
   465    ID = bar
   466    provider = provider["registry.terraform.io/hashicorp/test"]
   467  	`))
   468  }
   469  
   470  func TestUntaint_module(t *testing.T) {
   471  	state := states.BuildState(func(s *states.SyncState) {
   472  		s.SetResourceInstanceCurrent(
   473  			addrs.Resource{
   474  				Mode: addrs.ManagedResourceMode,
   475  				Type: "test_instance",
   476  				Name: "foo",
   477  			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
   478  			&states.ResourceInstanceObjectSrc{
   479  				AttrsJSON: []byte(`{"id":"bar"}`),
   480  				Status:    states.ObjectTainted,
   481  			},
   482  			addrs.AbsProviderConfig{
   483  				Provider: addrs.NewDefaultProvider("test"),
   484  				Module:   addrs.RootModule,
   485  			},
   486  		)
   487  		s.SetResourceInstanceCurrent(
   488  			addrs.Resource{
   489  				Mode: addrs.ManagedResourceMode,
   490  				Type: "test_instance",
   491  				Name: "blah",
   492  			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance.Child("child", addrs.NoKey)),
   493  			&states.ResourceInstanceObjectSrc{
   494  				AttrsJSON: []byte(`{"id":"bar"}`),
   495  				Status:    states.ObjectTainted,
   496  			},
   497  			addrs.AbsProviderConfig{
   498  				Provider: addrs.NewDefaultProvider("test"),
   499  				Module:   addrs.RootModule,
   500  			},
   501  		)
   502  	})
   503  	statePath := testStateFile(t, state)
   504  
   505  	ui := new(cli.MockUi)
   506  	view, _ := testView(t)
   507  	c := &UntaintCommand{
   508  		Meta: Meta{
   509  			Ui:   ui,
   510  			View: view,
   511  		},
   512  	}
   513  
   514  	args := []string{
   515  		"-state", statePath,
   516  		"module.child.test_instance.blah",
   517  	}
   518  	if code := c.Run(args); code != 0 {
   519  		t.Fatalf("command exited with status code %d; want 0\n\n%s", code, ui.ErrorWriter.String())
   520  	}
   521  
   522  	testStateOutput(t, statePath, strings.TrimSpace(`
   523  test_instance.foo: (tainted)
   524    ID = bar
   525    provider = provider["registry.terraform.io/hashicorp/test"]
   526  
   527  module.child:
   528    test_instance.blah:
   529      ID = bar
   530      provider = provider["registry.terraform.io/hashicorp/test"]
   531  	`))
   532  }