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