github.com/graywolf-at-work-2/terraform-vendor@v1.4.5/internal/command/apply_test.go (about)

     1  package command
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"fmt"
     7  	"io/ioutil"
     8  	"os"
     9  	"path/filepath"
    10  	"reflect"
    11  	"strings"
    12  	"sync"
    13  	"testing"
    14  	"time"
    15  
    16  	"github.com/google/go-cmp/cmp"
    17  	"github.com/google/go-cmp/cmp/cmpopts"
    18  	"github.com/mitchellh/cli"
    19  	"github.com/zclconf/go-cty/cty"
    20  
    21  	"github.com/hashicorp/terraform/internal/addrs"
    22  	"github.com/hashicorp/terraform/internal/configs/configschema"
    23  	"github.com/hashicorp/terraform/internal/plans"
    24  	"github.com/hashicorp/terraform/internal/providers"
    25  	"github.com/hashicorp/terraform/internal/states"
    26  	"github.com/hashicorp/terraform/internal/states/statemgr"
    27  	"github.com/hashicorp/terraform/internal/terraform"
    28  	"github.com/hashicorp/terraform/internal/tfdiags"
    29  )
    30  
    31  func TestApply(t *testing.T) {
    32  	// Create a temporary working directory that is empty
    33  	td := t.TempDir()
    34  	testCopyDir(t, testFixturePath("apply"), td)
    35  	defer testChdir(t, td)()
    36  
    37  	statePath := testTempFile(t)
    38  
    39  	p := applyFixtureProvider()
    40  
    41  	view, done := testView(t)
    42  	c := &ApplyCommand{
    43  		Meta: Meta{
    44  			testingOverrides: metaOverridesForProvider(p),
    45  			View:             view,
    46  		},
    47  	}
    48  
    49  	args := []string{
    50  		"-state", statePath,
    51  		"-auto-approve",
    52  	}
    53  	code := c.Run(args)
    54  	output := done(t)
    55  	if code != 0 {
    56  		t.Fatalf("bad: %d\n\n%s", code, output.Stderr())
    57  	}
    58  
    59  	if _, err := os.Stat(statePath); err != nil {
    60  		t.Fatalf("err: %s", err)
    61  	}
    62  
    63  	state := testStateRead(t, statePath)
    64  	if state == nil {
    65  		t.Fatal("state should not be nil")
    66  	}
    67  }
    68  
    69  func TestApply_path(t *testing.T) {
    70  	// Create a temporary working directory that is empty
    71  	td := t.TempDir()
    72  	testCopyDir(t, testFixturePath("apply"), td)
    73  	defer testChdir(t, td)()
    74  
    75  	p := applyFixtureProvider()
    76  
    77  	view, done := testView(t)
    78  	c := &ApplyCommand{
    79  		Meta: Meta{
    80  			testingOverrides: metaOverridesForProvider(p),
    81  			View:             view,
    82  		},
    83  	}
    84  
    85  	args := []string{
    86  		"-auto-approve",
    87  		testFixturePath("apply"),
    88  	}
    89  	code := c.Run(args)
    90  	output := done(t)
    91  	if code != 1 {
    92  		t.Fatalf("bad: %d\n\n%s", code, output.Stderr())
    93  	}
    94  	if !strings.Contains(output.Stderr(), "-chdir") {
    95  		t.Fatal("expected command output to refer to -chdir flag, but got:", output.Stderr())
    96  	}
    97  }
    98  
    99  func TestApply_approveNo(t *testing.T) {
   100  	// Create a temporary working directory that is empty
   101  	td := t.TempDir()
   102  	testCopyDir(t, testFixturePath("apply"), td)
   103  	defer testChdir(t, td)()
   104  
   105  	statePath := testTempFile(t)
   106  
   107  	defer testInputMap(t, map[string]string{
   108  		"approve": "no",
   109  	})()
   110  
   111  	// Do not use the NewMockUi initializer here, as we want to delay
   112  	// the call to init until after setting up the input mocks
   113  	ui := new(cli.MockUi)
   114  
   115  	p := applyFixtureProvider()
   116  	view, done := testView(t)
   117  	c := &ApplyCommand{
   118  		Meta: Meta{
   119  			testingOverrides: metaOverridesForProvider(p),
   120  			Ui:               ui,
   121  			View:             view,
   122  		},
   123  	}
   124  
   125  	args := []string{
   126  		"-state", statePath,
   127  	}
   128  	code := c.Run(args)
   129  	output := done(t)
   130  	if code != 1 {
   131  		t.Fatalf("bad: %d\n\n%s", code, output.Stderr())
   132  	}
   133  	if got, want := output.Stdout(), "Apply cancelled"; !strings.Contains(got, want) {
   134  		t.Fatalf("expected output to include %q, but was:\n%s", want, got)
   135  	}
   136  
   137  	if _, err := os.Stat(statePath); err == nil || !os.IsNotExist(err) {
   138  		t.Fatalf("state file should not exist")
   139  	}
   140  }
   141  
   142  func TestApply_approveYes(t *testing.T) {
   143  	// Create a temporary working directory that is empty
   144  	td := t.TempDir()
   145  	testCopyDir(t, testFixturePath("apply"), td)
   146  	defer testChdir(t, td)()
   147  
   148  	statePath := testTempFile(t)
   149  
   150  	p := applyFixtureProvider()
   151  
   152  	defer testInputMap(t, map[string]string{
   153  		"approve": "yes",
   154  	})()
   155  
   156  	// Do not use the NewMockUi initializer here, as we want to delay
   157  	// the call to init until after setting up the input mocks
   158  	ui := new(cli.MockUi)
   159  
   160  	view, done := testView(t)
   161  	c := &ApplyCommand{
   162  		Meta: Meta{
   163  			testingOverrides: metaOverridesForProvider(p),
   164  			Ui:               ui,
   165  			View:             view,
   166  		},
   167  	}
   168  
   169  	args := []string{
   170  		"-state", statePath,
   171  	}
   172  	code := c.Run(args)
   173  	output := done(t)
   174  	if code != 0 {
   175  		t.Fatalf("bad: %d\n\n%s", code, output.Stderr())
   176  	}
   177  
   178  	if _, err := os.Stat(statePath); err != nil {
   179  		t.Fatalf("err: %s", err)
   180  	}
   181  
   182  	state := testStateRead(t, statePath)
   183  	if state == nil {
   184  		t.Fatal("state should not be nil")
   185  	}
   186  }
   187  
   188  // test apply with locked state
   189  func TestApply_lockedState(t *testing.T) {
   190  	// Create a temporary working directory that is empty
   191  	td := t.TempDir()
   192  	testCopyDir(t, testFixturePath("apply"), td)
   193  	defer testChdir(t, td)()
   194  
   195  	statePath := testTempFile(t)
   196  
   197  	unlock, err := testLockState(t, testDataDir, statePath)
   198  	if err != nil {
   199  		t.Fatal(err)
   200  	}
   201  	defer unlock()
   202  
   203  	p := applyFixtureProvider()
   204  	view, done := testView(t)
   205  	c := &ApplyCommand{
   206  		Meta: Meta{
   207  			testingOverrides: metaOverridesForProvider(p),
   208  			View:             view,
   209  		},
   210  	}
   211  
   212  	args := []string{
   213  		"-state", statePath,
   214  		"-auto-approve",
   215  	}
   216  	code := c.Run(args)
   217  	output := done(t)
   218  	if code == 0 {
   219  		t.Fatal("expected error")
   220  	}
   221  
   222  	if !strings.Contains(output.Stderr(), "lock") {
   223  		t.Fatal("command output does not look like a lock error:", output.Stderr())
   224  	}
   225  }
   226  
   227  // test apply with locked state, waiting for unlock
   228  func TestApply_lockedStateWait(t *testing.T) {
   229  	// Create a temporary working directory that is empty
   230  	td := t.TempDir()
   231  	testCopyDir(t, testFixturePath("apply"), td)
   232  	defer testChdir(t, td)()
   233  
   234  	statePath := testTempFile(t)
   235  
   236  	unlock, err := testLockState(t, testDataDir, statePath)
   237  	if err != nil {
   238  		t.Fatal(err)
   239  	}
   240  
   241  	// unlock during apply
   242  	go func() {
   243  		time.Sleep(500 * time.Millisecond)
   244  		unlock()
   245  	}()
   246  
   247  	p := applyFixtureProvider()
   248  	view, done := testView(t)
   249  	c := &ApplyCommand{
   250  		Meta: Meta{
   251  			testingOverrides: metaOverridesForProvider(p),
   252  			View:             view,
   253  		},
   254  	}
   255  
   256  	// wait 4s just in case the lock process doesn't release in under a second,
   257  	// and we want our context to be alive for a second retry at the 3s mark.
   258  	args := []string{
   259  		"-state", statePath,
   260  		"-lock-timeout", "4s",
   261  		"-auto-approve",
   262  	}
   263  	code := c.Run(args)
   264  	output := done(t)
   265  	if code != 0 {
   266  		t.Fatalf("lock should have succeeded in less than 3s: %s", output.Stderr())
   267  	}
   268  }
   269  
   270  // Verify that the parallelism flag allows no more than the desired number of
   271  // concurrent calls to ApplyResourceChange.
   272  func TestApply_parallelism(t *testing.T) {
   273  	// Create a temporary working directory that is empty
   274  	td := t.TempDir()
   275  	testCopyDir(t, testFixturePath("parallelism"), td)
   276  	defer testChdir(t, td)()
   277  
   278  	statePath := testTempFile(t)
   279  
   280  	par := 4
   281  
   282  	// started is a semaphore that we use to ensure that we never have more
   283  	// than "par" apply operations happening concurrently
   284  	started := make(chan struct{}, par)
   285  
   286  	// beginCtx is used as a starting gate to hold back ApplyResourceChange
   287  	// calls until we reach the desired concurrency. The cancel func "begin" is
   288  	// called once we reach the desired concurrency, allowing all apply calls
   289  	// to proceed in unison.
   290  	beginCtx, begin := context.WithCancel(context.Background())
   291  
   292  	// Since our mock provider has its own mutex preventing concurrent calls
   293  	// to ApplyResourceChange, we need to use a number of separate providers
   294  	// here. They will all have the same mock implementation function assigned
   295  	// but crucially they will each have their own mutex.
   296  	providerFactories := map[addrs.Provider]providers.Factory{}
   297  	for i := 0; i < 10; i++ {
   298  		name := fmt.Sprintf("test%d", i)
   299  		provider := &terraform.MockProvider{}
   300  		provider.GetProviderSchemaResponse = &providers.GetProviderSchemaResponse{
   301  			ResourceTypes: map[string]providers.Schema{
   302  				name + "_instance": {Block: &configschema.Block{}},
   303  			},
   304  		}
   305  		provider.PlanResourceChangeFn = func(req providers.PlanResourceChangeRequest) providers.PlanResourceChangeResponse {
   306  			return providers.PlanResourceChangeResponse{
   307  				PlannedState: req.ProposedNewState,
   308  			}
   309  		}
   310  		provider.ApplyResourceChangeFn = func(req providers.ApplyResourceChangeRequest) providers.ApplyResourceChangeResponse {
   311  
   312  			// If we ever have more than our intended parallelism number of
   313  			// apply operations running concurrently, the semaphore will fail.
   314  			select {
   315  			case started <- struct{}{}:
   316  				defer func() {
   317  					<-started
   318  				}()
   319  			default:
   320  				t.Fatal("too many concurrent apply operations")
   321  			}
   322  
   323  			// If we never reach our intended parallelism, the context will
   324  			// never be canceled and the test will time out.
   325  			if len(started) >= par {
   326  				begin()
   327  			}
   328  			<-beginCtx.Done()
   329  
   330  			// do some "work"
   331  			// Not required for correctness, but makes it easier to spot a
   332  			// failure when there is more overlap.
   333  			time.Sleep(10 * time.Millisecond)
   334  
   335  			return providers.ApplyResourceChangeResponse{
   336  				NewState: cty.EmptyObjectVal,
   337  			}
   338  		}
   339  		providerFactories[addrs.NewDefaultProvider(name)] = providers.FactoryFixed(provider)
   340  	}
   341  	testingOverrides := &testingOverrides{
   342  		Providers: providerFactories,
   343  	}
   344  
   345  	view, done := testView(t)
   346  	c := &ApplyCommand{
   347  		Meta: Meta{
   348  			testingOverrides: testingOverrides,
   349  			View:             view,
   350  		},
   351  	}
   352  
   353  	args := []string{
   354  		"-state", statePath,
   355  		"-auto-approve",
   356  		fmt.Sprintf("-parallelism=%d", par),
   357  	}
   358  
   359  	res := c.Run(args)
   360  	output := done(t)
   361  	if res != 0 {
   362  		t.Fatal(output.Stdout())
   363  	}
   364  }
   365  
   366  func TestApply_configInvalid(t *testing.T) {
   367  	// Create a temporary working directory that is empty
   368  	td := t.TempDir()
   369  	testCopyDir(t, testFixturePath("apply-config-invalid"), td)
   370  	defer testChdir(t, td)()
   371  
   372  	p := testProvider()
   373  	view, done := testView(t)
   374  	c := &ApplyCommand{
   375  		Meta: Meta{
   376  			testingOverrides: metaOverridesForProvider(p),
   377  			View:             view,
   378  		},
   379  	}
   380  
   381  	args := []string{
   382  		"-state", testTempFile(t),
   383  		"-auto-approve",
   384  	}
   385  	code := c.Run(args)
   386  	output := done(t)
   387  	if code != 1 {
   388  		t.Fatalf("bad: \n%s", output.Stdout())
   389  	}
   390  }
   391  
   392  func TestApply_defaultState(t *testing.T) {
   393  	// Create a temporary working directory that is empty
   394  	td := t.TempDir()
   395  	testCopyDir(t, testFixturePath("apply"), td)
   396  	defer testChdir(t, td)()
   397  
   398  	statePath := filepath.Join(td, DefaultStateFilename)
   399  
   400  	// Change to the temporary directory
   401  	cwd, err := os.Getwd()
   402  	if err != nil {
   403  		t.Fatalf("err: %s", err)
   404  	}
   405  	if err := os.Chdir(filepath.Dir(statePath)); err != nil {
   406  		t.Fatalf("err: %s", err)
   407  	}
   408  	defer os.Chdir(cwd)
   409  
   410  	p := applyFixtureProvider()
   411  	view, done := testView(t)
   412  	c := &ApplyCommand{
   413  		Meta: Meta{
   414  			testingOverrides: metaOverridesForProvider(p),
   415  			View:             view,
   416  		},
   417  	}
   418  
   419  	// create an existing state file
   420  	localState := statemgr.NewFilesystem(statePath)
   421  	if err := localState.WriteState(states.NewState()); err != nil {
   422  		t.Fatal(err)
   423  	}
   424  
   425  	args := []string{
   426  		"-auto-approve",
   427  	}
   428  	code := c.Run(args)
   429  	output := done(t)
   430  	if code != 0 {
   431  		t.Fatalf("bad: %d\n\n%s", code, output.Stderr())
   432  	}
   433  
   434  	if _, err := os.Stat(statePath); err != nil {
   435  		t.Fatalf("err: %s", err)
   436  	}
   437  
   438  	state := testStateRead(t, statePath)
   439  	if state == nil {
   440  		t.Fatal("state should not be nil")
   441  	}
   442  }
   443  
   444  func TestApply_error(t *testing.T) {
   445  	// Create a temporary working directory that is empty
   446  	td := t.TempDir()
   447  	testCopyDir(t, testFixturePath("apply-error"), td)
   448  	defer testChdir(t, td)()
   449  
   450  	statePath := testTempFile(t)
   451  
   452  	p := testProvider()
   453  	view, done := testView(t)
   454  	c := &ApplyCommand{
   455  		Meta: Meta{
   456  			testingOverrides: metaOverridesForProvider(p),
   457  			View:             view,
   458  		},
   459  	}
   460  
   461  	var lock sync.Mutex
   462  	errored := false
   463  	p.ApplyResourceChangeFn = func(req providers.ApplyResourceChangeRequest) (resp providers.ApplyResourceChangeResponse) {
   464  		lock.Lock()
   465  		defer lock.Unlock()
   466  
   467  		if !errored {
   468  			errored = true
   469  			resp.Diagnostics = resp.Diagnostics.Append(fmt.Errorf("error"))
   470  		}
   471  
   472  		s := req.PlannedState.AsValueMap()
   473  		s["id"] = cty.StringVal("foo")
   474  
   475  		resp.NewState = cty.ObjectVal(s)
   476  		return
   477  	}
   478  	p.PlanResourceChangeFn = func(req providers.PlanResourceChangeRequest) (resp providers.PlanResourceChangeResponse) {
   479  		s := req.ProposedNewState.AsValueMap()
   480  		s["id"] = cty.UnknownVal(cty.String)
   481  		resp.PlannedState = cty.ObjectVal(s)
   482  		return
   483  	}
   484  	p.GetProviderSchemaResponse = &providers.GetProviderSchemaResponse{
   485  		ResourceTypes: map[string]providers.Schema{
   486  			"test_instance": {
   487  				Block: &configschema.Block{
   488  					Attributes: map[string]*configschema.Attribute{
   489  						"id":    {Type: cty.String, Optional: true, Computed: true},
   490  						"ami":   {Type: cty.String, Optional: true},
   491  						"error": {Type: cty.Bool, Optional: true},
   492  					},
   493  				},
   494  			},
   495  		},
   496  	}
   497  
   498  	args := []string{
   499  		"-state", statePath,
   500  		"-auto-approve",
   501  	}
   502  	code := c.Run(args)
   503  	output := done(t)
   504  	if code != 1 {
   505  		t.Fatalf("wrong exit code %d; want 1\n%s", code, output.Stdout())
   506  	}
   507  
   508  	if _, err := os.Stat(statePath); err != nil {
   509  		t.Fatalf("err: %s", err)
   510  	}
   511  
   512  	state := testStateRead(t, statePath)
   513  	if state == nil {
   514  		t.Fatal("state should not be nil")
   515  	}
   516  	if len(state.RootModule().Resources) == 0 {
   517  		t.Fatal("no resources in state")
   518  	}
   519  }
   520  
   521  func TestApply_input(t *testing.T) {
   522  	// Create a temporary working directory that is empty
   523  	td := t.TempDir()
   524  	testCopyDir(t, testFixturePath("apply-input"), td)
   525  	defer testChdir(t, td)()
   526  
   527  	// Disable test mode so input would be asked
   528  	test = false
   529  	defer func() { test = true }()
   530  
   531  	// The configuration for this test includes a declaration of variable
   532  	// "foo" with no default, and we don't set it on the command line below,
   533  	// so the apply command will produce an interactive prompt for the
   534  	// value of var.foo. We'll answer "foo" here, and we expect the output
   535  	// value "result" to echo that back to us below.
   536  	defaultInputReader = bytes.NewBufferString("foo\n")
   537  	defaultInputWriter = new(bytes.Buffer)
   538  
   539  	statePath := testTempFile(t)
   540  
   541  	p := testProvider()
   542  	view, done := testView(t)
   543  	c := &ApplyCommand{
   544  		Meta: Meta{
   545  			testingOverrides: metaOverridesForProvider(p),
   546  			View:             view,
   547  		},
   548  	}
   549  
   550  	args := []string{
   551  		"-state", statePath,
   552  		"-auto-approve",
   553  	}
   554  	code := c.Run(args)
   555  	output := done(t)
   556  	if code != 0 {
   557  		t.Fatalf("bad: %d\n\n%s", code, output.Stderr())
   558  	}
   559  
   560  	expected := strings.TrimSpace(`
   561  <no state>
   562  Outputs:
   563  
   564  result = foo
   565  	`)
   566  	testStateOutput(t, statePath, expected)
   567  }
   568  
   569  // When only a partial set of the variables are set, Terraform
   570  // should still ask for the unset ones by default (with -input=true)
   571  func TestApply_inputPartial(t *testing.T) {
   572  	// Create a temporary working directory that is empty
   573  	td := t.TempDir()
   574  	testCopyDir(t, testFixturePath("apply-input-partial"), td)
   575  	defer testChdir(t, td)()
   576  
   577  	// Disable test mode so input would be asked
   578  	test = false
   579  	defer func() { test = true }()
   580  
   581  	// Set some default reader/writers for the inputs
   582  	defaultInputReader = bytes.NewBufferString("one\ntwo\n")
   583  	defaultInputWriter = new(bytes.Buffer)
   584  
   585  	statePath := testTempFile(t)
   586  
   587  	p := testProvider()
   588  	view, done := testView(t)
   589  	c := &ApplyCommand{
   590  		Meta: Meta{
   591  			testingOverrides: metaOverridesForProvider(p),
   592  			View:             view,
   593  		},
   594  	}
   595  
   596  	args := []string{
   597  		"-state", statePath,
   598  		"-auto-approve",
   599  		"-var", "foo=foovalue",
   600  	}
   601  	code := c.Run(args)
   602  	output := done(t)
   603  	if code != 0 {
   604  		t.Fatalf("bad: %d\n\n%s", code, output.Stderr())
   605  	}
   606  
   607  	expected := strings.TrimSpace(`
   608  <no state>
   609  Outputs:
   610  
   611  bar = one
   612  foo = foovalue
   613  	`)
   614  	testStateOutput(t, statePath, expected)
   615  }
   616  
   617  func TestApply_noArgs(t *testing.T) {
   618  	// Create a temporary working directory that is empty
   619  	td := t.TempDir()
   620  	testCopyDir(t, testFixturePath("apply"), td)
   621  	defer testChdir(t, td)()
   622  
   623  	statePath := testTempFile(t)
   624  
   625  	p := applyFixtureProvider()
   626  	view, done := testView(t)
   627  	c := &ApplyCommand{
   628  		Meta: Meta{
   629  			testingOverrides: metaOverridesForProvider(p),
   630  			View:             view,
   631  		},
   632  	}
   633  
   634  	args := []string{
   635  		"-state", statePath,
   636  		"-auto-approve",
   637  	}
   638  	code := c.Run(args)
   639  	output := done(t)
   640  	if code != 0 {
   641  		t.Fatalf("bad: %d\n\n%s", code, output.Stderr())
   642  	}
   643  
   644  	if _, err := os.Stat(statePath); err != nil {
   645  		t.Fatalf("err: %s", err)
   646  	}
   647  
   648  	state := testStateRead(t, statePath)
   649  	if state == nil {
   650  		t.Fatal("state should not be nil")
   651  	}
   652  }
   653  
   654  func TestApply_plan(t *testing.T) {
   655  	// Disable test mode so input would be asked
   656  	test = false
   657  	defer func() { test = true }()
   658  
   659  	// Set some default reader/writers for the inputs
   660  	defaultInputReader = new(bytes.Buffer)
   661  	defaultInputWriter = new(bytes.Buffer)
   662  
   663  	planPath := applyFixturePlanFile(t)
   664  	statePath := testTempFile(t)
   665  
   666  	p := applyFixtureProvider()
   667  	view, done := testView(t)
   668  	c := &ApplyCommand{
   669  		Meta: Meta{
   670  			testingOverrides: metaOverridesForProvider(p),
   671  			View:             view,
   672  		},
   673  	}
   674  
   675  	args := []string{
   676  		"-state-out", statePath,
   677  		planPath,
   678  	}
   679  	code := c.Run(args)
   680  	output := done(t)
   681  	if code != 0 {
   682  		t.Fatalf("bad: %d\n\n%s", code, output.Stderr())
   683  	}
   684  
   685  	if _, err := os.Stat(statePath); err != nil {
   686  		t.Fatalf("err: %s", err)
   687  	}
   688  
   689  	state := testStateRead(t, statePath)
   690  	if state == nil {
   691  		t.Fatal("state should not be nil")
   692  	}
   693  }
   694  
   695  func TestApply_plan_backup(t *testing.T) {
   696  	statePath := testTempFile(t)
   697  	backupPath := testTempFile(t)
   698  
   699  	p := applyFixtureProvider()
   700  	view, done := testView(t)
   701  	c := &ApplyCommand{
   702  		Meta: Meta{
   703  			testingOverrides: metaOverridesForProvider(p),
   704  			View:             view,
   705  		},
   706  	}
   707  
   708  	// create a state file that needs to be backed up
   709  	fs := statemgr.NewFilesystem(statePath)
   710  	fs.StateSnapshotMeta()
   711  	err := fs.WriteState(states.NewState())
   712  	if err != nil {
   713  		t.Fatal(err)
   714  	}
   715  
   716  	// the plan file must contain the metadata from the prior state to be
   717  	// backed up
   718  	planPath := applyFixturePlanFileMatchState(t, fs.StateSnapshotMeta())
   719  
   720  	args := []string{
   721  		"-state", statePath,
   722  		"-backup", backupPath,
   723  		planPath,
   724  	}
   725  	code := c.Run(args)
   726  	output := done(t)
   727  	if code != 0 {
   728  		t.Fatalf("bad: %d\n\n%s", code, output.Stderr())
   729  	}
   730  
   731  	// Should have a backup file
   732  	testStateRead(t, backupPath)
   733  }
   734  
   735  func TestApply_plan_noBackup(t *testing.T) {
   736  	planPath := applyFixturePlanFile(t)
   737  	statePath := testTempFile(t)
   738  
   739  	p := applyFixtureProvider()
   740  	view, done := testView(t)
   741  	c := &ApplyCommand{
   742  		Meta: Meta{
   743  			testingOverrides: metaOverridesForProvider(p),
   744  			View:             view,
   745  		},
   746  	}
   747  
   748  	args := []string{
   749  		"-state-out", statePath,
   750  		"-backup", "-",
   751  		planPath,
   752  	}
   753  	code := c.Run(args)
   754  	output := done(t)
   755  	if code != 0 {
   756  		t.Fatalf("bad: %d\n\n%s", code, output.Stderr())
   757  	}
   758  
   759  	// Ensure there is no backup
   760  	_, err := os.Stat(statePath + DefaultBackupExtension)
   761  	if err == nil || !os.IsNotExist(err) {
   762  		t.Fatalf("backup should not exist")
   763  	}
   764  
   765  	// Ensure there is no literal "-"
   766  	_, err = os.Stat("-")
   767  	if err == nil || !os.IsNotExist(err) {
   768  		t.Fatalf("backup should not exist")
   769  	}
   770  }
   771  
   772  func TestApply_plan_remoteState(t *testing.T) {
   773  	// Disable test mode so input would be asked
   774  	test = false
   775  	defer func() { test = true }()
   776  	tmp := testCwd(t)
   777  	remoteStatePath := filepath.Join(tmp, DefaultDataDir, DefaultStateFilename)
   778  	if err := os.MkdirAll(filepath.Dir(remoteStatePath), 0755); err != nil {
   779  		t.Fatalf("err: %s", err)
   780  	}
   781  
   782  	// Set some default reader/writers for the inputs
   783  	defaultInputReader = new(bytes.Buffer)
   784  	defaultInputWriter = new(bytes.Buffer)
   785  
   786  	// Create a remote state
   787  	state := testState()
   788  	_, srv := testRemoteState(t, state, 200)
   789  	defer srv.Close()
   790  
   791  	_, snap := testModuleWithSnapshot(t, "apply")
   792  	backendConfig := cty.ObjectVal(map[string]cty.Value{
   793  		"address":                   cty.StringVal(srv.URL),
   794  		"update_method":             cty.NullVal(cty.String),
   795  		"lock_address":              cty.NullVal(cty.String),
   796  		"unlock_address":            cty.NullVal(cty.String),
   797  		"lock_method":               cty.NullVal(cty.String),
   798  		"unlock_method":             cty.NullVal(cty.String),
   799  		"username":                  cty.NullVal(cty.String),
   800  		"password":                  cty.NullVal(cty.String),
   801  		"skip_cert_verification":    cty.NullVal(cty.Bool),
   802  		"retry_max":                 cty.NullVal(cty.String),
   803  		"retry_wait_min":            cty.NullVal(cty.String),
   804  		"retry_wait_max":            cty.NullVal(cty.String),
   805  		"client_ca_certificate_pem": cty.NullVal(cty.String),
   806  		"client_certificate_pem":    cty.NullVal(cty.String),
   807  		"client_private_key_pem":    cty.NullVal(cty.String),
   808  	})
   809  	backendConfigRaw, err := plans.NewDynamicValue(backendConfig, backendConfig.Type())
   810  	if err != nil {
   811  		t.Fatal(err)
   812  	}
   813  	planPath := testPlanFile(t, snap, state, &plans.Plan{
   814  		Backend: plans.Backend{
   815  			Type:   "http",
   816  			Config: backendConfigRaw,
   817  		},
   818  		Changes: plans.NewChanges(),
   819  	})
   820  
   821  	p := testProvider()
   822  	view, done := testView(t)
   823  	c := &ApplyCommand{
   824  		Meta: Meta{
   825  			testingOverrides: metaOverridesForProvider(p),
   826  			View:             view,
   827  		},
   828  	}
   829  
   830  	args := []string{
   831  		planPath,
   832  	}
   833  	code := c.Run(args)
   834  	output := done(t)
   835  	if code != 0 {
   836  		t.Fatalf("bad: %d\n\n%s", code, output.Stderr())
   837  	}
   838  
   839  	// State file should be not be installed
   840  	if _, err := os.Stat(filepath.Join(tmp, DefaultStateFilename)); err == nil {
   841  		data, _ := ioutil.ReadFile(DefaultStateFilename)
   842  		t.Fatalf("State path should not exist: %s", string(data))
   843  	}
   844  
   845  	// Check that there is no remote state config
   846  	if src, err := ioutil.ReadFile(remoteStatePath); err == nil {
   847  		t.Fatalf("has %s file; should not\n%s", remoteStatePath, src)
   848  	}
   849  }
   850  
   851  func TestApply_planWithVarFile(t *testing.T) {
   852  	varFileDir := testTempDir(t)
   853  	varFilePath := filepath.Join(varFileDir, "terraform.tfvars")
   854  	if err := ioutil.WriteFile(varFilePath, []byte(applyVarFile), 0644); err != nil {
   855  		t.Fatalf("err: %s", err)
   856  	}
   857  
   858  	planPath := applyFixturePlanFile(t)
   859  	statePath := testTempFile(t)
   860  
   861  	cwd, err := os.Getwd()
   862  	if err != nil {
   863  		t.Fatalf("err: %s", err)
   864  	}
   865  	if err := os.Chdir(varFileDir); err != nil {
   866  		t.Fatalf("err: %s", err)
   867  	}
   868  	defer os.Chdir(cwd)
   869  
   870  	p := applyFixtureProvider()
   871  	view, done := testView(t)
   872  	c := &ApplyCommand{
   873  		Meta: Meta{
   874  			testingOverrides: metaOverridesForProvider(p),
   875  			View:             view,
   876  		},
   877  	}
   878  
   879  	args := []string{
   880  		"-state-out", statePath,
   881  		planPath,
   882  	}
   883  	code := c.Run(args)
   884  	output := done(t)
   885  	if code != 0 {
   886  		t.Fatalf("bad: %d\n\n%s", code, output.Stderr())
   887  	}
   888  
   889  	if _, err := os.Stat(statePath); err != nil {
   890  		t.Fatalf("err: %s", err)
   891  	}
   892  
   893  	state := testStateRead(t, statePath)
   894  	if state == nil {
   895  		t.Fatal("state should not be nil")
   896  	}
   897  }
   898  
   899  func TestApply_planVars(t *testing.T) {
   900  	planPath := applyFixturePlanFile(t)
   901  	statePath := testTempFile(t)
   902  
   903  	p := applyFixtureProvider()
   904  	view, done := testView(t)
   905  	c := &ApplyCommand{
   906  		Meta: Meta{
   907  			testingOverrides: metaOverridesForProvider(p),
   908  			View:             view,
   909  		},
   910  	}
   911  
   912  	args := []string{
   913  		"-state", statePath,
   914  		"-var", "foo=bar",
   915  		planPath,
   916  	}
   917  	code := c.Run(args)
   918  	output := done(t)
   919  	if code == 0 {
   920  		t.Fatal("should've failed: ", output.Stdout())
   921  	}
   922  }
   923  
   924  // we should be able to apply a plan file with no other file dependencies
   925  func TestApply_planNoModuleFiles(t *testing.T) {
   926  	// temporary data directory which we can remove between commands
   927  	td := testTempDir(t)
   928  	defer os.RemoveAll(td)
   929  
   930  	defer testChdir(t, td)()
   931  
   932  	p := applyFixtureProvider()
   933  	planPath := applyFixturePlanFile(t)
   934  	view, done := testView(t)
   935  	apply := &ApplyCommand{
   936  		Meta: Meta{
   937  			testingOverrides: metaOverridesForProvider(p),
   938  			Ui:               new(cli.MockUi),
   939  			View:             view,
   940  		},
   941  	}
   942  	args := []string{
   943  		planPath,
   944  	}
   945  	apply.Run(args)
   946  	done(t)
   947  }
   948  
   949  func TestApply_refresh(t *testing.T) {
   950  	// Create a temporary working directory that is empty
   951  	td := t.TempDir()
   952  	testCopyDir(t, testFixturePath("apply"), td)
   953  	defer testChdir(t, td)()
   954  
   955  	originalState := states.BuildState(func(s *states.SyncState) {
   956  		s.SetResourceInstanceCurrent(
   957  			addrs.Resource{
   958  				Mode: addrs.ManagedResourceMode,
   959  				Type: "test_instance",
   960  				Name: "foo",
   961  			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
   962  			&states.ResourceInstanceObjectSrc{
   963  				AttrsJSON: []byte(`{"ami":"bar"}`),
   964  				Status:    states.ObjectReady,
   965  			},
   966  			addrs.AbsProviderConfig{
   967  				Provider: addrs.NewDefaultProvider("test"),
   968  				Module:   addrs.RootModule,
   969  			},
   970  		)
   971  	})
   972  	statePath := testStateFile(t, originalState)
   973  
   974  	p := applyFixtureProvider()
   975  	view, done := testView(t)
   976  	c := &ApplyCommand{
   977  		Meta: Meta{
   978  			testingOverrides: metaOverridesForProvider(p),
   979  			View:             view,
   980  		},
   981  	}
   982  
   983  	args := []string{
   984  		"-state", statePath,
   985  		"-auto-approve",
   986  	}
   987  	code := c.Run(args)
   988  	output := done(t)
   989  	if code != 0 {
   990  		t.Fatalf("bad: %d\n\n%s", code, output.Stderr())
   991  	}
   992  
   993  	if !p.ReadResourceCalled {
   994  		t.Fatal("should call ReadResource")
   995  	}
   996  
   997  	if _, err := os.Stat(statePath); err != nil {
   998  		t.Fatalf("err: %s", err)
   999  	}
  1000  
  1001  	state := testStateRead(t, statePath)
  1002  	if state == nil {
  1003  		t.Fatal("state should not be nil")
  1004  	}
  1005  
  1006  	// Should have a backup file
  1007  	backupState := testStateRead(t, statePath+DefaultBackupExtension)
  1008  
  1009  	actualStr := strings.TrimSpace(backupState.String())
  1010  	expectedStr := strings.TrimSpace(originalState.String())
  1011  	if actualStr != expectedStr {
  1012  		t.Fatalf("bad:\n\n%s\n\n%s", actualStr, expectedStr)
  1013  	}
  1014  }
  1015  
  1016  func TestApply_refreshFalse(t *testing.T) {
  1017  	// Create a temporary working directory that is empty
  1018  	td := t.TempDir()
  1019  	testCopyDir(t, testFixturePath("apply"), td)
  1020  	defer testChdir(t, td)()
  1021  
  1022  	originalState := states.BuildState(func(s *states.SyncState) {
  1023  		s.SetResourceInstanceCurrent(
  1024  			addrs.Resource{
  1025  				Mode: addrs.ManagedResourceMode,
  1026  				Type: "test_instance",
  1027  				Name: "foo",
  1028  			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
  1029  			&states.ResourceInstanceObjectSrc{
  1030  				AttrsJSON: []byte(`{"ami":"bar"}`),
  1031  				Status:    states.ObjectReady,
  1032  			},
  1033  			addrs.AbsProviderConfig{
  1034  				Provider: addrs.NewDefaultProvider("test"),
  1035  				Module:   addrs.RootModule,
  1036  			},
  1037  		)
  1038  	})
  1039  	statePath := testStateFile(t, originalState)
  1040  
  1041  	p := applyFixtureProvider()
  1042  	view, done := testView(t)
  1043  	c := &ApplyCommand{
  1044  		Meta: Meta{
  1045  			testingOverrides: metaOverridesForProvider(p),
  1046  			View:             view,
  1047  		},
  1048  	}
  1049  
  1050  	args := []string{
  1051  		"-state", statePath,
  1052  		"-auto-approve",
  1053  		"-refresh=false",
  1054  	}
  1055  	code := c.Run(args)
  1056  	output := done(t)
  1057  	if code != 0 {
  1058  		t.Fatalf("bad: %d\n\n%s", code, output.Stderr())
  1059  	}
  1060  
  1061  	if p.ReadResourceCalled {
  1062  		t.Fatal("should not call ReadResource when refresh=false")
  1063  	}
  1064  }
  1065  func TestApply_shutdown(t *testing.T) {
  1066  	// Create a temporary working directory that is empty
  1067  	td := t.TempDir()
  1068  	testCopyDir(t, testFixturePath("apply-shutdown"), td)
  1069  	defer testChdir(t, td)()
  1070  
  1071  	cancelled := make(chan struct{})
  1072  	shutdownCh := make(chan struct{})
  1073  
  1074  	statePath := testTempFile(t)
  1075  	p := testProvider()
  1076  
  1077  	view, done := testView(t)
  1078  	c := &ApplyCommand{
  1079  		Meta: Meta{
  1080  			testingOverrides: metaOverridesForProvider(p),
  1081  			View:             view,
  1082  			ShutdownCh:       shutdownCh,
  1083  		},
  1084  	}
  1085  
  1086  	p.StopFn = func() error {
  1087  		close(cancelled)
  1088  		return nil
  1089  	}
  1090  
  1091  	p.PlanResourceChangeFn = func(req providers.PlanResourceChangeRequest) (resp providers.PlanResourceChangeResponse) {
  1092  		resp.PlannedState = req.ProposedNewState
  1093  		return
  1094  	}
  1095  
  1096  	var once sync.Once
  1097  	p.ApplyResourceChangeFn = func(req providers.ApplyResourceChangeRequest) (resp providers.ApplyResourceChangeResponse) {
  1098  		// only cancel once
  1099  		once.Do(func() {
  1100  			shutdownCh <- struct{}{}
  1101  		})
  1102  
  1103  		// Because of the internal lock in the MockProvider, we can't
  1104  		// coordiante directly with the calling of Stop, and making the
  1105  		// MockProvider concurrent is disruptive to a lot of existing tests.
  1106  		// Wait here a moment to help make sure the main goroutine gets to the
  1107  		// Stop call before we exit, or the plan may finish before it can be
  1108  		// canceled.
  1109  		time.Sleep(200 * time.Millisecond)
  1110  
  1111  		resp.NewState = req.PlannedState
  1112  		return
  1113  	}
  1114  
  1115  	p.GetProviderSchemaResponse = &providers.GetProviderSchemaResponse{
  1116  		ResourceTypes: map[string]providers.Schema{
  1117  			"test_instance": {
  1118  				Block: &configschema.Block{
  1119  					Attributes: map[string]*configschema.Attribute{
  1120  						"ami": {Type: cty.String, Optional: true},
  1121  					},
  1122  				},
  1123  			},
  1124  		},
  1125  	}
  1126  
  1127  	args := []string{
  1128  		"-state", statePath,
  1129  		"-auto-approve",
  1130  	}
  1131  	code := c.Run(args)
  1132  	output := done(t)
  1133  	if code != 1 {
  1134  		t.Fatalf("bad: %d\n\n%s", code, output.Stderr())
  1135  	}
  1136  
  1137  	if _, err := os.Stat(statePath); err != nil {
  1138  		t.Fatalf("err: %s", err)
  1139  	}
  1140  
  1141  	select {
  1142  	case <-cancelled:
  1143  	default:
  1144  		t.Fatal("command not cancelled")
  1145  	}
  1146  
  1147  	state := testStateRead(t, statePath)
  1148  	if state == nil {
  1149  		t.Fatal("state should not be nil")
  1150  	}
  1151  }
  1152  
  1153  func TestApply_state(t *testing.T) {
  1154  	// Create a temporary working directory that is empty
  1155  	td := t.TempDir()
  1156  	testCopyDir(t, testFixturePath("apply"), td)
  1157  	defer testChdir(t, td)()
  1158  
  1159  	originalState := states.BuildState(func(s *states.SyncState) {
  1160  		s.SetResourceInstanceCurrent(
  1161  			addrs.Resource{
  1162  				Mode: addrs.ManagedResourceMode,
  1163  				Type: "test_instance",
  1164  				Name: "foo",
  1165  			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
  1166  			&states.ResourceInstanceObjectSrc{
  1167  				AttrsJSON: []byte(`{"ami":"foo"}`),
  1168  				Status:    states.ObjectReady,
  1169  			},
  1170  			addrs.AbsProviderConfig{
  1171  				Provider: addrs.NewDefaultProvider("test"),
  1172  				Module:   addrs.RootModule,
  1173  			},
  1174  		)
  1175  	})
  1176  	statePath := testStateFile(t, originalState)
  1177  
  1178  	p := applyFixtureProvider()
  1179  	p.PlanResourceChangeResponse = &providers.PlanResourceChangeResponse{
  1180  		PlannedState: cty.ObjectVal(map[string]cty.Value{
  1181  			"ami": cty.StringVal("bar"),
  1182  		}),
  1183  	}
  1184  	p.ApplyResourceChangeResponse = &providers.ApplyResourceChangeResponse{
  1185  		NewState: cty.ObjectVal(map[string]cty.Value{
  1186  			"ami": cty.StringVal("bar"),
  1187  		}),
  1188  	}
  1189  
  1190  	view, done := testView(t)
  1191  	c := &ApplyCommand{
  1192  		Meta: Meta{
  1193  			testingOverrides: metaOverridesForProvider(p),
  1194  			View:             view,
  1195  		},
  1196  	}
  1197  
  1198  	// Run the apply command pointing to our existing state
  1199  	args := []string{
  1200  		"-state", statePath,
  1201  		"-auto-approve",
  1202  	}
  1203  	code := c.Run(args)
  1204  	output := done(t)
  1205  	if code != 0 {
  1206  		t.Fatalf("bad: %d\n\n%s", code, output.Stderr())
  1207  	}
  1208  
  1209  	// Verify that the provider was called with the existing state
  1210  	actual := p.PlanResourceChangeRequest.PriorState
  1211  	expected := cty.ObjectVal(map[string]cty.Value{
  1212  		"id":  cty.NullVal(cty.String),
  1213  		"ami": cty.StringVal("foo"),
  1214  	})
  1215  	if !expected.RawEquals(actual) {
  1216  		t.Fatalf("wrong prior state during plan\ngot: %#v\nwant: %#v", actual, expected)
  1217  	}
  1218  
  1219  	actual = p.ApplyResourceChangeRequest.PriorState
  1220  	expected = cty.ObjectVal(map[string]cty.Value{
  1221  		"id":  cty.NullVal(cty.String),
  1222  		"ami": cty.StringVal("foo"),
  1223  	})
  1224  	if !expected.RawEquals(actual) {
  1225  		t.Fatalf("wrong prior state during apply\ngot: %#v\nwant: %#v", actual, expected)
  1226  	}
  1227  
  1228  	// Verify a new state exists
  1229  	if _, err := os.Stat(statePath); err != nil {
  1230  		t.Fatalf("err: %s", err)
  1231  	}
  1232  
  1233  	state := testStateRead(t, statePath)
  1234  	if state == nil {
  1235  		t.Fatal("state should not be nil")
  1236  	}
  1237  
  1238  	backupState := testStateRead(t, statePath+DefaultBackupExtension)
  1239  
  1240  	actualStr := strings.TrimSpace(backupState.String())
  1241  	expectedStr := strings.TrimSpace(originalState.String())
  1242  	if actualStr != expectedStr {
  1243  		t.Fatalf("bad:\n\n%s\n\n%s", actualStr, expectedStr)
  1244  	}
  1245  }
  1246  
  1247  func TestApply_stateNoExist(t *testing.T) {
  1248  	// Create a temporary working directory that is empty
  1249  	td := t.TempDir()
  1250  	testCopyDir(t, testFixturePath("apply"), td)
  1251  	defer testChdir(t, td)()
  1252  
  1253  	p := applyFixtureProvider()
  1254  	view, done := testView(t)
  1255  	c := &ApplyCommand{
  1256  		Meta: Meta{
  1257  			testingOverrides: metaOverridesForProvider(p),
  1258  			View:             view,
  1259  		},
  1260  	}
  1261  
  1262  	args := []string{
  1263  		"idontexist.tfstate",
  1264  	}
  1265  	code := c.Run(args)
  1266  	output := done(t)
  1267  	if code != 1 {
  1268  		t.Fatalf("bad: \n%s", output.Stdout())
  1269  	}
  1270  }
  1271  
  1272  func TestApply_sensitiveOutput(t *testing.T) {
  1273  	// Create a temporary working directory that is empty
  1274  	td := t.TempDir()
  1275  	testCopyDir(t, testFixturePath("apply-sensitive-output"), td)
  1276  	defer testChdir(t, td)()
  1277  
  1278  	p := testProvider()
  1279  	view, done := testView(t)
  1280  	c := &ApplyCommand{
  1281  		Meta: Meta{
  1282  			testingOverrides: metaOverridesForProvider(p),
  1283  			View:             view,
  1284  		},
  1285  	}
  1286  
  1287  	statePath := testTempFile(t)
  1288  
  1289  	args := []string{
  1290  		"-state", statePath,
  1291  		"-auto-approve",
  1292  	}
  1293  
  1294  	code := c.Run(args)
  1295  	output := done(t)
  1296  	if code != 0 {
  1297  		t.Fatalf("bad: \n%s", output.Stdout())
  1298  	}
  1299  
  1300  	stdout := output.Stdout()
  1301  	if !strings.Contains(stdout, "notsensitive = \"Hello world\"") {
  1302  		t.Fatalf("bad: output should contain 'notsensitive' output\n%s", stdout)
  1303  	}
  1304  	if !strings.Contains(stdout, "sensitive = <sensitive>") {
  1305  		t.Fatalf("bad: output should contain 'sensitive' output\n%s", stdout)
  1306  	}
  1307  }
  1308  
  1309  func TestApply_vars(t *testing.T) {
  1310  	// Create a temporary working directory that is empty
  1311  	td := t.TempDir()
  1312  	testCopyDir(t, testFixturePath("apply-vars"), td)
  1313  	defer testChdir(t, td)()
  1314  
  1315  	statePath := testTempFile(t)
  1316  
  1317  	p := testProvider()
  1318  	view, done := testView(t)
  1319  	c := &ApplyCommand{
  1320  		Meta: Meta{
  1321  			testingOverrides: metaOverridesForProvider(p),
  1322  			View:             view,
  1323  		},
  1324  	}
  1325  
  1326  	actual := ""
  1327  	p.GetProviderSchemaResponse = &providers.GetProviderSchemaResponse{
  1328  		ResourceTypes: map[string]providers.Schema{
  1329  			"test_instance": {
  1330  				Block: &configschema.Block{
  1331  					Attributes: map[string]*configschema.Attribute{
  1332  						"value": {Type: cty.String, Optional: true},
  1333  					},
  1334  				},
  1335  			},
  1336  		},
  1337  	}
  1338  	p.ApplyResourceChangeFn = func(req providers.ApplyResourceChangeRequest) providers.ApplyResourceChangeResponse {
  1339  		return providers.ApplyResourceChangeResponse{
  1340  			NewState: req.PlannedState,
  1341  		}
  1342  	}
  1343  	p.PlanResourceChangeFn = func(req providers.PlanResourceChangeRequest) providers.PlanResourceChangeResponse {
  1344  		actual = req.ProposedNewState.GetAttr("value").AsString()
  1345  		return providers.PlanResourceChangeResponse{
  1346  			PlannedState: req.ProposedNewState,
  1347  		}
  1348  	}
  1349  
  1350  	args := []string{
  1351  		"-auto-approve",
  1352  		"-var", "foo=bar",
  1353  		"-state", statePath,
  1354  	}
  1355  	code := c.Run(args)
  1356  	output := done(t)
  1357  	if code != 0 {
  1358  		t.Fatalf("bad: %d\n\n%s", code, output.Stderr())
  1359  	}
  1360  
  1361  	if actual != "bar" {
  1362  		t.Fatal("didn't work")
  1363  	}
  1364  }
  1365  
  1366  func TestApply_varFile(t *testing.T) {
  1367  	// Create a temporary working directory that is empty
  1368  	td := t.TempDir()
  1369  	testCopyDir(t, testFixturePath("apply-vars"), td)
  1370  	defer testChdir(t, td)()
  1371  
  1372  	varFilePath := testTempFile(t)
  1373  	if err := ioutil.WriteFile(varFilePath, []byte(applyVarFile), 0644); err != nil {
  1374  		t.Fatalf("err: %s", err)
  1375  	}
  1376  
  1377  	statePath := testTempFile(t)
  1378  
  1379  	p := testProvider()
  1380  	view, done := testView(t)
  1381  	c := &ApplyCommand{
  1382  		Meta: Meta{
  1383  			testingOverrides: metaOverridesForProvider(p),
  1384  			View:             view,
  1385  		},
  1386  	}
  1387  
  1388  	actual := ""
  1389  	p.GetProviderSchemaResponse = &providers.GetProviderSchemaResponse{
  1390  		ResourceTypes: map[string]providers.Schema{
  1391  			"test_instance": {
  1392  				Block: &configschema.Block{
  1393  					Attributes: map[string]*configschema.Attribute{
  1394  						"value": {Type: cty.String, Optional: true},
  1395  					},
  1396  				},
  1397  			},
  1398  		},
  1399  	}
  1400  	p.ApplyResourceChangeFn = func(req providers.ApplyResourceChangeRequest) providers.ApplyResourceChangeResponse {
  1401  		return providers.ApplyResourceChangeResponse{
  1402  			NewState: req.PlannedState,
  1403  		}
  1404  	}
  1405  	p.PlanResourceChangeFn = func(req providers.PlanResourceChangeRequest) providers.PlanResourceChangeResponse {
  1406  		actual = req.ProposedNewState.GetAttr("value").AsString()
  1407  		return providers.PlanResourceChangeResponse{
  1408  			PlannedState: req.ProposedNewState,
  1409  		}
  1410  	}
  1411  
  1412  	args := []string{
  1413  		"-auto-approve",
  1414  		"-var-file", varFilePath,
  1415  		"-state", statePath,
  1416  	}
  1417  	code := c.Run(args)
  1418  	output := done(t)
  1419  	if code != 0 {
  1420  		t.Fatalf("bad: %d\n\n%s", code, output.Stderr())
  1421  	}
  1422  
  1423  	if actual != "bar" {
  1424  		t.Fatal("didn't work")
  1425  	}
  1426  }
  1427  
  1428  func TestApply_varFileDefault(t *testing.T) {
  1429  	// Create a temporary working directory that is empty
  1430  	td := t.TempDir()
  1431  	testCopyDir(t, testFixturePath("apply-vars"), td)
  1432  	defer testChdir(t, td)()
  1433  
  1434  	varFilePath := filepath.Join(td, "terraform.tfvars")
  1435  	if err := ioutil.WriteFile(varFilePath, []byte(applyVarFile), 0644); err != nil {
  1436  		t.Fatalf("err: %s", err)
  1437  	}
  1438  
  1439  	statePath := testTempFile(t)
  1440  
  1441  	p := testProvider()
  1442  	view, done := testView(t)
  1443  	c := &ApplyCommand{
  1444  		Meta: Meta{
  1445  			testingOverrides: metaOverridesForProvider(p),
  1446  			View:             view,
  1447  		},
  1448  	}
  1449  
  1450  	actual := ""
  1451  	p.GetProviderSchemaResponse = &providers.GetProviderSchemaResponse{
  1452  		ResourceTypes: map[string]providers.Schema{
  1453  			"test_instance": {
  1454  				Block: &configschema.Block{
  1455  					Attributes: map[string]*configschema.Attribute{
  1456  						"value": {Type: cty.String, Optional: true},
  1457  					},
  1458  				},
  1459  			},
  1460  		},
  1461  	}
  1462  	p.ApplyResourceChangeFn = func(req providers.ApplyResourceChangeRequest) providers.ApplyResourceChangeResponse {
  1463  		return providers.ApplyResourceChangeResponse{
  1464  			NewState: req.PlannedState,
  1465  		}
  1466  	}
  1467  	p.PlanResourceChangeFn = func(req providers.PlanResourceChangeRequest) providers.PlanResourceChangeResponse {
  1468  		actual = req.ProposedNewState.GetAttr("value").AsString()
  1469  		return providers.PlanResourceChangeResponse{
  1470  			PlannedState: req.ProposedNewState,
  1471  		}
  1472  	}
  1473  
  1474  	args := []string{
  1475  		"-auto-approve",
  1476  		"-state", statePath,
  1477  	}
  1478  	code := c.Run(args)
  1479  	output := done(t)
  1480  	if code != 0 {
  1481  		t.Fatalf("bad: %d\n\n%s", code, output.Stderr())
  1482  	}
  1483  
  1484  	if actual != "bar" {
  1485  		t.Fatal("didn't work")
  1486  	}
  1487  }
  1488  
  1489  func TestApply_varFileDefaultJSON(t *testing.T) {
  1490  	// Create a temporary working directory that is empty
  1491  	td := t.TempDir()
  1492  	testCopyDir(t, testFixturePath("apply-vars"), td)
  1493  	defer testChdir(t, td)()
  1494  
  1495  	varFilePath := filepath.Join(td, "terraform.tfvars.json")
  1496  	if err := ioutil.WriteFile(varFilePath, []byte(applyVarFileJSON), 0644); err != nil {
  1497  		t.Fatalf("err: %s", err)
  1498  	}
  1499  
  1500  	statePath := testTempFile(t)
  1501  
  1502  	p := testProvider()
  1503  	view, done := testView(t)
  1504  	c := &ApplyCommand{
  1505  		Meta: Meta{
  1506  			testingOverrides: metaOverridesForProvider(p),
  1507  			View:             view,
  1508  		},
  1509  	}
  1510  
  1511  	actual := ""
  1512  	p.GetProviderSchemaResponse = &providers.GetProviderSchemaResponse{
  1513  		ResourceTypes: map[string]providers.Schema{
  1514  			"test_instance": {
  1515  				Block: &configschema.Block{
  1516  					Attributes: map[string]*configschema.Attribute{
  1517  						"value": {Type: cty.String, Optional: true},
  1518  					},
  1519  				},
  1520  			},
  1521  		},
  1522  	}
  1523  	p.ApplyResourceChangeFn = func(req providers.ApplyResourceChangeRequest) providers.ApplyResourceChangeResponse {
  1524  		return providers.ApplyResourceChangeResponse{
  1525  			NewState: req.PlannedState,
  1526  		}
  1527  	}
  1528  	p.PlanResourceChangeFn = func(req providers.PlanResourceChangeRequest) providers.PlanResourceChangeResponse {
  1529  		actual = req.ProposedNewState.GetAttr("value").AsString()
  1530  		return providers.PlanResourceChangeResponse{
  1531  			PlannedState: req.ProposedNewState,
  1532  		}
  1533  	}
  1534  
  1535  	args := []string{
  1536  		"-auto-approve",
  1537  		"-state", statePath,
  1538  	}
  1539  	code := c.Run(args)
  1540  	output := done(t)
  1541  	if code != 0 {
  1542  		t.Fatalf("bad: %d\n\n%s", code, output.Stderr())
  1543  	}
  1544  
  1545  	if actual != "bar" {
  1546  		t.Fatal("didn't work")
  1547  	}
  1548  }
  1549  
  1550  func TestApply_backup(t *testing.T) {
  1551  	// Create a temporary working directory that is empty
  1552  	td := t.TempDir()
  1553  	testCopyDir(t, testFixturePath("apply"), td)
  1554  	defer testChdir(t, td)()
  1555  
  1556  	originalState := states.BuildState(func(s *states.SyncState) {
  1557  		s.SetResourceInstanceCurrent(
  1558  			addrs.Resource{
  1559  				Mode: addrs.ManagedResourceMode,
  1560  				Type: "test_instance",
  1561  				Name: "foo",
  1562  			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
  1563  			&states.ResourceInstanceObjectSrc{
  1564  				AttrsJSON: []byte("{\n            \"id\": \"bar\"\n          }"),
  1565  				Status:    states.ObjectReady,
  1566  			},
  1567  			addrs.AbsProviderConfig{
  1568  				Provider: addrs.NewDefaultProvider("test"),
  1569  				Module:   addrs.RootModule,
  1570  			},
  1571  		)
  1572  	})
  1573  	statePath := testStateFile(t, originalState)
  1574  	backupPath := testTempFile(t)
  1575  
  1576  	p := applyFixtureProvider()
  1577  	p.PlanResourceChangeResponse = &providers.PlanResourceChangeResponse{
  1578  		PlannedState: cty.ObjectVal(map[string]cty.Value{
  1579  			"ami": cty.StringVal("bar"),
  1580  		}),
  1581  	}
  1582  
  1583  	view, done := testView(t)
  1584  	c := &ApplyCommand{
  1585  		Meta: Meta{
  1586  			testingOverrides: metaOverridesForProvider(p),
  1587  			View:             view,
  1588  		},
  1589  	}
  1590  
  1591  	// Run the apply command pointing to our existing state
  1592  	args := []string{
  1593  		"-auto-approve",
  1594  		"-state", statePath,
  1595  		"-backup", backupPath,
  1596  	}
  1597  	code := c.Run(args)
  1598  	output := done(t)
  1599  	if code != 0 {
  1600  		t.Fatalf("bad: %d\n\n%s", code, output.Stderr())
  1601  	}
  1602  
  1603  	// Verify a new state exists
  1604  	if _, err := os.Stat(statePath); err != nil {
  1605  		t.Fatalf("err: %s", err)
  1606  	}
  1607  
  1608  	state := testStateRead(t, statePath)
  1609  	if state == nil {
  1610  		t.Fatal("state should not be nil")
  1611  	}
  1612  
  1613  	backupState := testStateRead(t, backupPath)
  1614  
  1615  	actual := backupState.RootModule().Resources["test_instance.foo"]
  1616  	expected := originalState.RootModule().Resources["test_instance.foo"]
  1617  	if !cmp.Equal(actual, expected, cmpopts.EquateEmpty()) {
  1618  		t.Fatalf(
  1619  			"wrong aws_instance.foo state\n%s",
  1620  			cmp.Diff(expected, actual, cmp.Transformer("bytesAsString", func(b []byte) string {
  1621  				return string(b)
  1622  			})),
  1623  		)
  1624  	}
  1625  }
  1626  
  1627  func TestApply_disableBackup(t *testing.T) {
  1628  	// Create a temporary working directory that is empty
  1629  	td := t.TempDir()
  1630  	testCopyDir(t, testFixturePath("apply"), td)
  1631  	defer testChdir(t, td)()
  1632  
  1633  	originalState := testState()
  1634  	statePath := testStateFile(t, originalState)
  1635  
  1636  	p := applyFixtureProvider()
  1637  	p.PlanResourceChangeResponse = &providers.PlanResourceChangeResponse{
  1638  		PlannedState: cty.ObjectVal(map[string]cty.Value{
  1639  			"ami": cty.StringVal("bar"),
  1640  		}),
  1641  	}
  1642  
  1643  	view, done := testView(t)
  1644  	c := &ApplyCommand{
  1645  		Meta: Meta{
  1646  			testingOverrides: metaOverridesForProvider(p),
  1647  			View:             view,
  1648  		},
  1649  	}
  1650  
  1651  	// Run the apply command pointing to our existing state
  1652  	args := []string{
  1653  		"-auto-approve",
  1654  		"-state", statePath,
  1655  		"-backup", "-",
  1656  	}
  1657  	code := c.Run(args)
  1658  	output := done(t)
  1659  	if code != 0 {
  1660  		t.Fatalf("bad: %d\n\n%s", code, output.Stderr())
  1661  	}
  1662  
  1663  	// Verify that the provider was called with the existing state
  1664  	actual := p.PlanResourceChangeRequest.PriorState
  1665  	expected := cty.ObjectVal(map[string]cty.Value{
  1666  		"id":  cty.StringVal("bar"),
  1667  		"ami": cty.NullVal(cty.String),
  1668  	})
  1669  	if !expected.RawEquals(actual) {
  1670  		t.Fatalf("wrong prior state during plan\ngot:  %#v\nwant: %#v", actual, expected)
  1671  	}
  1672  
  1673  	actual = p.ApplyResourceChangeRequest.PriorState
  1674  	expected = cty.ObjectVal(map[string]cty.Value{
  1675  		"id":  cty.StringVal("bar"),
  1676  		"ami": cty.NullVal(cty.String),
  1677  	})
  1678  	if !expected.RawEquals(actual) {
  1679  		t.Fatalf("wrong prior state during apply\ngot:  %#v\nwant: %#v", actual, expected)
  1680  	}
  1681  
  1682  	// Verify a new state exists
  1683  	if _, err := os.Stat(statePath); err != nil {
  1684  		t.Fatalf("err: %s", err)
  1685  	}
  1686  
  1687  	state := testStateRead(t, statePath)
  1688  	if state == nil {
  1689  		t.Fatal("state should not be nil")
  1690  	}
  1691  
  1692  	// Ensure there is no backup
  1693  	_, err := os.Stat(statePath + DefaultBackupExtension)
  1694  	if err == nil || !os.IsNotExist(err) {
  1695  		t.Fatalf("backup should not exist")
  1696  	}
  1697  
  1698  	// Ensure there is no literal "-"
  1699  	_, err = os.Stat("-")
  1700  	if err == nil || !os.IsNotExist(err) {
  1701  		t.Fatalf("backup should not exist")
  1702  	}
  1703  }
  1704  
  1705  // Test that the Terraform env is passed through
  1706  func TestApply_terraformEnv(t *testing.T) {
  1707  	// Create a temporary working directory that is empty
  1708  	td := t.TempDir()
  1709  	testCopyDir(t, testFixturePath("apply-terraform-env"), td)
  1710  	defer testChdir(t, td)()
  1711  
  1712  	statePath := testTempFile(t)
  1713  
  1714  	p := testProvider()
  1715  	view, done := testView(t)
  1716  	c := &ApplyCommand{
  1717  		Meta: Meta{
  1718  			testingOverrides: metaOverridesForProvider(p),
  1719  			View:             view,
  1720  		},
  1721  	}
  1722  
  1723  	args := []string{
  1724  		"-auto-approve",
  1725  		"-state", statePath,
  1726  	}
  1727  	code := c.Run(args)
  1728  	output := done(t)
  1729  	if code != 0 {
  1730  		t.Fatalf("bad: %d\n\n%s", code, output.Stderr())
  1731  	}
  1732  
  1733  	expected := strings.TrimSpace(`
  1734  <no state>
  1735  Outputs:
  1736  
  1737  output = default
  1738  	`)
  1739  	testStateOutput(t, statePath, expected)
  1740  }
  1741  
  1742  // Test that the Terraform env is passed through
  1743  func TestApply_terraformEnvNonDefault(t *testing.T) {
  1744  	// Create a temporary working directory that is empty
  1745  	td := t.TempDir()
  1746  	testCopyDir(t, testFixturePath("apply-terraform-env"), td)
  1747  	defer testChdir(t, td)()
  1748  
  1749  	// Create new env
  1750  	{
  1751  		ui := new(cli.MockUi)
  1752  		newCmd := &WorkspaceNewCommand{
  1753  			Meta: Meta{
  1754  				Ui: ui,
  1755  			},
  1756  		}
  1757  		if code := newCmd.Run([]string{"test"}); code != 0 {
  1758  			t.Fatal("error creating workspace")
  1759  		}
  1760  	}
  1761  
  1762  	// Switch to it
  1763  	{
  1764  		args := []string{"test"}
  1765  		ui := new(cli.MockUi)
  1766  		selCmd := &WorkspaceSelectCommand{
  1767  			Meta: Meta{
  1768  				Ui: ui,
  1769  			},
  1770  		}
  1771  		if code := selCmd.Run(args); code != 0 {
  1772  			t.Fatal("error switching workspace")
  1773  		}
  1774  	}
  1775  
  1776  	p := testProvider()
  1777  	view, done := testView(t)
  1778  	c := &ApplyCommand{
  1779  		Meta: Meta{
  1780  			testingOverrides: metaOverridesForProvider(p),
  1781  			View:             view,
  1782  		},
  1783  	}
  1784  
  1785  	args := []string{
  1786  		"-auto-approve",
  1787  	}
  1788  	code := c.Run(args)
  1789  	output := done(t)
  1790  	if code != 0 {
  1791  		t.Fatalf("bad: %d\n\n%s", code, output.Stderr())
  1792  	}
  1793  
  1794  	statePath := filepath.Join("terraform.tfstate.d", "test", "terraform.tfstate")
  1795  	expected := strings.TrimSpace(`
  1796  <no state>
  1797  Outputs:
  1798  
  1799  output = test
  1800  	`)
  1801  	testStateOutput(t, statePath, expected)
  1802  }
  1803  
  1804  // Config with multiple resources, targeting apply of a subset
  1805  func TestApply_targeted(t *testing.T) {
  1806  	td := t.TempDir()
  1807  	testCopyDir(t, testFixturePath("apply-targeted"), td)
  1808  	defer testChdir(t, td)()
  1809  
  1810  	p := testProvider()
  1811  	p.GetProviderSchemaResponse = &providers.GetProviderSchemaResponse{
  1812  		ResourceTypes: map[string]providers.Schema{
  1813  			"test_instance": {
  1814  				Block: &configschema.Block{
  1815  					Attributes: map[string]*configschema.Attribute{
  1816  						"id": {Type: cty.String, Computed: true},
  1817  					},
  1818  				},
  1819  			},
  1820  		},
  1821  	}
  1822  	p.PlanResourceChangeFn = func(req providers.PlanResourceChangeRequest) providers.PlanResourceChangeResponse {
  1823  		return providers.PlanResourceChangeResponse{
  1824  			PlannedState: req.ProposedNewState,
  1825  		}
  1826  	}
  1827  
  1828  	view, done := testView(t)
  1829  	c := &ApplyCommand{
  1830  		Meta: Meta{
  1831  			testingOverrides: metaOverridesForProvider(p),
  1832  			View:             view,
  1833  		},
  1834  	}
  1835  
  1836  	args := []string{
  1837  		"-auto-approve",
  1838  		"-target", "test_instance.foo",
  1839  		"-target", "test_instance.baz",
  1840  	}
  1841  	code := c.Run(args)
  1842  	output := done(t)
  1843  	if code != 0 {
  1844  		t.Fatalf("bad: %d\n\n%s", code, output.Stderr())
  1845  	}
  1846  
  1847  	if got, want := output.Stdout(), "3 added, 0 changed, 0 destroyed"; !strings.Contains(got, want) {
  1848  		t.Fatalf("bad change summary, want %q, got:\n%s", want, got)
  1849  	}
  1850  }
  1851  
  1852  // Diagnostics for invalid -target flags
  1853  func TestApply_targetFlagsDiags(t *testing.T) {
  1854  	testCases := map[string]string{
  1855  		"test_instance.": "Dot must be followed by attribute name.",
  1856  		"test_instance":  "Resource specification must include a resource type and name.",
  1857  	}
  1858  
  1859  	for target, wantDiag := range testCases {
  1860  		t.Run(target, func(t *testing.T) {
  1861  			td := testTempDir(t)
  1862  			defer os.RemoveAll(td)
  1863  			defer testChdir(t, td)()
  1864  
  1865  			view, done := testView(t)
  1866  			c := &ApplyCommand{
  1867  				Meta: Meta{
  1868  					View: view,
  1869  				},
  1870  			}
  1871  
  1872  			args := []string{
  1873  				"-auto-approve",
  1874  				"-target", target,
  1875  			}
  1876  			code := c.Run(args)
  1877  			output := done(t)
  1878  			if code != 1 {
  1879  				t.Fatalf("bad: %d\n\n%s", code, output.Stderr())
  1880  			}
  1881  
  1882  			got := output.Stderr()
  1883  			if !strings.Contains(got, target) {
  1884  				t.Fatalf("bad error output, want %q, got:\n%s", target, got)
  1885  			}
  1886  			if !strings.Contains(got, wantDiag) {
  1887  				t.Fatalf("bad error output, want %q, got:\n%s", wantDiag, got)
  1888  			}
  1889  		})
  1890  	}
  1891  }
  1892  
  1893  func TestApply_replace(t *testing.T) {
  1894  	td := t.TempDir()
  1895  	testCopyDir(t, testFixturePath("apply-replace"), td)
  1896  	defer testChdir(t, td)()
  1897  
  1898  	originalState := states.BuildState(func(s *states.SyncState) {
  1899  		s.SetResourceInstanceCurrent(
  1900  			addrs.Resource{
  1901  				Mode: addrs.ManagedResourceMode,
  1902  				Type: "test_instance",
  1903  				Name: "a",
  1904  			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
  1905  			&states.ResourceInstanceObjectSrc{
  1906  				AttrsJSON: []byte(`{"id":"hello"}`),
  1907  				Status:    states.ObjectReady,
  1908  			},
  1909  			addrs.AbsProviderConfig{
  1910  				Provider: addrs.NewDefaultProvider("test"),
  1911  				Module:   addrs.RootModule,
  1912  			},
  1913  		)
  1914  	})
  1915  	statePath := testStateFile(t, originalState)
  1916  
  1917  	p := testProvider()
  1918  	p.GetProviderSchemaResponse = &providers.GetProviderSchemaResponse{
  1919  		ResourceTypes: map[string]providers.Schema{
  1920  			"test_instance": {
  1921  				Block: &configschema.Block{
  1922  					Attributes: map[string]*configschema.Attribute{
  1923  						"id": {Type: cty.String, Computed: true},
  1924  					},
  1925  				},
  1926  			},
  1927  		},
  1928  	}
  1929  	p.PlanResourceChangeFn = func(req providers.PlanResourceChangeRequest) providers.PlanResourceChangeResponse {
  1930  		return providers.PlanResourceChangeResponse{
  1931  			PlannedState: req.ProposedNewState,
  1932  		}
  1933  	}
  1934  	createCount := 0
  1935  	deleteCount := 0
  1936  	p.ApplyResourceChangeFn = func(req providers.ApplyResourceChangeRequest) providers.ApplyResourceChangeResponse {
  1937  		if req.PriorState.IsNull() {
  1938  			createCount++
  1939  		}
  1940  		if req.PlannedState.IsNull() {
  1941  			deleteCount++
  1942  		}
  1943  		return providers.ApplyResourceChangeResponse{
  1944  			NewState: req.PlannedState,
  1945  		}
  1946  	}
  1947  
  1948  	view, done := testView(t)
  1949  	c := &ApplyCommand{
  1950  		Meta: Meta{
  1951  			testingOverrides: metaOverridesForProvider(p),
  1952  			View:             view,
  1953  		},
  1954  	}
  1955  
  1956  	args := []string{
  1957  		"-auto-approve",
  1958  		"-state", statePath,
  1959  		"-replace", "test_instance.a",
  1960  	}
  1961  	code := c.Run(args)
  1962  	output := done(t)
  1963  	if code != 0 {
  1964  		t.Fatalf("wrong exit code %d\n\n%s", code, output.Stderr())
  1965  	}
  1966  
  1967  	if got, want := output.Stdout(), "1 added, 0 changed, 1 destroyed"; !strings.Contains(got, want) {
  1968  		t.Errorf("wrong change summary\ngot output:\n%s\n\nwant substring: %s", got, want)
  1969  	}
  1970  
  1971  	if got, want := createCount, 1; got != want {
  1972  		t.Errorf("wrong create count %d; want %d", got, want)
  1973  	}
  1974  	if got, want := deleteCount, 1; got != want {
  1975  		t.Errorf("wrong create count %d; want %d", got, want)
  1976  	}
  1977  }
  1978  
  1979  func TestApply_pluginPath(t *testing.T) {
  1980  	// Create a temporary working directory that is empty
  1981  	td := t.TempDir()
  1982  	testCopyDir(t, testFixturePath("apply"), td)
  1983  	defer testChdir(t, td)()
  1984  
  1985  	statePath := testTempFile(t)
  1986  
  1987  	p := applyFixtureProvider()
  1988  
  1989  	view, done := testView(t)
  1990  	c := &ApplyCommand{
  1991  		Meta: Meta{
  1992  			testingOverrides: metaOverridesForProvider(p),
  1993  			View:             view,
  1994  		},
  1995  	}
  1996  
  1997  	pluginPath := []string{"a", "b", "c"}
  1998  
  1999  	if err := c.Meta.storePluginPath(pluginPath); err != nil {
  2000  		t.Fatal(err)
  2001  	}
  2002  	c.Meta.pluginPath = nil
  2003  
  2004  	args := []string{
  2005  		"-state", statePath,
  2006  		"-auto-approve",
  2007  	}
  2008  	code := c.Run(args)
  2009  	output := done(t)
  2010  	if code != 0 {
  2011  		t.Fatalf("bad: %d\n\n%s", code, output.Stderr())
  2012  	}
  2013  
  2014  	if !reflect.DeepEqual(pluginPath, c.Meta.pluginPath) {
  2015  		t.Fatalf("expected plugin path %#v, got %#v", pluginPath, c.Meta.pluginPath)
  2016  	}
  2017  }
  2018  
  2019  func TestApply_jsonGoldenReference(t *testing.T) {
  2020  	// Create a temporary working directory that is empty
  2021  	td := t.TempDir()
  2022  	testCopyDir(t, testFixturePath("apply"), td)
  2023  	defer testChdir(t, td)()
  2024  
  2025  	statePath := testTempFile(t)
  2026  
  2027  	p := applyFixtureProvider()
  2028  
  2029  	view, done := testView(t)
  2030  	c := &ApplyCommand{
  2031  		Meta: Meta{
  2032  			testingOverrides: metaOverridesForProvider(p),
  2033  			View:             view,
  2034  		},
  2035  	}
  2036  
  2037  	args := []string{
  2038  		"-json",
  2039  		"-state", statePath,
  2040  		"-auto-approve",
  2041  	}
  2042  	code := c.Run(args)
  2043  	output := done(t)
  2044  	if code != 0 {
  2045  		t.Fatalf("bad: %d\n\n%s", code, output.Stderr())
  2046  	}
  2047  
  2048  	if _, err := os.Stat(statePath); err != nil {
  2049  		t.Fatalf("err: %s", err)
  2050  	}
  2051  
  2052  	state := testStateRead(t, statePath)
  2053  	if state == nil {
  2054  		t.Fatal("state should not be nil")
  2055  	}
  2056  
  2057  	checkGoldenReference(t, output, "apply")
  2058  }
  2059  
  2060  func TestApply_warnings(t *testing.T) {
  2061  	// Create a temporary working directory that is empty
  2062  	td := t.TempDir()
  2063  	testCopyDir(t, testFixturePath("apply"), td)
  2064  	defer testChdir(t, td)()
  2065  
  2066  	p := testProvider()
  2067  	p.GetProviderSchemaResponse = applyFixtureSchema()
  2068  	p.PlanResourceChangeFn = func(req providers.PlanResourceChangeRequest) providers.PlanResourceChangeResponse {
  2069  		return providers.PlanResourceChangeResponse{
  2070  			PlannedState: req.ProposedNewState,
  2071  			Diagnostics: tfdiags.Diagnostics{
  2072  				tfdiags.SimpleWarning("warning 1"),
  2073  				tfdiags.SimpleWarning("warning 2"),
  2074  			},
  2075  		}
  2076  	}
  2077  	p.ApplyResourceChangeFn = func(req providers.ApplyResourceChangeRequest) providers.ApplyResourceChangeResponse {
  2078  		return providers.ApplyResourceChangeResponse{
  2079  			NewState: cty.UnknownAsNull(req.PlannedState),
  2080  		}
  2081  	}
  2082  
  2083  	t.Run("full warnings", func(t *testing.T) {
  2084  		view, done := testView(t)
  2085  		c := &ApplyCommand{
  2086  			Meta: Meta{
  2087  				testingOverrides: metaOverridesForProvider(p),
  2088  				View:             view,
  2089  			},
  2090  		}
  2091  
  2092  		args := []string{"-auto-approve"}
  2093  		code := c.Run(args)
  2094  		output := done(t)
  2095  		if code != 0 {
  2096  			t.Fatalf("bad: %d\n\n%s", code, output.Stderr())
  2097  		}
  2098  		wantWarnings := []string{
  2099  			"warning 1",
  2100  			"warning 2",
  2101  		}
  2102  		for _, want := range wantWarnings {
  2103  			if !strings.Contains(output.Stdout(), want) {
  2104  				t.Errorf("missing warning %s", want)
  2105  			}
  2106  		}
  2107  	})
  2108  
  2109  	t.Run("compact warnings", func(t *testing.T) {
  2110  		view, done := testView(t)
  2111  		c := &ApplyCommand{
  2112  			Meta: Meta{
  2113  				testingOverrides: metaOverridesForProvider(p),
  2114  				View:             view,
  2115  			},
  2116  		}
  2117  
  2118  		code := c.Run([]string{"-auto-approve", "-compact-warnings"})
  2119  		output := done(t)
  2120  		if code != 0 {
  2121  			t.Fatalf("bad: %d\n\n%s", code, output.Stderr())
  2122  		}
  2123  		// the output should contain 2 warnings and a message about -compact-warnings
  2124  		wantWarnings := []string{
  2125  			"warning 1",
  2126  			"warning 2",
  2127  			"To see the full warning notes, run Terraform without -compact-warnings.",
  2128  		}
  2129  		for _, want := range wantWarnings {
  2130  			if !strings.Contains(output.Stdout(), want) {
  2131  				t.Errorf("missing warning %s", want)
  2132  			}
  2133  		}
  2134  	})
  2135  }
  2136  
  2137  // applyFixtureSchema returns a schema suitable for processing the
  2138  // configuration in testdata/apply . This schema should be
  2139  // assigned to a mock provider named "test".
  2140  func applyFixtureSchema() *providers.GetProviderSchemaResponse {
  2141  	return &providers.GetProviderSchemaResponse{
  2142  		ResourceTypes: map[string]providers.Schema{
  2143  			"test_instance": {
  2144  				Block: &configschema.Block{
  2145  					Attributes: map[string]*configschema.Attribute{
  2146  						"id":  {Type: cty.String, Optional: true, Computed: true},
  2147  						"ami": {Type: cty.String, Optional: true},
  2148  					},
  2149  				},
  2150  			},
  2151  		},
  2152  	}
  2153  }
  2154  
  2155  // applyFixtureProvider returns a mock provider that is configured for basic
  2156  // operation with the configuration in testdata/apply. This mock has
  2157  // GetSchemaResponse, PlanResourceChangeFn, and ApplyResourceChangeFn populated,
  2158  // with the plan/apply steps just passing through the data determined by
  2159  // Terraform Core.
  2160  func applyFixtureProvider() *terraform.MockProvider {
  2161  	p := testProvider()
  2162  	p.GetProviderSchemaResponse = applyFixtureSchema()
  2163  	p.PlanResourceChangeFn = func(req providers.PlanResourceChangeRequest) providers.PlanResourceChangeResponse {
  2164  		return providers.PlanResourceChangeResponse{
  2165  			PlannedState: req.ProposedNewState,
  2166  		}
  2167  	}
  2168  	p.ApplyResourceChangeFn = func(req providers.ApplyResourceChangeRequest) providers.ApplyResourceChangeResponse {
  2169  		return providers.ApplyResourceChangeResponse{
  2170  			NewState: cty.UnknownAsNull(req.PlannedState),
  2171  		}
  2172  	}
  2173  	return p
  2174  }
  2175  
  2176  // applyFixturePlanFile creates a plan file at a temporary location containing
  2177  // a single change to create the test_instance.foo that is included in the
  2178  // "apply" test fixture, returning the location of that plan file.
  2179  func applyFixturePlanFile(t *testing.T) string {
  2180  	return applyFixturePlanFileMatchState(t, statemgr.SnapshotMeta{})
  2181  }
  2182  
  2183  // applyFixturePlanFileMatchState creates a planfile like applyFixturePlanFile,
  2184  // but inserts the state meta information if that plan must match a preexisting
  2185  // state.
  2186  func applyFixturePlanFileMatchState(t *testing.T, stateMeta statemgr.SnapshotMeta) string {
  2187  	_, snap := testModuleWithSnapshot(t, "apply")
  2188  	plannedVal := cty.ObjectVal(map[string]cty.Value{
  2189  		"id":  cty.UnknownVal(cty.String),
  2190  		"ami": cty.StringVal("bar"),
  2191  	})
  2192  	priorValRaw, err := plans.NewDynamicValue(cty.NullVal(plannedVal.Type()), plannedVal.Type())
  2193  	if err != nil {
  2194  		t.Fatal(err)
  2195  	}
  2196  	plannedValRaw, err := plans.NewDynamicValue(plannedVal, plannedVal.Type())
  2197  	if err != nil {
  2198  		t.Fatal(err)
  2199  	}
  2200  	plan := testPlan(t)
  2201  	plan.Changes.SyncWrapper().AppendResourceInstanceChange(&plans.ResourceInstanceChangeSrc{
  2202  		Addr: addrs.Resource{
  2203  			Mode: addrs.ManagedResourceMode,
  2204  			Type: "test_instance",
  2205  			Name: "foo",
  2206  		}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
  2207  		ProviderAddr: addrs.AbsProviderConfig{
  2208  			Provider: addrs.NewDefaultProvider("test"),
  2209  			Module:   addrs.RootModule,
  2210  		},
  2211  		ChangeSrc: plans.ChangeSrc{
  2212  			Action: plans.Create,
  2213  			Before: priorValRaw,
  2214  			After:  plannedValRaw,
  2215  		},
  2216  	})
  2217  	return testPlanFileMatchState(
  2218  		t,
  2219  		snap,
  2220  		states.NewState(),
  2221  		plan,
  2222  		stateMeta,
  2223  	)
  2224  }
  2225  
  2226  const applyVarFile = `
  2227  foo = "bar"
  2228  `
  2229  
  2230  const applyVarFileJSON = `
  2231  { "foo": "bar" }
  2232  `