github.com/kanishk98/terraform@v1.3.0-dev.0.20220917174235-661ca8088a6a/internal/command/state_push_test.go (about)

     1  package command
     2  
     3  import (
     4  	"bytes"
     5  	"strings"
     6  	"testing"
     7  
     8  	"github.com/hashicorp/terraform/internal/backend"
     9  	"github.com/hashicorp/terraform/internal/backend/remote-state/inmem"
    10  	"github.com/hashicorp/terraform/internal/states"
    11  	"github.com/mitchellh/cli"
    12  )
    13  
    14  func TestStatePush_empty(t *testing.T) {
    15  	// Create a temporary working directory that is empty
    16  	td := t.TempDir()
    17  	testCopyDir(t, testFixturePath("state-push-good"), td)
    18  	defer testChdir(t, td)()
    19  
    20  	expected := testStateRead(t, "replace.tfstate")
    21  
    22  	p := testProvider()
    23  	ui := new(cli.MockUi)
    24  	view, _ := testView(t)
    25  	c := &StatePushCommand{
    26  		Meta: Meta{
    27  			testingOverrides: metaOverridesForProvider(p),
    28  			Ui:               ui,
    29  			View:             view,
    30  		},
    31  	}
    32  
    33  	args := []string{"replace.tfstate"}
    34  	if code := c.Run(args); code != 0 {
    35  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
    36  	}
    37  
    38  	actual := testStateRead(t, "local-state.tfstate")
    39  	if !actual.Equal(expected) {
    40  		t.Fatalf("bad: %#v", actual)
    41  	}
    42  }
    43  
    44  func TestStatePush_lockedState(t *testing.T) {
    45  	// Create a temporary working directory that is empty
    46  	td := t.TempDir()
    47  	testCopyDir(t, testFixturePath("state-push-good"), td)
    48  	defer testChdir(t, td)()
    49  
    50  	p := testProvider()
    51  	ui := new(cli.MockUi)
    52  	view, _ := testView(t)
    53  	c := &StatePushCommand{
    54  		Meta: Meta{
    55  			testingOverrides: metaOverridesForProvider(p),
    56  			Ui:               ui,
    57  			View:             view,
    58  		},
    59  	}
    60  
    61  	unlock, err := testLockState(t, testDataDir, "local-state.tfstate")
    62  	if err != nil {
    63  		t.Fatal(err)
    64  	}
    65  	defer unlock()
    66  
    67  	args := []string{"replace.tfstate"}
    68  	if code := c.Run(args); code != 1 {
    69  		t.Fatalf("bad: %d", code)
    70  	}
    71  	if !strings.Contains(ui.ErrorWriter.String(), "Error acquiring the state lock") {
    72  		t.Fatalf("expected a lock error, got: %s", ui.ErrorWriter.String())
    73  	}
    74  }
    75  
    76  func TestStatePush_replaceMatch(t *testing.T) {
    77  	// Create a temporary working directory that is empty
    78  	td := t.TempDir()
    79  	testCopyDir(t, testFixturePath("state-push-replace-match"), td)
    80  	defer testChdir(t, td)()
    81  
    82  	expected := testStateRead(t, "replace.tfstate")
    83  
    84  	p := testProvider()
    85  	ui := new(cli.MockUi)
    86  	view, _ := testView(t)
    87  	c := &StatePushCommand{
    88  		Meta: Meta{
    89  			testingOverrides: metaOverridesForProvider(p),
    90  			Ui:               ui,
    91  			View:             view,
    92  		},
    93  	}
    94  
    95  	args := []string{"replace.tfstate"}
    96  	if code := c.Run(args); code != 0 {
    97  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
    98  	}
    99  
   100  	actual := testStateRead(t, "local-state.tfstate")
   101  	if !actual.Equal(expected) {
   102  		t.Fatalf("bad: %#v", actual)
   103  	}
   104  }
   105  
   106  func TestStatePush_replaceMatchStdin(t *testing.T) {
   107  	// Create a temporary working directory that is empty
   108  	td := t.TempDir()
   109  	testCopyDir(t, testFixturePath("state-push-replace-match"), td)
   110  	defer testChdir(t, td)()
   111  
   112  	expected := testStateRead(t, "replace.tfstate")
   113  
   114  	// Set up the replacement to come from stdin
   115  	var buf bytes.Buffer
   116  	if err := writeStateForTesting(expected, &buf); err != nil {
   117  		t.Fatalf("err: %s", err)
   118  	}
   119  	defer testStdinPipe(t, &buf)()
   120  
   121  	p := testProvider()
   122  	ui := new(cli.MockUi)
   123  	view, _ := testView(t)
   124  	c := &StatePushCommand{
   125  		Meta: Meta{
   126  			testingOverrides: metaOverridesForProvider(p),
   127  			Ui:               ui,
   128  			View:             view,
   129  		},
   130  	}
   131  
   132  	args := []string{"-force", "-"}
   133  	if code := c.Run(args); code != 0 {
   134  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   135  	}
   136  
   137  	actual := testStateRead(t, "local-state.tfstate")
   138  	if !actual.Equal(expected) {
   139  		t.Fatalf("bad: %#v", actual)
   140  	}
   141  }
   142  
   143  func TestStatePush_lineageMismatch(t *testing.T) {
   144  	// Create a temporary working directory that is empty
   145  	td := t.TempDir()
   146  	testCopyDir(t, testFixturePath("state-push-bad-lineage"), td)
   147  	defer testChdir(t, td)()
   148  
   149  	expected := testStateRead(t, "local-state.tfstate")
   150  
   151  	p := testProvider()
   152  	ui := cli.NewMockUi()
   153  	view, _ := testView(t)
   154  	c := &StatePushCommand{
   155  		Meta: Meta{
   156  			testingOverrides: metaOverridesForProvider(p),
   157  			Ui:               ui,
   158  			View:             view,
   159  		},
   160  	}
   161  
   162  	args := []string{"replace.tfstate"}
   163  	if code := c.Run(args); code != 1 {
   164  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   165  	}
   166  
   167  	actual := testStateRead(t, "local-state.tfstate")
   168  	if !actual.Equal(expected) {
   169  		t.Fatalf("bad: %#v", actual)
   170  	}
   171  }
   172  
   173  func TestStatePush_serialNewer(t *testing.T) {
   174  	// Create a temporary working directory that is empty
   175  	td := t.TempDir()
   176  	testCopyDir(t, testFixturePath("state-push-serial-newer"), td)
   177  	defer testChdir(t, td)()
   178  
   179  	expected := testStateRead(t, "local-state.tfstate")
   180  
   181  	p := testProvider()
   182  	ui := new(cli.MockUi)
   183  	view, _ := testView(t)
   184  	c := &StatePushCommand{
   185  		Meta: Meta{
   186  			testingOverrides: metaOverridesForProvider(p),
   187  			Ui:               ui,
   188  			View:             view,
   189  		},
   190  	}
   191  
   192  	args := []string{"replace.tfstate"}
   193  	if code := c.Run(args); code != 1 {
   194  		t.Fatalf("bad: %d", code)
   195  	}
   196  
   197  	actual := testStateRead(t, "local-state.tfstate")
   198  	if !actual.Equal(expected) {
   199  		t.Fatalf("bad: %#v", actual)
   200  	}
   201  }
   202  
   203  func TestStatePush_serialOlder(t *testing.T) {
   204  	// Create a temporary working directory that is empty
   205  	td := t.TempDir()
   206  	testCopyDir(t, testFixturePath("state-push-serial-older"), td)
   207  	defer testChdir(t, td)()
   208  
   209  	expected := testStateRead(t, "replace.tfstate")
   210  
   211  	p := testProvider()
   212  	ui := new(cli.MockUi)
   213  	view, _ := testView(t)
   214  	c := &StatePushCommand{
   215  		Meta: Meta{
   216  			testingOverrides: metaOverridesForProvider(p),
   217  			Ui:               ui,
   218  			View:             view,
   219  		},
   220  	}
   221  
   222  	args := []string{"replace.tfstate"}
   223  	if code := c.Run(args); code != 0 {
   224  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   225  	}
   226  
   227  	actual := testStateRead(t, "local-state.tfstate")
   228  	if !actual.Equal(expected) {
   229  		t.Fatalf("bad: %#v", actual)
   230  	}
   231  }
   232  
   233  func TestStatePush_forceRemoteState(t *testing.T) {
   234  	td := t.TempDir()
   235  	testCopyDir(t, testFixturePath("inmem-backend"), td)
   236  	defer testChdir(t, td)()
   237  	defer inmem.Reset()
   238  
   239  	s := states.NewState()
   240  	statePath := testStateFile(t, s)
   241  
   242  	// init the backend
   243  	ui := new(cli.MockUi)
   244  	view, _ := testView(t)
   245  	initCmd := &InitCommand{
   246  		Meta: Meta{Ui: ui, View: view},
   247  	}
   248  	if code := initCmd.Run([]string{}); code != 0 {
   249  		t.Fatalf("bad: \n%s", ui.ErrorWriter.String())
   250  	}
   251  
   252  	// create a new workspace
   253  	ui = new(cli.MockUi)
   254  	newCmd := &WorkspaceNewCommand{
   255  		Meta: Meta{Ui: ui, View: view},
   256  	}
   257  	if code := newCmd.Run([]string{"test"}); code != 0 {
   258  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter)
   259  	}
   260  
   261  	// put a dummy state in place, so we have something to force
   262  	b := backend.TestBackendConfig(t, inmem.New(), nil)
   263  	sMgr, err := b.StateMgr("test")
   264  	if err != nil {
   265  		t.Fatal(err)
   266  	}
   267  	if err := sMgr.WriteState(states.NewState()); err != nil {
   268  		t.Fatal(err)
   269  	}
   270  	if err := sMgr.PersistState(nil); err != nil {
   271  		t.Fatal(err)
   272  	}
   273  
   274  	// push our local state to that new workspace
   275  	ui = new(cli.MockUi)
   276  	c := &StatePushCommand{
   277  		Meta: Meta{Ui: ui, View: view},
   278  	}
   279  
   280  	args := []string{"-force", statePath}
   281  	if code := c.Run(args); code != 0 {
   282  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   283  	}
   284  }
   285  
   286  func TestStatePush_checkRequiredVersion(t *testing.T) {
   287  	// Create a temporary working directory that is empty
   288  	td := t.TempDir()
   289  	testCopyDir(t, testFixturePath("command-check-required-version"), td)
   290  	defer testChdir(t, td)()
   291  
   292  	p := testProvider()
   293  	ui := cli.NewMockUi()
   294  	view, _ := testView(t)
   295  	c := &StatePushCommand{
   296  		Meta: Meta{
   297  			testingOverrides: metaOverridesForProvider(p),
   298  			Ui:               ui,
   299  			View:             view,
   300  		},
   301  	}
   302  
   303  	args := []string{"replace.tfstate"}
   304  	if code := c.Run(args); code != 1 {
   305  		t.Fatalf("got exit status %d; want 1\nstderr:\n%s\n\nstdout:\n%s", code, ui.ErrorWriter.String(), ui.OutputWriter.String())
   306  	}
   307  
   308  	// Required version diags are correct
   309  	errStr := ui.ErrorWriter.String()
   310  	if !strings.Contains(errStr, `required_version = "~> 0.9.0"`) {
   311  		t.Fatalf("output should point to unmet version constraint, but is:\n\n%s", errStr)
   312  	}
   313  	if strings.Contains(errStr, `required_version = ">= 0.13.0"`) {
   314  		t.Fatalf("output should not point to met version constraint, but is:\n\n%s", errStr)
   315  	}
   316  }