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

     1  package command
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"log"
     8  	"net"
     9  	"net/http"
    10  	"net/url"
    11  	"os"
    12  	"path/filepath"
    13  	"reflect"
    14  	"strings"
    15  	"sync"
    16  	"testing"
    17  	"time"
    18  
    19  	"github.com/hashicorp/terraform/state"
    20  	"github.com/hashicorp/terraform/terraform"
    21  	"github.com/mitchellh/cli"
    22  )
    23  
    24  func TestApply(t *testing.T) {
    25  	statePath := testTempFile(t)
    26  
    27  	p := testProvider()
    28  	ui := new(cli.MockUi)
    29  	c := &ApplyCommand{
    30  		Meta: Meta{
    31  			testingOverrides: metaOverridesForProvider(p),
    32  			Ui:               ui,
    33  		},
    34  	}
    35  
    36  	args := []string{
    37  		"-state", statePath,
    38  		"-auto-approve",
    39  		testFixturePath("apply"),
    40  	}
    41  	if code := c.Run(args); code != 0 {
    42  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
    43  	}
    44  
    45  	if _, err := os.Stat(statePath); err != nil {
    46  		t.Fatalf("err: %s", err)
    47  	}
    48  
    49  	state := testStateRead(t, statePath)
    50  	if state == nil {
    51  		t.Fatal("state should not be nil")
    52  	}
    53  }
    54  
    55  // test apply with locked state
    56  func TestApply_lockedState(t *testing.T) {
    57  	statePath := testTempFile(t)
    58  
    59  	unlock, err := testLockState("./testdata", statePath)
    60  	if err != nil {
    61  		t.Fatal(err)
    62  	}
    63  	defer unlock()
    64  
    65  	p := testProvider()
    66  	ui := new(cli.MockUi)
    67  	c := &ApplyCommand{
    68  		Meta: Meta{
    69  			testingOverrides: metaOverridesForProvider(p),
    70  			Ui:               ui,
    71  		},
    72  	}
    73  
    74  	args := []string{
    75  		"-state", statePath,
    76  		"-auto-approve",
    77  		testFixturePath("apply"),
    78  	}
    79  	if code := c.Run(args); code == 0 {
    80  		t.Fatal("expected error")
    81  	}
    82  
    83  	output := ui.ErrorWriter.String()
    84  	if !strings.Contains(output, "lock") {
    85  		t.Fatal("command output does not look like a lock error:", output)
    86  	}
    87  }
    88  
    89  // test apply with locked state, waiting for unlock
    90  func TestApply_lockedStateWait(t *testing.T) {
    91  	statePath := testTempFile(t)
    92  
    93  	unlock, err := testLockState("./testdata", statePath)
    94  	if err != nil {
    95  		t.Fatal(err)
    96  	}
    97  
    98  	// unlock during apply
    99  	go func() {
   100  		time.Sleep(500 * time.Millisecond)
   101  		unlock()
   102  	}()
   103  
   104  	p := testProvider()
   105  	ui := new(cli.MockUi)
   106  	c := &ApplyCommand{
   107  		Meta: Meta{
   108  			testingOverrides: metaOverridesForProvider(p),
   109  			Ui:               ui,
   110  		},
   111  	}
   112  
   113  	// wait 4s just in case the lock process doesn't release in under a second,
   114  	// and we want our context to be alive for a second retry at the 3s mark.
   115  	args := []string{
   116  		"-state", statePath,
   117  		"-lock-timeout", "4s",
   118  		"-auto-approve",
   119  		testFixturePath("apply"),
   120  	}
   121  	if code := c.Run(args); code != 0 {
   122  		log.Fatalf("lock should have succeed in less than 3s: %s", ui.ErrorWriter)
   123  	}
   124  }
   125  
   126  // high water mark counter
   127  type hwm struct {
   128  	sync.Mutex
   129  	val int
   130  	max int
   131  }
   132  
   133  func (t *hwm) Inc() {
   134  	t.Lock()
   135  	defer t.Unlock()
   136  	t.val++
   137  	if t.val > t.max {
   138  		t.max = t.val
   139  	}
   140  }
   141  
   142  func (t *hwm) Dec() {
   143  	t.Lock()
   144  	defer t.Unlock()
   145  	t.val--
   146  }
   147  
   148  func (t *hwm) Max() int {
   149  	t.Lock()
   150  	defer t.Unlock()
   151  	return t.max
   152  }
   153  
   154  func TestApply_parallelism(t *testing.T) {
   155  	provider := testProvider()
   156  	statePath := testTempFile(t)
   157  
   158  	par := 4
   159  
   160  	// This blocks all the appy functions. We close it when we exit so
   161  	// they end quickly after this test finishes.
   162  	block := make(chan struct{})
   163  	// signal how many goroutines have started
   164  	started := make(chan int, 100)
   165  
   166  	runCount := &hwm{}
   167  
   168  	provider.ApplyFn = func(
   169  		i *terraform.InstanceInfo,
   170  		s *terraform.InstanceState,
   171  		d *terraform.InstanceDiff) (*terraform.InstanceState, error) {
   172  		// Increment so we're counting parallelism
   173  		started <- 1
   174  		runCount.Inc()
   175  		defer runCount.Dec()
   176  		// Block here to stage up our max number of parallel instances
   177  		<-block
   178  
   179  		return nil, nil
   180  	}
   181  
   182  	ui := new(cli.MockUi)
   183  	c := &ApplyCommand{
   184  		Meta: Meta{
   185  			testingOverrides: metaOverridesForProvider(provider),
   186  			Ui:               ui,
   187  		},
   188  	}
   189  
   190  	args := []string{
   191  		"-state", statePath,
   192  		"-auto-approve",
   193  		fmt.Sprintf("-parallelism=%d", par),
   194  		testFixturePath("parallelism"),
   195  	}
   196  
   197  	// Run in a goroutine. We can get any errors from the ui.OutputWriter
   198  	doneCh := make(chan int, 1)
   199  	go func() {
   200  		doneCh <- c.Run(args)
   201  	}()
   202  
   203  	timeout := time.After(5 * time.Second)
   204  
   205  	// ensure things are running
   206  	for i := 0; i < par; i++ {
   207  		select {
   208  		case <-timeout:
   209  			t.Fatal("timeout waiting for all goroutines to start")
   210  		case <-started:
   211  		}
   212  	}
   213  
   214  	// a little extra sleep, since we can't ensure all goroutines from the walk have
   215  	// really started
   216  	time.Sleep(100 * time.Millisecond)
   217  	close(block)
   218  
   219  	select {
   220  	case res := <-doneCh:
   221  		if res != 0 {
   222  			t.Fatal(ui.OutputWriter.String())
   223  		}
   224  	case <-timeout:
   225  		t.Fatal("timeout waiting from Run()")
   226  	}
   227  
   228  	// The total in flight should equal the parallelism
   229  	if runCount.Max() != par {
   230  		t.Fatalf("Expected parallelism: %d, got: %d", par, runCount.Max())
   231  	}
   232  }
   233  
   234  func TestApply_configInvalid(t *testing.T) {
   235  	p := testProvider()
   236  	ui := new(cli.MockUi)
   237  	c := &ApplyCommand{
   238  		Meta: Meta{
   239  			testingOverrides: metaOverridesForProvider(p),
   240  			Ui:               ui,
   241  		},
   242  	}
   243  
   244  	args := []string{
   245  		"-state", testTempFile(t),
   246  		"-auto-approve",
   247  		testFixturePath("apply-config-invalid"),
   248  	}
   249  	if code := c.Run(args); code != 1 {
   250  		t.Fatalf("bad: \n%s", ui.OutputWriter.String())
   251  	}
   252  }
   253  
   254  func TestApply_defaultState(t *testing.T) {
   255  	td, err := ioutil.TempDir("", "tf")
   256  	if err != nil {
   257  		t.Fatalf("err: %s", err)
   258  	}
   259  	statePath := filepath.Join(td, DefaultStateFilename)
   260  
   261  	// Change to the temporary directory
   262  	cwd, err := os.Getwd()
   263  	if err != nil {
   264  		t.Fatalf("err: %s", err)
   265  	}
   266  	if err := os.Chdir(filepath.Dir(statePath)); err != nil {
   267  		t.Fatalf("err: %s", err)
   268  	}
   269  	defer os.Chdir(cwd)
   270  
   271  	p := testProvider()
   272  	ui := new(cli.MockUi)
   273  	c := &ApplyCommand{
   274  		Meta: Meta{
   275  			testingOverrides: metaOverridesForProvider(p),
   276  			Ui:               ui,
   277  		},
   278  	}
   279  
   280  	// create an existing state file
   281  	localState := &state.LocalState{Path: statePath}
   282  	if err := localState.WriteState(terraform.NewState()); err != nil {
   283  		t.Fatal(err)
   284  	}
   285  
   286  	serial := localState.State().Serial
   287  
   288  	args := []string{
   289  		"-auto-approve",
   290  		testFixturePath("apply"),
   291  	}
   292  	if code := c.Run(args); code != 0 {
   293  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   294  	}
   295  
   296  	if _, err := os.Stat(statePath); err != nil {
   297  		t.Fatalf("err: %s", err)
   298  	}
   299  
   300  	state := testStateRead(t, statePath)
   301  	if state == nil {
   302  		t.Fatal("state should not be nil")
   303  	}
   304  
   305  	if state.Serial <= serial {
   306  		t.Fatalf("serial was not incremented. previous:%d, current%d", serial, state.Serial)
   307  	}
   308  }
   309  
   310  func TestApply_error(t *testing.T) {
   311  	statePath := testTempFile(t)
   312  
   313  	p := testProvider()
   314  	ui := new(cli.MockUi)
   315  	c := &ApplyCommand{
   316  		Meta: Meta{
   317  			testingOverrides: metaOverridesForProvider(p),
   318  			Ui:               ui,
   319  		},
   320  	}
   321  
   322  	var lock sync.Mutex
   323  	errored := false
   324  	p.ApplyFn = func(
   325  		info *terraform.InstanceInfo,
   326  		s *terraform.InstanceState,
   327  		d *terraform.InstanceDiff) (*terraform.InstanceState, error) {
   328  		lock.Lock()
   329  		defer lock.Unlock()
   330  
   331  		if !errored {
   332  			errored = true
   333  			return nil, fmt.Errorf("error")
   334  		}
   335  
   336  		return &terraform.InstanceState{ID: "foo"}, nil
   337  	}
   338  	p.DiffFn = func(
   339  		*terraform.InstanceInfo,
   340  		*terraform.InstanceState,
   341  		*terraform.ResourceConfig) (*terraform.InstanceDiff, error) {
   342  		return &terraform.InstanceDiff{
   343  			Attributes: map[string]*terraform.ResourceAttrDiff{
   344  				"ami": &terraform.ResourceAttrDiff{
   345  					New: "bar",
   346  				},
   347  			},
   348  		}, nil
   349  	}
   350  
   351  	args := []string{
   352  		"-state", statePath,
   353  		"-auto-approve",
   354  		testFixturePath("apply-error"),
   355  	}
   356  	if code := c.Run(args); code != 1 {
   357  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   358  	}
   359  
   360  	if _, err := os.Stat(statePath); err != nil {
   361  		t.Fatalf("err: %s", err)
   362  	}
   363  
   364  	state := testStateRead(t, statePath)
   365  	if state == nil {
   366  		t.Fatal("state should not be nil")
   367  	}
   368  	if len(state.RootModule().Resources) == 0 {
   369  		t.Fatal("no resources in state")
   370  	}
   371  }
   372  
   373  func TestApply_input(t *testing.T) {
   374  	// Disable test mode so input would be asked
   375  	test = false
   376  	defer func() { test = true }()
   377  
   378  	// Set some default reader/writers for the inputs
   379  	defaultInputReader = bytes.NewBufferString("foo\n")
   380  	defaultInputWriter = new(bytes.Buffer)
   381  
   382  	statePath := testTempFile(t)
   383  
   384  	p := testProvider()
   385  	ui := new(cli.MockUi)
   386  	c := &ApplyCommand{
   387  		Meta: Meta{
   388  			testingOverrides: metaOverridesForProvider(p),
   389  			Ui:               ui,
   390  		},
   391  	}
   392  
   393  	args := []string{
   394  		"-state", statePath,
   395  		"-auto-approve",
   396  		testFixturePath("apply-input"),
   397  	}
   398  	if code := c.Run(args); code != 0 {
   399  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   400  	}
   401  
   402  	if !p.InputCalled {
   403  		t.Fatal("input should be called")
   404  	}
   405  }
   406  
   407  // When only a partial set of the variables are set, Terraform
   408  // should still ask for the unset ones by default (with -input=true)
   409  func TestApply_inputPartial(t *testing.T) {
   410  	// Disable test mode so input would be asked
   411  	test = false
   412  	defer func() { test = true }()
   413  
   414  	// Set some default reader/writers for the inputs
   415  	defaultInputReader = bytes.NewBufferString("one\ntwo\n")
   416  	defaultInputWriter = new(bytes.Buffer)
   417  
   418  	statePath := testTempFile(t)
   419  
   420  	p := testProvider()
   421  	ui := new(cli.MockUi)
   422  	c := &ApplyCommand{
   423  		Meta: Meta{
   424  			testingOverrides: metaOverridesForProvider(p),
   425  			Ui:               ui,
   426  		},
   427  	}
   428  
   429  	args := []string{
   430  		"-state", statePath,
   431  		"-auto-approve",
   432  		"-var", "foo=foovalue",
   433  		testFixturePath("apply-input-partial"),
   434  	}
   435  	if code := c.Run(args); code != 0 {
   436  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   437  	}
   438  
   439  	expected := strings.TrimSpace(`
   440  <no state>
   441  Outputs:
   442  
   443  bar = one
   444  foo = foovalue
   445  	`)
   446  	testStateOutput(t, statePath, expected)
   447  }
   448  
   449  func TestApply_noArgs(t *testing.T) {
   450  	cwd, err := os.Getwd()
   451  	if err != nil {
   452  		t.Fatalf("err: %s", err)
   453  	}
   454  	if err := os.Chdir(testFixturePath("plan")); err != nil {
   455  		t.Fatalf("err: %s", err)
   456  	}
   457  	defer os.Chdir(cwd)
   458  
   459  	statePath := testTempFile(t)
   460  
   461  	p := testProvider()
   462  	ui := new(cli.MockUi)
   463  	c := &ApplyCommand{
   464  		Meta: Meta{
   465  			testingOverrides: metaOverridesForProvider(p),
   466  			Ui:               ui,
   467  		},
   468  	}
   469  
   470  	args := []string{
   471  		"-state", statePath,
   472  		"-auto-approve",
   473  	}
   474  	if code := c.Run(args); code != 0 {
   475  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   476  	}
   477  
   478  	if _, err := os.Stat(statePath); err != nil {
   479  		t.Fatalf("err: %s", err)
   480  	}
   481  
   482  	state := testStateRead(t, statePath)
   483  	if err != nil {
   484  		t.Fatalf("err: %s", err)
   485  	}
   486  	if state == nil {
   487  		t.Fatal("state should not be nil")
   488  	}
   489  }
   490  
   491  func TestApply_plan(t *testing.T) {
   492  	// Disable test mode so input would be asked
   493  	test = false
   494  	defer func() { test = true }()
   495  
   496  	// Set some default reader/writers for the inputs
   497  	defaultInputReader = new(bytes.Buffer)
   498  	defaultInputWriter = new(bytes.Buffer)
   499  
   500  	planPath := testPlanFile(t, &terraform.Plan{
   501  		Module: testModule(t, "apply"),
   502  	})
   503  	statePath := testTempFile(t)
   504  
   505  	p := testProvider()
   506  	ui := new(cli.MockUi)
   507  	c := &ApplyCommand{
   508  		Meta: Meta{
   509  			testingOverrides: metaOverridesForProvider(p),
   510  			Ui:               ui,
   511  		},
   512  	}
   513  
   514  	args := []string{
   515  		"-state-out", statePath,
   516  		planPath,
   517  	}
   518  	if code := c.Run(args); code != 0 {
   519  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   520  	}
   521  
   522  	if p.InputCalled {
   523  		t.Fatalf("input should not be called for plans")
   524  	}
   525  
   526  	if _, err := os.Stat(statePath); err != nil {
   527  		t.Fatalf("err: %s", err)
   528  	}
   529  
   530  	state := testStateRead(t, statePath)
   531  	if state == nil {
   532  		t.Fatal("state should not be nil")
   533  	}
   534  }
   535  
   536  func TestApply_plan_backup(t *testing.T) {
   537  	plan := testPlan(t)
   538  	planPath := testPlanFile(t, plan)
   539  	statePath := testTempFile(t)
   540  	backupPath := testTempFile(t)
   541  
   542  	p := testProvider()
   543  	ui := new(cli.MockUi)
   544  	c := &ApplyCommand{
   545  		Meta: Meta{
   546  			testingOverrides: metaOverridesForProvider(p),
   547  			Ui:               ui,
   548  		},
   549  	}
   550  
   551  	// create a state file that needs to be backed up
   552  	err := (&state.LocalState{Path: statePath}).WriteState(plan.State)
   553  	if err != nil {
   554  		t.Fatal(err)
   555  	}
   556  	args := []string{
   557  		"-state-out", statePath,
   558  		"-backup", backupPath,
   559  		planPath,
   560  	}
   561  	if code := c.Run(args); code != 0 {
   562  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   563  	}
   564  
   565  	// Should have a backup file
   566  	testStateRead(t, backupPath)
   567  }
   568  
   569  func TestApply_plan_noBackup(t *testing.T) {
   570  	planPath := testPlanFile(t, testPlan(t))
   571  	statePath := testTempFile(t)
   572  
   573  	p := testProvider()
   574  	ui := new(cli.MockUi)
   575  	c := &ApplyCommand{
   576  		Meta: Meta{
   577  			testingOverrides: metaOverridesForProvider(p),
   578  			Ui:               ui,
   579  		},
   580  	}
   581  
   582  	args := []string{
   583  		"-state-out", statePath,
   584  		"-backup", "-",
   585  		planPath,
   586  	}
   587  	if code := c.Run(args); code != 0 {
   588  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   589  	}
   590  
   591  	// Ensure there is no backup
   592  	_, err := os.Stat(statePath + DefaultBackupExtension)
   593  	if err == nil || !os.IsNotExist(err) {
   594  		t.Fatalf("backup should not exist")
   595  	}
   596  
   597  	// Ensure there is no literal "-"
   598  	_, err = os.Stat("-")
   599  	if err == nil || !os.IsNotExist(err) {
   600  		t.Fatalf("backup should not exist")
   601  	}
   602  }
   603  
   604  func TestApply_plan_remoteState(t *testing.T) {
   605  	// Disable test mode so input would be asked
   606  	test = false
   607  	defer func() { test = true }()
   608  	tmp, cwd := testCwd(t)
   609  	defer testFixCwd(t, tmp, cwd)
   610  	remoteStatePath := filepath.Join(tmp, DefaultDataDir, DefaultStateFilename)
   611  	if err := os.MkdirAll(filepath.Dir(remoteStatePath), 0755); err != nil {
   612  		t.Fatalf("err: %s", err)
   613  	}
   614  
   615  	// Set some default reader/writers for the inputs
   616  	defaultInputReader = new(bytes.Buffer)
   617  	defaultInputWriter = new(bytes.Buffer)
   618  
   619  	// Create a remote state
   620  	state := testState()
   621  	conf, srv := testRemoteState(t, state, 200)
   622  	defer srv.Close()
   623  	state.Remote = conf
   624  
   625  	planPath := testPlanFile(t, &terraform.Plan{
   626  		Module: testModule(t, "apply"),
   627  		State:  state,
   628  	})
   629  
   630  	p := testProvider()
   631  	ui := new(cli.MockUi)
   632  	c := &ApplyCommand{
   633  		Meta: Meta{
   634  			testingOverrides: metaOverridesForProvider(p),
   635  			Ui:               ui,
   636  		},
   637  	}
   638  
   639  	args := []string{
   640  		planPath,
   641  	}
   642  	if code := c.Run(args); code != 0 {
   643  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   644  	}
   645  
   646  	if p.InputCalled {
   647  		t.Fatalf("input should not be called for plans")
   648  	}
   649  
   650  	// State file should be not be installed
   651  	if _, err := os.Stat(filepath.Join(tmp, DefaultStateFilename)); err == nil {
   652  		data, _ := ioutil.ReadFile(DefaultStateFilename)
   653  		t.Fatalf("State path should not exist: %s", string(data))
   654  	}
   655  
   656  	// Check that there is no remote state config
   657  	if _, err := os.Stat(remoteStatePath); err == nil {
   658  		t.Fatalf("has remote state config")
   659  	}
   660  }
   661  
   662  func TestApply_planWithVarFile(t *testing.T) {
   663  	varFileDir := testTempDir(t)
   664  	varFilePath := filepath.Join(varFileDir, "terraform.tfvars")
   665  	if err := ioutil.WriteFile(varFilePath, []byte(applyVarFile), 0644); err != nil {
   666  		t.Fatalf("err: %s", err)
   667  	}
   668  
   669  	planPath := testPlanFile(t, &terraform.Plan{
   670  		Module: testModule(t, "apply"),
   671  	})
   672  	statePath := testTempFile(t)
   673  
   674  	cwd, err := os.Getwd()
   675  	if err != nil {
   676  		t.Fatalf("err: %s", err)
   677  	}
   678  	if err := os.Chdir(varFileDir); err != nil {
   679  		t.Fatalf("err: %s", err)
   680  	}
   681  	defer os.Chdir(cwd)
   682  
   683  	p := testProvider()
   684  	ui := new(cli.MockUi)
   685  	c := &ApplyCommand{
   686  		Meta: Meta{
   687  			testingOverrides: metaOverridesForProvider(p),
   688  			Ui:               ui,
   689  		},
   690  	}
   691  
   692  	args := []string{
   693  		"-state-out", statePath,
   694  		planPath,
   695  	}
   696  	if code := c.Run(args); code != 0 {
   697  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   698  	}
   699  
   700  	if _, err := os.Stat(statePath); err != nil {
   701  		t.Fatalf("err: %s", err)
   702  	}
   703  
   704  	state := testStateRead(t, statePath)
   705  	if state == nil {
   706  		t.Fatal("state should not be nil")
   707  	}
   708  }
   709  
   710  func TestApply_planVars(t *testing.T) {
   711  	planPath := testPlanFile(t, &terraform.Plan{
   712  		Module: testModule(t, "apply"),
   713  	})
   714  	statePath := testTempFile(t)
   715  
   716  	p := testProvider()
   717  	ui := new(cli.MockUi)
   718  	c := &ApplyCommand{
   719  		Meta: Meta{
   720  			testingOverrides: metaOverridesForProvider(p),
   721  			Ui:               ui,
   722  		},
   723  	}
   724  
   725  	args := []string{
   726  		"-state", statePath,
   727  		"-var", "foo=bar",
   728  		planPath,
   729  	}
   730  	if code := c.Run(args); code == 0 {
   731  		t.Fatal("should've failed")
   732  	}
   733  }
   734  
   735  // we should be able to apply a plan file with no other file dependencies
   736  func TestApply_planNoModuleFiles(t *testing.T) {
   737  	// temporary data directory which we can remove between commands
   738  	td, err := ioutil.TempDir("", "tf")
   739  	if err != nil {
   740  		t.Fatal(err)
   741  	}
   742  	defer os.RemoveAll(td)
   743  
   744  	defer testChdir(t, td)()
   745  
   746  	p := testProvider()
   747  	planFile := testPlanFile(t, &terraform.Plan{
   748  		Module: testModule(t, "apply-plan-no-module"),
   749  	})
   750  
   751  	apply := &ApplyCommand{
   752  		Meta: Meta{
   753  			testingOverrides: metaOverridesForProvider(p),
   754  			Ui:               new(cli.MockUi),
   755  		},
   756  	}
   757  	args := []string{
   758  		planFile,
   759  	}
   760  	apply.Run(args)
   761  	if p.ValidateCalled {
   762  		t.Fatal("Validate should not be called with a plan")
   763  	}
   764  }
   765  
   766  func TestApply_refresh(t *testing.T) {
   767  	originalState := &terraform.State{
   768  		Modules: []*terraform.ModuleState{
   769  			&terraform.ModuleState{
   770  				Path: []string{"root"},
   771  				Resources: map[string]*terraform.ResourceState{
   772  					"test_instance.foo": &terraform.ResourceState{
   773  						Type: "test_instance",
   774  						Primary: &terraform.InstanceState{
   775  							ID: "bar",
   776  						},
   777  					},
   778  				},
   779  			},
   780  		},
   781  	}
   782  
   783  	statePath := testStateFile(t, originalState)
   784  
   785  	p := testProvider()
   786  	ui := new(cli.MockUi)
   787  	c := &ApplyCommand{
   788  		Meta: Meta{
   789  			testingOverrides: metaOverridesForProvider(p),
   790  			Ui:               ui,
   791  		},
   792  	}
   793  
   794  	args := []string{
   795  		"-state", statePath,
   796  		"-auto-approve",
   797  		testFixturePath("apply"),
   798  	}
   799  	if code := c.Run(args); code != 0 {
   800  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   801  	}
   802  
   803  	if !p.RefreshCalled {
   804  		t.Fatal("should call refresh")
   805  	}
   806  
   807  	if _, err := os.Stat(statePath); err != nil {
   808  		t.Fatalf("err: %s", err)
   809  	}
   810  
   811  	state := testStateRead(t, statePath)
   812  	if state == nil {
   813  		t.Fatal("state should not be nil")
   814  	}
   815  
   816  	// Should have a backup file
   817  	backupState := testStateRead(t, statePath+DefaultBackupExtension)
   818  
   819  	actualStr := strings.TrimSpace(backupState.String())
   820  	expectedStr := strings.TrimSpace(originalState.String())
   821  	if actualStr != expectedStr {
   822  		t.Fatalf("bad:\n\n%s\n\n%s", actualStr, expectedStr)
   823  	}
   824  }
   825  
   826  func TestApply_shutdown(t *testing.T) {
   827  	cancelled := make(chan struct{})
   828  	shutdownCh := make(chan struct{})
   829  
   830  	statePath := testTempFile(t)
   831  	p := testProvider()
   832  
   833  	ui := new(cli.MockUi)
   834  	c := &ApplyCommand{
   835  		Meta: Meta{
   836  			testingOverrides: metaOverridesForProvider(p),
   837  			Ui:               ui,
   838  			ShutdownCh:       shutdownCh,
   839  		},
   840  	}
   841  
   842  	p.StopFn = func() error {
   843  		close(cancelled)
   844  		return nil
   845  	}
   846  
   847  	p.DiffFn = func(
   848  		*terraform.InstanceInfo,
   849  		*terraform.InstanceState,
   850  		*terraform.ResourceConfig) (*terraform.InstanceDiff, error) {
   851  		return &terraform.InstanceDiff{
   852  			Attributes: map[string]*terraform.ResourceAttrDiff{
   853  				"ami": &terraform.ResourceAttrDiff{
   854  					New: "bar",
   855  				},
   856  			},
   857  		}, nil
   858  	}
   859  
   860  	var once sync.Once
   861  	p.ApplyFn = func(
   862  		*terraform.InstanceInfo,
   863  		*terraform.InstanceState,
   864  		*terraform.InstanceDiff) (*terraform.InstanceState, error) {
   865  
   866  		// only cancel once
   867  		once.Do(func() {
   868  			shutdownCh <- struct{}{}
   869  		})
   870  
   871  		// Because of the internal lock in the MockProvider, we can't
   872  		// coordiante directly with the calling of Stop, and making the
   873  		// MockProvider concurrent is disruptive to a lot of existing tests.
   874  		// Wait here a moment to help make sure the main goroutine gets to the
   875  		// Stop call before we exit, or the plan may finish before it can be
   876  		// canceled.
   877  		time.Sleep(200 * time.Millisecond)
   878  
   879  		return &terraform.InstanceState{
   880  			ID: "foo",
   881  			Attributes: map[string]string{
   882  				"ami": "2",
   883  			},
   884  		}, nil
   885  	}
   886  
   887  	args := []string{
   888  		"-state", statePath,
   889  		"-auto-approve",
   890  		testFixturePath("apply-shutdown"),
   891  	}
   892  	if code := c.Run(args); code != 0 {
   893  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   894  	}
   895  
   896  	if _, err := os.Stat(statePath); err != nil {
   897  		t.Fatalf("err: %s", err)
   898  	}
   899  
   900  	select {
   901  	case <-cancelled:
   902  	default:
   903  		t.Fatal("command not cancelled")
   904  	}
   905  
   906  	state := testStateRead(t, statePath)
   907  	if state == nil {
   908  		t.Fatal("state should not be nil")
   909  	}
   910  }
   911  
   912  func TestApply_state(t *testing.T) {
   913  	originalState := &terraform.State{
   914  		Modules: []*terraform.ModuleState{
   915  			&terraform.ModuleState{
   916  				Path: []string{"root"},
   917  				Resources: map[string]*terraform.ResourceState{
   918  					"test_instance.foo": &terraform.ResourceState{
   919  						Type: "test_instance",
   920  						Primary: &terraform.InstanceState{
   921  							ID: "bar",
   922  						},
   923  					},
   924  				},
   925  			},
   926  		},
   927  	}
   928  
   929  	statePath := testStateFile(t, originalState)
   930  
   931  	p := testProvider()
   932  	p.DiffReturn = &terraform.InstanceDiff{
   933  		Attributes: map[string]*terraform.ResourceAttrDiff{
   934  			"ami": &terraform.ResourceAttrDiff{
   935  				New: "bar",
   936  			},
   937  		},
   938  	}
   939  
   940  	ui := new(cli.MockUi)
   941  	c := &ApplyCommand{
   942  		Meta: Meta{
   943  			testingOverrides: metaOverridesForProvider(p),
   944  			Ui:               ui,
   945  		},
   946  	}
   947  
   948  	// Run the apply command pointing to our existing state
   949  	args := []string{
   950  		"-state", statePath,
   951  		"-auto-approve",
   952  		testFixturePath("apply"),
   953  	}
   954  	if code := c.Run(args); code != 0 {
   955  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   956  	}
   957  
   958  	// Verify that the provider was called with the existing state
   959  	actual := strings.TrimSpace(p.DiffState.String())
   960  	expected := strings.TrimSpace(testApplyStateDiffStr)
   961  	if actual != expected {
   962  		t.Fatalf("bad:\n\n%s", actual)
   963  	}
   964  
   965  	actual = strings.TrimSpace(p.ApplyState.String())
   966  	expected = strings.TrimSpace(testApplyStateStr)
   967  	if actual != expected {
   968  		t.Fatalf("bad:\n\n%s", actual)
   969  	}
   970  
   971  	// Verify a new state exists
   972  	if _, err := os.Stat(statePath); err != nil {
   973  		t.Fatalf("err: %s", err)
   974  	}
   975  
   976  	state := testStateRead(t, statePath)
   977  	if state == nil {
   978  		t.Fatal("state should not be nil")
   979  	}
   980  
   981  	backupState := testStateRead(t, statePath+DefaultBackupExtension)
   982  
   983  	// nil out the ConnInfo since that should not be restored
   984  	originalState.RootModule().Resources["test_instance.foo"].Primary.Ephemeral.ConnInfo = nil
   985  
   986  	actualStr := strings.TrimSpace(backupState.String())
   987  	expectedStr := strings.TrimSpace(originalState.String())
   988  	if actualStr != expectedStr {
   989  		t.Fatalf("bad:\n\n%s\n\n%s", actualStr, expectedStr)
   990  	}
   991  }
   992  
   993  func TestApply_stateNoExist(t *testing.T) {
   994  	p := testProvider()
   995  	ui := new(cli.MockUi)
   996  	c := &ApplyCommand{
   997  		Meta: Meta{
   998  			testingOverrides: metaOverridesForProvider(p),
   999  			Ui:               ui,
  1000  		},
  1001  	}
  1002  
  1003  	args := []string{
  1004  		"idontexist.tfstate",
  1005  		testFixturePath("apply"),
  1006  	}
  1007  	if code := c.Run(args); code != 1 {
  1008  		t.Fatalf("bad: \n%s", ui.OutputWriter.String())
  1009  	}
  1010  }
  1011  
  1012  func TestApply_sensitiveOutput(t *testing.T) {
  1013  	p := testProvider()
  1014  	ui := new(cli.MockUi)
  1015  	c := &ApplyCommand{
  1016  		Meta: Meta{
  1017  			testingOverrides: metaOverridesForProvider(p),
  1018  			Ui:               ui,
  1019  		},
  1020  	}
  1021  
  1022  	statePath := testTempFile(t)
  1023  
  1024  	args := []string{
  1025  		"-state", statePath,
  1026  		"-auto-approve",
  1027  		testFixturePath("apply-sensitive-output"),
  1028  	}
  1029  
  1030  	if code := c.Run(args); code != 0 {
  1031  		t.Fatalf("bad: \n%s", ui.OutputWriter.String())
  1032  	}
  1033  
  1034  	output := ui.OutputWriter.String()
  1035  	if !strings.Contains(output, "notsensitive = Hello world") {
  1036  		t.Fatalf("bad: output should contain 'notsensitive' output\n%s", output)
  1037  	}
  1038  	if !strings.Contains(output, "sensitive = <sensitive>") {
  1039  		t.Fatalf("bad: output should contain 'sensitive' output\n%s", output)
  1040  	}
  1041  }
  1042  
  1043  func TestApply_stateFuture(t *testing.T) {
  1044  	originalState := testState()
  1045  	originalState.TFVersion = "99.99.99"
  1046  	statePath := testStateFile(t, originalState)
  1047  
  1048  	p := testProvider()
  1049  	ui := new(cli.MockUi)
  1050  	c := &ApplyCommand{
  1051  		Meta: Meta{
  1052  			testingOverrides: metaOverridesForProvider(p),
  1053  			Ui:               ui,
  1054  		},
  1055  	}
  1056  
  1057  	args := []string{
  1058  		"-state", statePath,
  1059  		"-auto-approve",
  1060  		testFixturePath("apply"),
  1061  	}
  1062  	if code := c.Run(args); code == 0 {
  1063  		t.Fatal("should fail")
  1064  	}
  1065  
  1066  	newState := testStateRead(t, statePath)
  1067  	if !newState.Equal(originalState) {
  1068  		t.Fatalf("bad: %#v", newState)
  1069  	}
  1070  	if newState.TFVersion != originalState.TFVersion {
  1071  		t.Fatalf("bad: %#v", newState)
  1072  	}
  1073  }
  1074  
  1075  func TestApply_statePast(t *testing.T) {
  1076  	originalState := testState()
  1077  	originalState.TFVersion = "0.1.0"
  1078  	statePath := testStateFile(t, originalState)
  1079  
  1080  	p := testProvider()
  1081  	ui := new(cli.MockUi)
  1082  	c := &ApplyCommand{
  1083  		Meta: Meta{
  1084  			testingOverrides: metaOverridesForProvider(p),
  1085  			Ui:               ui,
  1086  		},
  1087  	}
  1088  
  1089  	args := []string{
  1090  		"-state", statePath,
  1091  		"-auto-approve",
  1092  		testFixturePath("apply"),
  1093  	}
  1094  	if code := c.Run(args); code != 0 {
  1095  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
  1096  	}
  1097  }
  1098  
  1099  func TestApply_vars(t *testing.T) {
  1100  	statePath := testTempFile(t)
  1101  
  1102  	p := testProvider()
  1103  	ui := new(cli.MockUi)
  1104  	c := &ApplyCommand{
  1105  		Meta: Meta{
  1106  			testingOverrides: metaOverridesForProvider(p),
  1107  			Ui:               ui,
  1108  		},
  1109  	}
  1110  
  1111  	actual := ""
  1112  	p.DiffFn = func(
  1113  		info *terraform.InstanceInfo,
  1114  		s *terraform.InstanceState,
  1115  		c *terraform.ResourceConfig) (*terraform.InstanceDiff, error) {
  1116  		if v, ok := c.Config["value"]; ok {
  1117  			actual = v.(string)
  1118  		}
  1119  
  1120  		return &terraform.InstanceDiff{}, nil
  1121  	}
  1122  
  1123  	args := []string{
  1124  		"-auto-approve",
  1125  		"-var", "foo=bar",
  1126  		"-state", statePath,
  1127  		testFixturePath("apply-vars"),
  1128  	}
  1129  	if code := c.Run(args); code != 0 {
  1130  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
  1131  	}
  1132  
  1133  	if actual != "bar" {
  1134  		t.Fatal("didn't work")
  1135  	}
  1136  }
  1137  
  1138  func TestApply_varFile(t *testing.T) {
  1139  	varFilePath := testTempFile(t)
  1140  	if err := ioutil.WriteFile(varFilePath, []byte(applyVarFile), 0644); err != nil {
  1141  		t.Fatalf("err: %s", err)
  1142  	}
  1143  
  1144  	statePath := testTempFile(t)
  1145  
  1146  	p := testProvider()
  1147  	ui := new(cli.MockUi)
  1148  	c := &ApplyCommand{
  1149  		Meta: Meta{
  1150  			testingOverrides: metaOverridesForProvider(p),
  1151  			Ui:               ui,
  1152  		},
  1153  	}
  1154  
  1155  	actual := ""
  1156  	p.DiffFn = func(
  1157  		info *terraform.InstanceInfo,
  1158  		s *terraform.InstanceState,
  1159  		c *terraform.ResourceConfig) (*terraform.InstanceDiff, error) {
  1160  		if v, ok := c.Config["value"]; ok {
  1161  			actual = v.(string)
  1162  		}
  1163  
  1164  		return &terraform.InstanceDiff{}, nil
  1165  	}
  1166  
  1167  	args := []string{
  1168  		"-auto-approve",
  1169  		"-var-file", varFilePath,
  1170  		"-state", statePath,
  1171  		testFixturePath("apply-vars"),
  1172  	}
  1173  	if code := c.Run(args); code != 0 {
  1174  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
  1175  	}
  1176  
  1177  	if actual != "bar" {
  1178  		t.Fatal("didn't work")
  1179  	}
  1180  }
  1181  
  1182  func TestApply_varFileDefault(t *testing.T) {
  1183  	varFileDir := testTempDir(t)
  1184  	varFilePath := filepath.Join(varFileDir, "terraform.tfvars")
  1185  	if err := ioutil.WriteFile(varFilePath, []byte(applyVarFile), 0644); err != nil {
  1186  		t.Fatalf("err: %s", err)
  1187  	}
  1188  
  1189  	statePath := testTempFile(t)
  1190  
  1191  	cwd, err := os.Getwd()
  1192  	if err != nil {
  1193  		t.Fatalf("err: %s", err)
  1194  	}
  1195  	if err := os.Chdir(varFileDir); err != nil {
  1196  		t.Fatalf("err: %s", err)
  1197  	}
  1198  	defer os.Chdir(cwd)
  1199  
  1200  	p := testProvider()
  1201  	ui := new(cli.MockUi)
  1202  	c := &ApplyCommand{
  1203  		Meta: Meta{
  1204  			testingOverrides: metaOverridesForProvider(p),
  1205  			Ui:               ui,
  1206  		},
  1207  	}
  1208  
  1209  	actual := ""
  1210  	p.DiffFn = func(
  1211  		info *terraform.InstanceInfo,
  1212  		s *terraform.InstanceState,
  1213  		c *terraform.ResourceConfig) (*terraform.InstanceDiff, error) {
  1214  		if v, ok := c.Config["value"]; ok {
  1215  			actual = v.(string)
  1216  		}
  1217  
  1218  		return &terraform.InstanceDiff{}, nil
  1219  	}
  1220  
  1221  	args := []string{
  1222  		"-auto-approve",
  1223  		"-state", statePath,
  1224  		testFixturePath("apply-vars"),
  1225  	}
  1226  	if code := c.Run(args); code != 0 {
  1227  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
  1228  	}
  1229  
  1230  	if actual != "bar" {
  1231  		t.Fatal("didn't work")
  1232  	}
  1233  }
  1234  
  1235  func TestApply_varFileDefaultJSON(t *testing.T) {
  1236  	varFileDir := testTempDir(t)
  1237  	varFilePath := filepath.Join(varFileDir, "terraform.tfvars.json")
  1238  	if err := ioutil.WriteFile(varFilePath, []byte(applyVarFileJSON), 0644); err != nil {
  1239  		t.Fatalf("err: %s", err)
  1240  	}
  1241  
  1242  	statePath := testTempFile(t)
  1243  
  1244  	cwd, err := os.Getwd()
  1245  	if err != nil {
  1246  		t.Fatalf("err: %s", err)
  1247  	}
  1248  	if err := os.Chdir(varFileDir); err != nil {
  1249  		t.Fatalf("err: %s", err)
  1250  	}
  1251  	defer os.Chdir(cwd)
  1252  
  1253  	p := testProvider()
  1254  	ui := new(cli.MockUi)
  1255  	c := &ApplyCommand{
  1256  		Meta: Meta{
  1257  			testingOverrides: metaOverridesForProvider(p),
  1258  			Ui:               ui,
  1259  		},
  1260  	}
  1261  
  1262  	actual := ""
  1263  	p.DiffFn = func(
  1264  		info *terraform.InstanceInfo,
  1265  		s *terraform.InstanceState,
  1266  		c *terraform.ResourceConfig) (*terraform.InstanceDiff, error) {
  1267  		if v, ok := c.Config["value"]; ok {
  1268  			actual = v.(string)
  1269  		}
  1270  
  1271  		return &terraform.InstanceDiff{}, nil
  1272  	}
  1273  
  1274  	args := []string{
  1275  		"-auto-approve",
  1276  		"-state", statePath,
  1277  		testFixturePath("apply-vars"),
  1278  	}
  1279  	if code := c.Run(args); code != 0 {
  1280  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
  1281  	}
  1282  
  1283  	if actual != "bar" {
  1284  		t.Fatal("didn't work")
  1285  	}
  1286  }
  1287  
  1288  func TestApply_backup(t *testing.T) {
  1289  	originalState := &terraform.State{
  1290  		Modules: []*terraform.ModuleState{
  1291  			&terraform.ModuleState{
  1292  				Path: []string{"root"},
  1293  				Resources: map[string]*terraform.ResourceState{
  1294  					"test_instance.foo": &terraform.ResourceState{
  1295  						Type: "test_instance",
  1296  						Primary: &terraform.InstanceState{
  1297  							ID: "bar",
  1298  						},
  1299  					},
  1300  				},
  1301  			},
  1302  		},
  1303  	}
  1304  	originalState.Init()
  1305  
  1306  	statePath := testStateFile(t, originalState)
  1307  	backupPath := testTempFile(t)
  1308  
  1309  	p := testProvider()
  1310  	p.DiffReturn = &terraform.InstanceDiff{
  1311  		Attributes: map[string]*terraform.ResourceAttrDiff{
  1312  			"ami": &terraform.ResourceAttrDiff{
  1313  				New: "bar",
  1314  			},
  1315  		},
  1316  	}
  1317  
  1318  	ui := new(cli.MockUi)
  1319  	c := &ApplyCommand{
  1320  		Meta: Meta{
  1321  			testingOverrides: metaOverridesForProvider(p),
  1322  			Ui:               ui,
  1323  		},
  1324  	}
  1325  
  1326  	// Run the apply command pointing to our existing state
  1327  	args := []string{
  1328  		"-auto-approve",
  1329  		"-state", statePath,
  1330  		"-backup", backupPath,
  1331  		testFixturePath("apply"),
  1332  	}
  1333  	if code := c.Run(args); code != 0 {
  1334  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
  1335  	}
  1336  
  1337  	// Verify a new state exists
  1338  	if _, err := os.Stat(statePath); err != nil {
  1339  		t.Fatalf("err: %s", err)
  1340  	}
  1341  
  1342  	state := testStateRead(t, statePath)
  1343  	if state == nil {
  1344  		t.Fatal("state should not be nil")
  1345  	}
  1346  
  1347  	backupState := testStateRead(t, backupPath)
  1348  
  1349  	actual := backupState.RootModule().Resources["test_instance.foo"]
  1350  	expected := originalState.RootModule().Resources["test_instance.foo"]
  1351  	if !reflect.DeepEqual(actual, expected) {
  1352  		t.Fatalf("bad: %#v %#v", actual, expected)
  1353  	}
  1354  }
  1355  
  1356  func TestApply_disableBackup(t *testing.T) {
  1357  	originalState := testState()
  1358  	statePath := testStateFile(t, originalState)
  1359  
  1360  	p := testProvider()
  1361  	p.DiffReturn = &terraform.InstanceDiff{
  1362  		Attributes: map[string]*terraform.ResourceAttrDiff{
  1363  			"ami": &terraform.ResourceAttrDiff{
  1364  				New: "bar",
  1365  			},
  1366  		},
  1367  	}
  1368  
  1369  	ui := new(cli.MockUi)
  1370  	c := &ApplyCommand{
  1371  		Meta: Meta{
  1372  			testingOverrides: metaOverridesForProvider(p),
  1373  			Ui:               ui,
  1374  		},
  1375  	}
  1376  
  1377  	// Run the apply command pointing to our existing state
  1378  	args := []string{
  1379  		"-auto-approve",
  1380  		"-state", statePath,
  1381  		"-backup", "-",
  1382  		testFixturePath("apply"),
  1383  	}
  1384  	if code := c.Run(args); code != 0 {
  1385  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
  1386  	}
  1387  
  1388  	// Verify that the provider was called with the existing state
  1389  	actual := strings.TrimSpace(p.DiffState.String())
  1390  	expected := strings.TrimSpace(testApplyDisableBackupStr)
  1391  	if actual != expected {
  1392  		t.Fatalf("bad:\n\n%s", actual)
  1393  	}
  1394  
  1395  	actual = strings.TrimSpace(p.ApplyState.String())
  1396  	expected = strings.TrimSpace(testApplyDisableBackupStateStr)
  1397  	if actual != expected {
  1398  		t.Fatalf("bad:\n\n%s", actual)
  1399  	}
  1400  
  1401  	// Verify a new state exists
  1402  	if _, err := os.Stat(statePath); err != nil {
  1403  		t.Fatalf("err: %s", err)
  1404  	}
  1405  
  1406  	state := testStateRead(t, statePath)
  1407  	if state == nil {
  1408  		t.Fatal("state should not be nil")
  1409  	}
  1410  
  1411  	// Ensure there is no backup
  1412  	_, err := os.Stat(statePath + DefaultBackupExtension)
  1413  	if err == nil || !os.IsNotExist(err) {
  1414  		t.Fatalf("backup should not exist")
  1415  	}
  1416  
  1417  	// Ensure there is no literal "-"
  1418  	_, err = os.Stat("-")
  1419  	if err == nil || !os.IsNotExist(err) {
  1420  		t.Fatalf("backup should not exist")
  1421  	}
  1422  }
  1423  
  1424  // Test that the Terraform env is passed through
  1425  func TestApply_terraformEnv(t *testing.T) {
  1426  	statePath := testTempFile(t)
  1427  
  1428  	p := testProvider()
  1429  	ui := new(cli.MockUi)
  1430  	c := &ApplyCommand{
  1431  		Meta: Meta{
  1432  			testingOverrides: metaOverridesForProvider(p),
  1433  			Ui:               ui,
  1434  		},
  1435  	}
  1436  
  1437  	args := []string{
  1438  		"-auto-approve",
  1439  		"-state", statePath,
  1440  		testFixturePath("apply-terraform-env"),
  1441  	}
  1442  	if code := c.Run(args); code != 0 {
  1443  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
  1444  	}
  1445  
  1446  	expected := strings.TrimSpace(`
  1447  <no state>
  1448  Outputs:
  1449  
  1450  output = default
  1451  	`)
  1452  	testStateOutput(t, statePath, expected)
  1453  }
  1454  
  1455  // Test that the Terraform env is passed through
  1456  func TestApply_terraformEnvNonDefault(t *testing.T) {
  1457  	// Create a temporary working directory that is empty
  1458  	td := tempDir(t)
  1459  	os.MkdirAll(td, 0755)
  1460  	defer os.RemoveAll(td)
  1461  	defer testChdir(t, td)()
  1462  
  1463  	// Create new env
  1464  	{
  1465  		ui := new(cli.MockUi)
  1466  		newCmd := &WorkspaceNewCommand{}
  1467  		newCmd.Meta = Meta{Ui: ui}
  1468  		if code := newCmd.Run([]string{"test"}); code != 0 {
  1469  			t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter)
  1470  		}
  1471  	}
  1472  
  1473  	// Switch to it
  1474  	{
  1475  		args := []string{"test"}
  1476  		ui := new(cli.MockUi)
  1477  		selCmd := &WorkspaceSelectCommand{}
  1478  		selCmd.Meta = Meta{Ui: ui}
  1479  		if code := selCmd.Run(args); code != 0 {
  1480  			t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter)
  1481  		}
  1482  	}
  1483  
  1484  	p := testProvider()
  1485  	ui := new(cli.MockUi)
  1486  	c := &ApplyCommand{
  1487  		Meta: Meta{
  1488  			testingOverrides: metaOverridesForProvider(p),
  1489  			Ui:               ui,
  1490  		},
  1491  	}
  1492  
  1493  	args := []string{
  1494  		"-auto-approve",
  1495  		testFixturePath("apply-terraform-env"),
  1496  	}
  1497  	if code := c.Run(args); code != 0 {
  1498  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
  1499  	}
  1500  
  1501  	statePath := filepath.Join("terraform.tfstate.d", "test", "terraform.tfstate")
  1502  	expected := strings.TrimSpace(`
  1503  <no state>
  1504  Outputs:
  1505  
  1506  output = test
  1507  	`)
  1508  	testStateOutput(t, statePath, expected)
  1509  }
  1510  
  1511  func testHttpServer(t *testing.T) net.Listener {
  1512  	ln, err := net.Listen("tcp", "127.0.0.1:0")
  1513  	if err != nil {
  1514  		t.Fatalf("err: %s", err)
  1515  	}
  1516  
  1517  	mux := http.NewServeMux()
  1518  	mux.HandleFunc("/header", testHttpHandlerHeader)
  1519  
  1520  	var server http.Server
  1521  	server.Handler = mux
  1522  	go server.Serve(ln)
  1523  
  1524  	return ln
  1525  }
  1526  
  1527  func testHttpHandlerHeader(w http.ResponseWriter, r *http.Request) {
  1528  	var url url.URL
  1529  	url.Scheme = "file"
  1530  	url.Path = filepath.ToSlash(testFixturePath("init"))
  1531  
  1532  	w.Header().Add("X-Terraform-Get", url.String())
  1533  	w.WriteHeader(200)
  1534  }
  1535  
  1536  const applyVarFile = `
  1537  foo = "bar"
  1538  `
  1539  
  1540  const applyVarFileJSON = `
  1541  { "foo": "bar" }
  1542  `
  1543  
  1544  const testApplyDisableBackupStr = `
  1545  ID = bar
  1546  Tainted = false
  1547  `
  1548  
  1549  const testApplyDisableBackupStateStr = `
  1550  ID = bar
  1551  Tainted = false
  1552  `
  1553  
  1554  const testApplyStateStr = `
  1555  ID = bar
  1556  Tainted = false
  1557  `
  1558  
  1559  const testApplyStateDiffStr = `
  1560  ID = bar
  1561  Tainted = false
  1562  `