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