github.com/jsoriano/terraform@v0.6.7-0.20151026070445-8b70867fdd95/terraform/context_apply_test.go (about)

     1  package terraform
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"reflect"
     7  	"sort"
     8  	"strings"
     9  	"sync"
    10  	"sync/atomic"
    11  	"testing"
    12  	"time"
    13  
    14  	"github.com/hashicorp/terraform/config/module"
    15  )
    16  
    17  func TestContext2Apply(t *testing.T) {
    18  	m := testModule(t, "apply-good")
    19  	p := testProvider("aws")
    20  	p.ApplyFn = testApplyFn
    21  	p.DiffFn = testDiffFn
    22  	ctx := testContext2(t, &ContextOpts{
    23  		Module: m,
    24  		Providers: map[string]ResourceProviderFactory{
    25  			"aws": testProviderFuncFixed(p),
    26  		},
    27  	})
    28  
    29  	if _, err := ctx.Plan(); err != nil {
    30  		t.Fatalf("err: %s", err)
    31  	}
    32  
    33  	state, err := ctx.Apply()
    34  	if err != nil {
    35  		t.Fatalf("err: %s", err)
    36  	}
    37  
    38  	mod := state.RootModule()
    39  	if len(mod.Resources) < 2 {
    40  		t.Fatalf("bad: %#v", mod.Resources)
    41  	}
    42  
    43  	actual := strings.TrimSpace(state.String())
    44  	expected := strings.TrimSpace(testTerraformApplyStr)
    45  	if actual != expected {
    46  		t.Fatalf("bad: \n%s", actual)
    47  	}
    48  }
    49  
    50  func TestContext2Apply_providerAlias(t *testing.T) {
    51  	m := testModule(t, "apply-provider-alias")
    52  	p := testProvider("aws")
    53  	p.ApplyFn = testApplyFn
    54  	p.DiffFn = testDiffFn
    55  	ctx := testContext2(t, &ContextOpts{
    56  		Module: m,
    57  		Providers: map[string]ResourceProviderFactory{
    58  			"aws": testProviderFuncFixed(p),
    59  		},
    60  	})
    61  
    62  	if _, err := ctx.Plan(); err != nil {
    63  		t.Fatalf("err: %s", err)
    64  	}
    65  
    66  	state, err := ctx.Apply()
    67  	if err != nil {
    68  		t.Fatalf("err: %s", err)
    69  	}
    70  
    71  	mod := state.RootModule()
    72  	if len(mod.Resources) < 2 {
    73  		t.Fatalf("bad: %#v", mod.Resources)
    74  	}
    75  
    76  	actual := strings.TrimSpace(state.String())
    77  	expected := strings.TrimSpace(testTerraformApplyProviderAliasStr)
    78  	if actual != expected {
    79  		t.Fatalf("bad: \n%s", actual)
    80  	}
    81  }
    82  
    83  // GH-2870
    84  func TestContext2Apply_providerWarning(t *testing.T) {
    85  	m := testModule(t, "apply-provider-warning")
    86  	p := testProvider("aws")
    87  	p.ApplyFn = testApplyFn
    88  	p.DiffFn = testDiffFn
    89  	p.ValidateFn = func(c *ResourceConfig) (ws []string, es []error) {
    90  		ws = append(ws, "Just a warning")
    91  		return
    92  	}
    93  	ctx := testContext2(t, &ContextOpts{
    94  		Module: m,
    95  		Providers: map[string]ResourceProviderFactory{
    96  			"aws": testProviderFuncFixed(p),
    97  		},
    98  	})
    99  
   100  	if _, err := ctx.Plan(); err != nil {
   101  		t.Fatalf("err: %s", err)
   102  	}
   103  
   104  	state, err := ctx.Apply()
   105  	if err != nil {
   106  		t.Fatalf("err: %s", err)
   107  	}
   108  
   109  	actual := strings.TrimSpace(state.String())
   110  	expected := strings.TrimSpace(`
   111  aws_instance.foo:
   112    ID = foo
   113  	`)
   114  	if actual != expected {
   115  		t.Fatalf("got: \n%s\n\nexpected:\n%s", actual, expected)
   116  	}
   117  
   118  	if !p.ConfigureCalled {
   119  		t.Fatalf("provider Configure() was never called!")
   120  	}
   121  }
   122  
   123  func TestContext2Apply_emptyModule(t *testing.T) {
   124  	m := testModule(t, "apply-empty-module")
   125  	p := testProvider("aws")
   126  	p.ApplyFn = testApplyFn
   127  	p.DiffFn = testDiffFn
   128  	ctx := testContext2(t, &ContextOpts{
   129  		Module: m,
   130  		Providers: map[string]ResourceProviderFactory{
   131  			"aws": testProviderFuncFixed(p),
   132  		},
   133  	})
   134  
   135  	if _, err := ctx.Plan(); err != nil {
   136  		t.Fatalf("err: %s", err)
   137  	}
   138  
   139  	state, err := ctx.Apply()
   140  	if err != nil {
   141  		t.Fatalf("err: %s", err)
   142  	}
   143  
   144  	actual := strings.TrimSpace(state.String())
   145  	actual = strings.Replace(actual, "  ", "", -1)
   146  	expected := strings.TrimSpace(testTerraformApplyEmptyModuleStr)
   147  	if actual != expected {
   148  		t.Fatalf("bad: \n%s\nexpect:\n%s", actual, expected)
   149  	}
   150  }
   151  
   152  func TestContext2Apply_createBeforeDestroy(t *testing.T) {
   153  	m := testModule(t, "apply-good-create-before")
   154  	p := testProvider("aws")
   155  	p.ApplyFn = testApplyFn
   156  	p.DiffFn = testDiffFn
   157  	state := &State{
   158  		Modules: []*ModuleState{
   159  			&ModuleState{
   160  				Path: rootModulePath,
   161  				Resources: map[string]*ResourceState{
   162  					"aws_instance.bar": &ResourceState{
   163  						Type: "aws_instance",
   164  						Primary: &InstanceState{
   165  							ID: "bar",
   166  							Attributes: map[string]string{
   167  								"require_new": "abc",
   168  							},
   169  						},
   170  					},
   171  				},
   172  			},
   173  		},
   174  	}
   175  	ctx := testContext2(t, &ContextOpts{
   176  		Module: m,
   177  		Providers: map[string]ResourceProviderFactory{
   178  			"aws": testProviderFuncFixed(p),
   179  		},
   180  		State: state,
   181  	})
   182  
   183  	if p, err := ctx.Plan(); err != nil {
   184  		t.Fatalf("err: %s", err)
   185  	} else {
   186  		t.Logf(p.String())
   187  	}
   188  
   189  	state, err := ctx.Apply()
   190  	if err != nil {
   191  		t.Fatalf("err: %s", err)
   192  	}
   193  
   194  	mod := state.RootModule()
   195  	if len(mod.Resources) != 1 {
   196  		t.Fatalf("bad: %s", state)
   197  	}
   198  
   199  	actual := strings.TrimSpace(state.String())
   200  	expected := strings.TrimSpace(testTerraformApplyCreateBeforeStr)
   201  	if actual != expected {
   202  		t.Fatalf("bad: \n%s", actual)
   203  	}
   204  }
   205  
   206  func TestContext2Apply_createBeforeDestroyUpdate(t *testing.T) {
   207  	m := testModule(t, "apply-good-create-before-update")
   208  	p := testProvider("aws")
   209  	p.ApplyFn = testApplyFn
   210  	p.DiffFn = testDiffFn
   211  	state := &State{
   212  		Modules: []*ModuleState{
   213  			&ModuleState{
   214  				Path: rootModulePath,
   215  				Resources: map[string]*ResourceState{
   216  					"aws_instance.bar": &ResourceState{
   217  						Type: "aws_instance",
   218  						Primary: &InstanceState{
   219  							ID: "bar",
   220  							Attributes: map[string]string{
   221  								"foo": "bar",
   222  							},
   223  						},
   224  					},
   225  				},
   226  			},
   227  		},
   228  	}
   229  	ctx := testContext2(t, &ContextOpts{
   230  		Module: m,
   231  		Providers: map[string]ResourceProviderFactory{
   232  			"aws": testProviderFuncFixed(p),
   233  		},
   234  		State: state,
   235  	})
   236  
   237  	if p, err := ctx.Plan(); err != nil {
   238  		t.Fatalf("err: %s", err)
   239  	} else {
   240  		t.Logf(p.String())
   241  	}
   242  
   243  	state, err := ctx.Apply()
   244  	if err != nil {
   245  		t.Fatalf("err: %s", err)
   246  	}
   247  
   248  	mod := state.RootModule()
   249  	if len(mod.Resources) != 1 {
   250  		t.Fatalf("bad: %s", state)
   251  	}
   252  
   253  	actual := strings.TrimSpace(state.String())
   254  	expected := strings.TrimSpace(testTerraformApplyCreateBeforeUpdateStr)
   255  	if actual != expected {
   256  		t.Fatalf("bad: \n%s", actual)
   257  	}
   258  }
   259  
   260  func TestContext2Apply_destroyComputed(t *testing.T) {
   261  	m := testModule(t, "apply-destroy-computed")
   262  	p := testProvider("aws")
   263  	p.ApplyFn = testApplyFn
   264  	p.DiffFn = testDiffFn
   265  	state := &State{
   266  		Modules: []*ModuleState{
   267  			&ModuleState{
   268  				Path: rootModulePath,
   269  				Resources: map[string]*ResourceState{
   270  					"aws_instance.foo": &ResourceState{
   271  						Type: "aws_instance",
   272  						Primary: &InstanceState{
   273  							ID: "foo",
   274  							Attributes: map[string]string{
   275  								"output": "value",
   276  							},
   277  						},
   278  					},
   279  				},
   280  			},
   281  		},
   282  	}
   283  	ctx := testContext2(t, &ContextOpts{
   284  		Module: m,
   285  		Providers: map[string]ResourceProviderFactory{
   286  			"aws": testProviderFuncFixed(p),
   287  		},
   288  		State:   state,
   289  		Destroy: true,
   290  	})
   291  
   292  	if p, err := ctx.Plan(); err != nil {
   293  		t.Fatalf("err: %s", err)
   294  	} else {
   295  		t.Logf(p.String())
   296  	}
   297  
   298  	if _, err := ctx.Apply(); err != nil {
   299  		t.Fatalf("err: %s", err)
   300  	}
   301  }
   302  
   303  // https://github.com/hashicorp/terraform/issues/2892
   304  func TestContext2Apply_destroyCrossProviders(t *testing.T) {
   305  	m := testModule(t, "apply-destroy-cross-providers")
   306  
   307  	p_aws := testProvider("aws")
   308  	p_aws.ApplyFn = testApplyFn
   309  	p_aws.DiffFn = testDiffFn
   310  
   311  	p_tf := testProvider("terraform")
   312  	p_tf.ApplyFn = testApplyFn
   313  	p_tf.DiffFn = testDiffFn
   314  
   315  	providers := map[string]ResourceProviderFactory{
   316  		"aws":       testProviderFuncFixed(p_aws),
   317  		"terraform": testProviderFuncFixed(p_tf),
   318  	}
   319  
   320  	// Bug only appears from time to time,
   321  	// so we run this test multiple times
   322  	// to check for the race-condition
   323  	for i := 0; i <= 10; i++ {
   324  		ctx := getContextForApply_destroyCrossProviders(
   325  			t, m, providers)
   326  
   327  		if p, err := ctx.Plan(); err != nil {
   328  			t.Fatalf("err: %s", err)
   329  		} else {
   330  			t.Logf(p.String())
   331  		}
   332  
   333  		if _, err := ctx.Apply(); err != nil {
   334  			t.Fatalf("err: %s", err)
   335  		}
   336  	}
   337  }
   338  
   339  func getContextForApply_destroyCrossProviders(
   340  	t *testing.T,
   341  	m *module.Tree,
   342  	providers map[string]ResourceProviderFactory) *Context {
   343  	state := &State{
   344  		Modules: []*ModuleState{
   345  			&ModuleState{
   346  				Path: rootModulePath,
   347  				Resources: map[string]*ResourceState{
   348  					"terraform_remote_state.shared": &ResourceState{
   349  						Type: "terraform_remote_state",
   350  						Primary: &InstanceState{
   351  							ID: "remote-2652591293",
   352  							Attributes: map[string]string{
   353  								"output.env_name": "test",
   354  							},
   355  						},
   356  					},
   357  				},
   358  			},
   359  			&ModuleState{
   360  				Path: []string{"root", "example"},
   361  				Resources: map[string]*ResourceState{
   362  					"aws_vpc.bar": &ResourceState{
   363  						Type: "aws_vpc",
   364  						Primary: &InstanceState{
   365  							ID: "vpc-aaabbb12",
   366  							Attributes: map[string]string{
   367  								"value": "test",
   368  							},
   369  						},
   370  					},
   371  				},
   372  			},
   373  		},
   374  	}
   375  	ctx := testContext2(t, &ContextOpts{
   376  		Module:    m,
   377  		Providers: providers,
   378  		State:     state,
   379  		Destroy:   true,
   380  	})
   381  
   382  	return ctx
   383  }
   384  
   385  func TestContext2Apply_minimal(t *testing.T) {
   386  	m := testModule(t, "apply-minimal")
   387  	p := testProvider("aws")
   388  	p.ApplyFn = testApplyFn
   389  	p.DiffFn = testDiffFn
   390  	ctx := testContext2(t, &ContextOpts{
   391  		Module: m,
   392  		Providers: map[string]ResourceProviderFactory{
   393  			"aws": testProviderFuncFixed(p),
   394  		},
   395  	})
   396  
   397  	if _, err := ctx.Plan(); err != nil {
   398  		t.Fatalf("err: %s", err)
   399  	}
   400  
   401  	state, err := ctx.Apply()
   402  	if err != nil {
   403  		t.Fatalf("err: %s", err)
   404  	}
   405  
   406  	actual := strings.TrimSpace(state.String())
   407  	expected := strings.TrimSpace(testTerraformApplyMinimalStr)
   408  	if actual != expected {
   409  		t.Fatalf("bad: \n%s", actual)
   410  	}
   411  }
   412  
   413  func TestContext2Apply_badDiff(t *testing.T) {
   414  	m := testModule(t, "apply-good")
   415  	p := testProvider("aws")
   416  	p.ApplyFn = testApplyFn
   417  	p.DiffFn = testDiffFn
   418  	ctx := testContext2(t, &ContextOpts{
   419  		Module: m,
   420  		Providers: map[string]ResourceProviderFactory{
   421  			"aws": testProviderFuncFixed(p),
   422  		},
   423  	})
   424  
   425  	if _, err := ctx.Plan(); err != nil {
   426  		t.Fatalf("err: %s", err)
   427  	}
   428  
   429  	p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) {
   430  		return &InstanceDiff{
   431  			Attributes: map[string]*ResourceAttrDiff{
   432  				"newp": nil,
   433  			},
   434  		}, nil
   435  	}
   436  
   437  	if _, err := ctx.Apply(); err == nil {
   438  		t.Fatal("should error")
   439  	}
   440  }
   441  
   442  func TestContext2Apply_cancel(t *testing.T) {
   443  	stopped := false
   444  
   445  	m := testModule(t, "apply-cancel")
   446  	p := testProvider("aws")
   447  	ctx := testContext2(t, &ContextOpts{
   448  		Module: m,
   449  		Providers: map[string]ResourceProviderFactory{
   450  			"aws": testProviderFuncFixed(p),
   451  		},
   452  	})
   453  
   454  	p.ApplyFn = func(*InstanceInfo, *InstanceState, *InstanceDiff) (*InstanceState, error) {
   455  		if !stopped {
   456  			stopped = true
   457  			go ctx.Stop()
   458  
   459  			for {
   460  				if ctx.sh.Stopped() {
   461  					break
   462  				}
   463  			}
   464  		}
   465  
   466  		return &InstanceState{
   467  			ID: "foo",
   468  			Attributes: map[string]string{
   469  				"num": "2",
   470  			},
   471  		}, nil
   472  	}
   473  	p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) {
   474  		return &InstanceDiff{
   475  			Attributes: map[string]*ResourceAttrDiff{
   476  				"num": &ResourceAttrDiff{
   477  					New: "bar",
   478  				},
   479  			},
   480  		}, nil
   481  	}
   482  
   483  	if _, err := ctx.Plan(); err != nil {
   484  		t.Fatalf("err: %s", err)
   485  	}
   486  
   487  	// Start the Apply in a goroutine
   488  	stateCh := make(chan *State)
   489  	go func() {
   490  		state, err := ctx.Apply()
   491  		if err != nil {
   492  			panic(err)
   493  		}
   494  
   495  		stateCh <- state
   496  	}()
   497  
   498  	state := <-stateCh
   499  
   500  	mod := state.RootModule()
   501  	if len(mod.Resources) != 1 {
   502  		t.Fatalf("bad: %s", state.String())
   503  	}
   504  
   505  	actual := strings.TrimSpace(state.String())
   506  	expected := strings.TrimSpace(testTerraformApplyCancelStr)
   507  	if actual != expected {
   508  		t.Fatalf("bad: \n%s", actual)
   509  	}
   510  }
   511  
   512  func TestContext2Apply_compute(t *testing.T) {
   513  	m := testModule(t, "apply-compute")
   514  	p := testProvider("aws")
   515  	p.ApplyFn = testApplyFn
   516  	p.DiffFn = testDiffFn
   517  	ctx := testContext2(t, &ContextOpts{
   518  		Module: m,
   519  		Providers: map[string]ResourceProviderFactory{
   520  			"aws": testProviderFuncFixed(p),
   521  		},
   522  	})
   523  
   524  	if _, err := ctx.Plan(); err != nil {
   525  		t.Fatalf("err: %s", err)
   526  	}
   527  
   528  	ctx.variables = map[string]string{"value": "1"}
   529  
   530  	state, err := ctx.Apply()
   531  	if err != nil {
   532  		t.Fatalf("err: %s", err)
   533  	}
   534  
   535  	actual := strings.TrimSpace(state.String())
   536  	expected := strings.TrimSpace(testTerraformApplyComputeStr)
   537  	if actual != expected {
   538  		t.Fatalf("bad: \n%s", actual)
   539  	}
   540  }
   541  
   542  func TestContext2Apply_countDecrease(t *testing.T) {
   543  	m := testModule(t, "apply-count-dec")
   544  	p := testProvider("aws")
   545  	p.DiffFn = testDiffFn
   546  	s := &State{
   547  		Modules: []*ModuleState{
   548  			&ModuleState{
   549  				Path: rootModulePath,
   550  				Resources: map[string]*ResourceState{
   551  					"aws_instance.foo.0": &ResourceState{
   552  						Type: "aws_instance",
   553  						Primary: &InstanceState{
   554  							ID: "bar",
   555  							Attributes: map[string]string{
   556  								"foo":  "foo",
   557  								"type": "aws_instance",
   558  							},
   559  						},
   560  					},
   561  					"aws_instance.foo.1": &ResourceState{
   562  						Type: "aws_instance",
   563  						Primary: &InstanceState{
   564  							ID: "bar",
   565  							Attributes: map[string]string{
   566  								"foo":  "foo",
   567  								"type": "aws_instance",
   568  							},
   569  						},
   570  					},
   571  					"aws_instance.foo.2": &ResourceState{
   572  						Type: "aws_instance",
   573  						Primary: &InstanceState{
   574  							ID: "bar",
   575  							Attributes: map[string]string{
   576  								"foo":  "foo",
   577  								"type": "aws_instance",
   578  							},
   579  						},
   580  					},
   581  				},
   582  			},
   583  		},
   584  	}
   585  	ctx := testContext2(t, &ContextOpts{
   586  		Module: m,
   587  		Providers: map[string]ResourceProviderFactory{
   588  			"aws": testProviderFuncFixed(p),
   589  		},
   590  		State: s,
   591  	})
   592  
   593  	if _, err := ctx.Plan(); err != nil {
   594  		t.Fatalf("err: %s", err)
   595  	}
   596  
   597  	state, err := ctx.Apply()
   598  	if err != nil {
   599  		t.Fatalf("err: %s", err)
   600  	}
   601  
   602  	actual := strings.TrimSpace(state.String())
   603  	expected := strings.TrimSpace(testTerraformApplyCountDecStr)
   604  	if actual != expected {
   605  		t.Fatalf("bad: \n%s", actual)
   606  	}
   607  }
   608  
   609  func TestContext2Apply_countDecreaseToOne(t *testing.T) {
   610  	m := testModule(t, "apply-count-dec-one")
   611  	p := testProvider("aws")
   612  	p.ApplyFn = testApplyFn
   613  	p.DiffFn = testDiffFn
   614  	s := &State{
   615  		Modules: []*ModuleState{
   616  			&ModuleState{
   617  				Path: rootModulePath,
   618  				Resources: map[string]*ResourceState{
   619  					"aws_instance.foo.0": &ResourceState{
   620  						Type: "aws_instance",
   621  						Primary: &InstanceState{
   622  							ID: "bar",
   623  							Attributes: map[string]string{
   624  								"foo":  "foo",
   625  								"type": "aws_instance",
   626  							},
   627  						},
   628  					},
   629  					"aws_instance.foo.1": &ResourceState{
   630  						Type: "aws_instance",
   631  						Primary: &InstanceState{
   632  							ID: "bar",
   633  						},
   634  					},
   635  					"aws_instance.foo.2": &ResourceState{
   636  						Type: "aws_instance",
   637  						Primary: &InstanceState{
   638  							ID: "bar",
   639  						},
   640  					},
   641  				},
   642  			},
   643  		},
   644  	}
   645  	ctx := testContext2(t, &ContextOpts{
   646  		Module: m,
   647  		Providers: map[string]ResourceProviderFactory{
   648  			"aws": testProviderFuncFixed(p),
   649  		},
   650  		State: s,
   651  	})
   652  
   653  	if _, err := ctx.Plan(); err != nil {
   654  		t.Fatalf("err: %s", err)
   655  	}
   656  
   657  	state, err := ctx.Apply()
   658  	if err != nil {
   659  		t.Fatalf("err: %s", err)
   660  	}
   661  
   662  	actual := strings.TrimSpace(state.String())
   663  	expected := strings.TrimSpace(testTerraformApplyCountDecToOneStr)
   664  	if actual != expected {
   665  		t.Fatalf("bad: \n%s", actual)
   666  	}
   667  }
   668  
   669  // https://github.com/PeoplePerHour/terraform/pull/11
   670  //
   671  // This tests a case where both a "resource" and "resource.0" are in
   672  // the state file, which apparently is a reasonable backwards compatibility
   673  // concern found in the above 3rd party repo.
   674  func TestContext2Apply_countDecreaseToOneCorrupted(t *testing.T) {
   675  	m := testModule(t, "apply-count-dec-one")
   676  	p := testProvider("aws")
   677  	p.ApplyFn = testApplyFn
   678  	p.DiffFn = testDiffFn
   679  	s := &State{
   680  		Modules: []*ModuleState{
   681  			&ModuleState{
   682  				Path: rootModulePath,
   683  				Resources: map[string]*ResourceState{
   684  					"aws_instance.foo": &ResourceState{
   685  						Type: "aws_instance",
   686  						Primary: &InstanceState{
   687  							ID: "bar",
   688  							Attributes: map[string]string{
   689  								"foo":  "foo",
   690  								"type": "aws_instance",
   691  							},
   692  						},
   693  					},
   694  					"aws_instance.foo.0": &ResourceState{
   695  						Type: "aws_instance",
   696  						Primary: &InstanceState{
   697  							ID: "baz",
   698  							Attributes: map[string]string{
   699  								"type": "aws_instance",
   700  							},
   701  						},
   702  					},
   703  				},
   704  			},
   705  		},
   706  	}
   707  	ctx := testContext2(t, &ContextOpts{
   708  		Module: m,
   709  		Providers: map[string]ResourceProviderFactory{
   710  			"aws": testProviderFuncFixed(p),
   711  		},
   712  		State: s,
   713  	})
   714  
   715  	if p, err := ctx.Plan(); err != nil {
   716  		t.Fatalf("err: %s", err)
   717  	} else {
   718  		testStringMatch(t, p, testTerraformApplyCountDecToOneCorruptedPlanStr)
   719  	}
   720  
   721  	state, err := ctx.Apply()
   722  	if err != nil {
   723  		t.Fatalf("err: %s", err)
   724  	}
   725  
   726  	actual := strings.TrimSpace(state.String())
   727  	expected := strings.TrimSpace(testTerraformApplyCountDecToOneCorruptedStr)
   728  	if actual != expected {
   729  		t.Fatalf("bad: \n%s", actual)
   730  	}
   731  }
   732  
   733  func TestContext2Apply_countTainted(t *testing.T) {
   734  	m := testModule(t, "apply-count-tainted")
   735  	p := testProvider("aws")
   736  	p.DiffFn = testDiffFn
   737  	s := &State{
   738  		Modules: []*ModuleState{
   739  			&ModuleState{
   740  				Path: rootModulePath,
   741  				Resources: map[string]*ResourceState{
   742  					"aws_instance.foo.0": &ResourceState{
   743  						Type: "aws_instance",
   744  						Tainted: []*InstanceState{
   745  							&InstanceState{
   746  								ID: "bar",
   747  								Attributes: map[string]string{
   748  									"foo":  "foo",
   749  									"type": "aws_instance",
   750  								},
   751  							},
   752  						},
   753  					},
   754  				},
   755  			},
   756  		},
   757  	}
   758  	ctx := testContext2(t, &ContextOpts{
   759  		Module: m,
   760  		Providers: map[string]ResourceProviderFactory{
   761  			"aws": testProviderFuncFixed(p),
   762  		},
   763  		State: s,
   764  	})
   765  
   766  	if _, err := ctx.Plan(); err != nil {
   767  		t.Fatalf("err: %s", err)
   768  	}
   769  
   770  	state, err := ctx.Apply()
   771  	if err != nil {
   772  		t.Fatalf("err: %s", err)
   773  	}
   774  
   775  	actual := strings.TrimSpace(state.String())
   776  	expected := strings.TrimSpace(testTerraformApplyCountTaintedStr)
   777  	if actual != expected {
   778  		t.Fatalf("bad: \n%s", actual)
   779  	}
   780  }
   781  
   782  func TestContext2Apply_countVariable(t *testing.T) {
   783  	m := testModule(t, "apply-count-variable")
   784  	p := testProvider("aws")
   785  	p.ApplyFn = testApplyFn
   786  	p.DiffFn = testDiffFn
   787  	ctx := testContext2(t, &ContextOpts{
   788  		Module: m,
   789  		Providers: map[string]ResourceProviderFactory{
   790  			"aws": testProviderFuncFixed(p),
   791  		},
   792  	})
   793  
   794  	if _, err := ctx.Plan(); err != nil {
   795  		t.Fatalf("err: %s", err)
   796  	}
   797  
   798  	state, err := ctx.Apply()
   799  	if err != nil {
   800  		t.Fatalf("err: %s", err)
   801  	}
   802  
   803  	actual := strings.TrimSpace(state.String())
   804  	expected := strings.TrimSpace(testTerraformApplyCountVariableStr)
   805  	if actual != expected {
   806  		t.Fatalf("bad: \n%s", actual)
   807  	}
   808  }
   809  
   810  func TestContext2Apply_module(t *testing.T) {
   811  	m := testModule(t, "apply-module")
   812  	p := testProvider("aws")
   813  	p.ApplyFn = testApplyFn
   814  	p.DiffFn = testDiffFn
   815  	ctx := testContext2(t, &ContextOpts{
   816  		Module: m,
   817  		Providers: map[string]ResourceProviderFactory{
   818  			"aws": testProviderFuncFixed(p),
   819  		},
   820  	})
   821  
   822  	if _, err := ctx.Plan(); err != nil {
   823  		t.Fatalf("err: %s", err)
   824  	}
   825  
   826  	state, err := ctx.Apply()
   827  	if err != nil {
   828  		t.Fatalf("err: %s", err)
   829  	}
   830  
   831  	actual := strings.TrimSpace(state.String())
   832  	expected := strings.TrimSpace(testTerraformApplyModuleStr)
   833  	if actual != expected {
   834  		t.Fatalf("bad: \n%s", actual)
   835  	}
   836  }
   837  
   838  func TestContext2Apply_moduleDestroyOrder(t *testing.T) {
   839  	m := testModule(t, "apply-module-destroy-order")
   840  	p := testProvider("aws")
   841  	p.DiffFn = testDiffFn
   842  
   843  	// Create a custom apply function to track the order they were destroyed
   844  	var order []string
   845  	var orderLock sync.Mutex
   846  	p.ApplyFn = func(
   847  		info *InstanceInfo,
   848  		is *InstanceState,
   849  		id *InstanceDiff) (*InstanceState, error) {
   850  		orderLock.Lock()
   851  		defer orderLock.Unlock()
   852  
   853  		order = append(order, is.ID)
   854  		return nil, nil
   855  	}
   856  
   857  	state := &State{
   858  		Modules: []*ModuleState{
   859  			&ModuleState{
   860  				Path: rootModulePath,
   861  				Resources: map[string]*ResourceState{
   862  					"aws_instance.b": &ResourceState{
   863  						Type: "aws_instance",
   864  						Primary: &InstanceState{
   865  							ID: "b",
   866  						},
   867  					},
   868  				},
   869  			},
   870  
   871  			&ModuleState{
   872  				Path: []string{"root", "child"},
   873  				Resources: map[string]*ResourceState{
   874  					"aws_instance.a": &ResourceState{
   875  						Type: "aws_instance",
   876  						Primary: &InstanceState{
   877  							ID: "a",
   878  						},
   879  					},
   880  				},
   881  				Outputs: map[string]string{
   882  					"a_output": "a",
   883  				},
   884  			},
   885  		},
   886  	}
   887  
   888  	ctx := testContext2(t, &ContextOpts{
   889  		Module: m,
   890  		Providers: map[string]ResourceProviderFactory{
   891  			"aws": testProviderFuncFixed(p),
   892  		},
   893  		State:   state,
   894  		Destroy: true,
   895  	})
   896  
   897  	if _, err := ctx.Plan(); err != nil {
   898  		t.Fatalf("err: %s", err)
   899  	}
   900  
   901  	state, err := ctx.Apply()
   902  	if err != nil {
   903  		t.Fatalf("err: %s", err)
   904  	}
   905  
   906  	expected := []string{"b", "a"}
   907  	if !reflect.DeepEqual(order, expected) {
   908  		t.Fatalf("bad: %#v", order)
   909  	}
   910  
   911  	{
   912  		actual := strings.TrimSpace(state.String())
   913  		expected := strings.TrimSpace(testTerraformApplyModuleDestroyOrderStr)
   914  		if actual != expected {
   915  			t.Fatalf("bad: \n%s", actual)
   916  		}
   917  	}
   918  }
   919  
   920  func TestContext2Apply_moduleOrphanProvider(t *testing.T) {
   921  	m := testModule(t, "apply-module-orphan-provider-inherit")
   922  	p := testProvider("aws")
   923  	p.ApplyFn = testApplyFn
   924  	p.DiffFn = testDiffFn
   925  
   926  	p.ConfigureFn = func(c *ResourceConfig) error {
   927  		if _, ok := c.Get("value"); !ok {
   928  			return fmt.Errorf("value is not found")
   929  		}
   930  
   931  		return nil
   932  	}
   933  
   934  	// Create a state with an orphan module
   935  	state := &State{
   936  		Modules: []*ModuleState{
   937  			&ModuleState{
   938  				Path: []string{"root", "child"},
   939  				Resources: map[string]*ResourceState{
   940  					"aws_instance.bar": &ResourceState{
   941  						Type: "aws_instance",
   942  						Primary: &InstanceState{
   943  							ID: "bar",
   944  						},
   945  					},
   946  				},
   947  			},
   948  		},
   949  	}
   950  
   951  	ctx := testContext2(t, &ContextOpts{
   952  		Module: m,
   953  		State:  state,
   954  		Providers: map[string]ResourceProviderFactory{
   955  			"aws": testProviderFuncFixed(p),
   956  		},
   957  	})
   958  
   959  	if _, err := ctx.Plan(); err != nil {
   960  		t.Fatalf("err: %s", err)
   961  	}
   962  
   963  	if _, err := ctx.Apply(); err != nil {
   964  		t.Fatalf("err: %s", err)
   965  	}
   966  }
   967  
   968  // This tests an issue where all the providers in a module but not
   969  // in the root weren't being added to the root properly. In this test
   970  // case: aws is explicitly added to root, but "test" should be added to.
   971  // With the bug, it wasn't.
   972  func TestContext2Apply_moduleOnlyProvider(t *testing.T) {
   973  	m := testModule(t, "apply-module-only-provider")
   974  	p := testProvider("aws")
   975  	p.ApplyFn = testApplyFn
   976  	p.DiffFn = testDiffFn
   977  	pTest := testProvider("test")
   978  	pTest.ApplyFn = testApplyFn
   979  	pTest.DiffFn = testDiffFn
   980  
   981  	ctx := testContext2(t, &ContextOpts{
   982  		Module: m,
   983  		Providers: map[string]ResourceProviderFactory{
   984  			"aws":  testProviderFuncFixed(p),
   985  			"test": testProviderFuncFixed(pTest),
   986  		},
   987  	})
   988  
   989  	if _, err := ctx.Plan(); err != nil {
   990  		t.Fatalf("err: %s", err)
   991  	}
   992  
   993  	state, err := ctx.Apply()
   994  	if err != nil {
   995  		t.Fatalf("err: %s", err)
   996  	}
   997  
   998  	actual := strings.TrimSpace(state.String())
   999  	expected := strings.TrimSpace(testTerraformApplyModuleOnlyProviderStr)
  1000  	if actual != expected {
  1001  		t.Fatalf("bad: \n%s", actual)
  1002  	}
  1003  }
  1004  
  1005  func TestContext2Apply_moduleProviderAlias(t *testing.T) {
  1006  	m := testModule(t, "apply-module-provider-alias")
  1007  	p := testProvider("aws")
  1008  	p.ApplyFn = testApplyFn
  1009  	p.DiffFn = testDiffFn
  1010  	ctx := testContext2(t, &ContextOpts{
  1011  		Module: m,
  1012  		Providers: map[string]ResourceProviderFactory{
  1013  			"aws": testProviderFuncFixed(p),
  1014  		},
  1015  	})
  1016  
  1017  	if _, err := ctx.Plan(); err != nil {
  1018  		t.Fatalf("err: %s", err)
  1019  	}
  1020  
  1021  	state, err := ctx.Apply()
  1022  	if err != nil {
  1023  		t.Fatalf("err: %s", err)
  1024  	}
  1025  
  1026  	actual := strings.TrimSpace(state.String())
  1027  	expected := strings.TrimSpace(testTerraformApplyModuleProviderAliasStr)
  1028  	if actual != expected {
  1029  		t.Fatalf("bad: \n%s", actual)
  1030  	}
  1031  }
  1032  
  1033  func TestContext2Apply_moduleProviderAliasTargets(t *testing.T) {
  1034  	m := testModule(t, "apply-module-provider-alias")
  1035  	p := testProvider("aws")
  1036  	p.ApplyFn = testApplyFn
  1037  	p.DiffFn = testDiffFn
  1038  	ctx := testContext2(t, &ContextOpts{
  1039  		Module: m,
  1040  		Providers: map[string]ResourceProviderFactory{
  1041  			"aws": testProviderFuncFixed(p),
  1042  		},
  1043  		Targets: []string{"no.thing"},
  1044  	})
  1045  
  1046  	if _, err := ctx.Plan(); err != nil {
  1047  		t.Fatalf("err: %s", err)
  1048  	}
  1049  
  1050  	state, err := ctx.Apply()
  1051  	if err != nil {
  1052  		t.Fatalf("err: %s", err)
  1053  	}
  1054  
  1055  	actual := strings.TrimSpace(state.String())
  1056  	expected := strings.TrimSpace(`
  1057  <no state>
  1058  	`)
  1059  	if actual != expected {
  1060  		t.Fatalf("bad: \n%s", actual)
  1061  	}
  1062  }
  1063  
  1064  func TestContext2Apply_moduleProviderCloseNested(t *testing.T) {
  1065  	m := testModule(t, "apply-module-provider-close-nested")
  1066  	p := testProvider("aws")
  1067  	p.ApplyFn = testApplyFn
  1068  	p.DiffFn = testDiffFn
  1069  	ctx := testContext2(t, &ContextOpts{
  1070  		Module: m,
  1071  		Providers: map[string]ResourceProviderFactory{
  1072  			"aws": testProviderFuncFixed(p),
  1073  		},
  1074  		State: &State{
  1075  			Modules: []*ModuleState{
  1076  				&ModuleState{
  1077  					Path: []string{"root", "child", "subchild"},
  1078  					Resources: map[string]*ResourceState{
  1079  						"aws_instance.foo": &ResourceState{
  1080  							Type: "aws_instance",
  1081  							Primary: &InstanceState{
  1082  								ID: "bar",
  1083  							},
  1084  						},
  1085  					},
  1086  				},
  1087  			},
  1088  		},
  1089  		Destroy: true,
  1090  	})
  1091  
  1092  	if _, err := ctx.Plan(); err != nil {
  1093  		t.Fatalf("err: %s", err)
  1094  	}
  1095  
  1096  	if _, err := ctx.Apply(); err != nil {
  1097  		t.Fatalf("err: %s", err)
  1098  	}
  1099  }
  1100  
  1101  func TestContext2Apply_moduleVarResourceCount(t *testing.T) {
  1102  	m := testModule(t, "apply-module-var-resource-count")
  1103  	p := testProvider("aws")
  1104  	p.ApplyFn = testApplyFn
  1105  	p.DiffFn = testDiffFn
  1106  	ctx := testContext2(t, &ContextOpts{
  1107  		Module: m,
  1108  		Providers: map[string]ResourceProviderFactory{
  1109  			"aws": testProviderFuncFixed(p),
  1110  		},
  1111  		Variables: map[string]string{
  1112  			"count": "2",
  1113  		},
  1114  		Destroy: true,
  1115  	})
  1116  
  1117  	if _, err := ctx.Plan(); err != nil {
  1118  		t.Fatalf("err: %s", err)
  1119  	}
  1120  
  1121  	if _, err := ctx.Apply(); err != nil {
  1122  		t.Fatalf("err: %s", err)
  1123  	}
  1124  
  1125  	ctx = testContext2(t, &ContextOpts{
  1126  		Module: m,
  1127  		Providers: map[string]ResourceProviderFactory{
  1128  			"aws": testProviderFuncFixed(p),
  1129  		},
  1130  		Variables: map[string]string{
  1131  			"count": "5",
  1132  		},
  1133  	})
  1134  
  1135  	if _, err := ctx.Plan(); err != nil {
  1136  		t.Fatalf("err: %s", err)
  1137  	}
  1138  
  1139  	if _, err := ctx.Apply(); err != nil {
  1140  		t.Fatalf("err: %s", err)
  1141  	}
  1142  }
  1143  
  1144  // GH-819
  1145  func TestContext2Apply_moduleBool(t *testing.T) {
  1146  	m := testModule(t, "apply-module-bool")
  1147  	p := testProvider("aws")
  1148  	p.ApplyFn = testApplyFn
  1149  	p.DiffFn = testDiffFn
  1150  	ctx := testContext2(t, &ContextOpts{
  1151  		Module: m,
  1152  		Providers: map[string]ResourceProviderFactory{
  1153  			"aws": testProviderFuncFixed(p),
  1154  		},
  1155  	})
  1156  
  1157  	if _, err := ctx.Plan(); err != nil {
  1158  		t.Fatalf("err: %s", err)
  1159  	}
  1160  
  1161  	state, err := ctx.Apply()
  1162  	if err != nil {
  1163  		t.Fatalf("err: %s", err)
  1164  	}
  1165  
  1166  	actual := strings.TrimSpace(state.String())
  1167  	expected := strings.TrimSpace(testTerraformApplyModuleBoolStr)
  1168  	if actual != expected {
  1169  		t.Fatalf("bad: \n%s", actual)
  1170  	}
  1171  }
  1172  
  1173  func TestContext2Apply_multiProvider(t *testing.T) {
  1174  	m := testModule(t, "apply-multi-provider")
  1175  	p := testProvider("aws")
  1176  	p.ApplyFn = testApplyFn
  1177  	p.DiffFn = testDiffFn
  1178  
  1179  	pDO := testProvider("do")
  1180  	pDO.ApplyFn = testApplyFn
  1181  	pDO.DiffFn = testDiffFn
  1182  
  1183  	ctx := testContext2(t, &ContextOpts{
  1184  		Module: m,
  1185  		Providers: map[string]ResourceProviderFactory{
  1186  			"aws": testProviderFuncFixed(p),
  1187  			"do":  testProviderFuncFixed(pDO),
  1188  		},
  1189  	})
  1190  
  1191  	if _, err := ctx.Plan(); err != nil {
  1192  		t.Fatalf("err: %s", err)
  1193  	}
  1194  
  1195  	state, err := ctx.Apply()
  1196  	if err != nil {
  1197  		t.Fatalf("err: %s", err)
  1198  	}
  1199  
  1200  	mod := state.RootModule()
  1201  	if len(mod.Resources) < 2 {
  1202  		t.Fatalf("bad: %#v", mod.Resources)
  1203  	}
  1204  
  1205  	actual := strings.TrimSpace(state.String())
  1206  	expected := strings.TrimSpace(testTerraformApplyMultiProviderStr)
  1207  	if actual != expected {
  1208  		t.Fatalf("bad: \n%s", actual)
  1209  	}
  1210  }
  1211  
  1212  func TestContext2Apply_multiVar(t *testing.T) {
  1213  	m := testModule(t, "apply-multi-var")
  1214  	p := testProvider("aws")
  1215  	p.ApplyFn = testApplyFn
  1216  	p.DiffFn = testDiffFn
  1217  
  1218  	// First, apply with a count of 3
  1219  	ctx := testContext2(t, &ContextOpts{
  1220  		Module: m,
  1221  		Providers: map[string]ResourceProviderFactory{
  1222  			"aws": testProviderFuncFixed(p),
  1223  		},
  1224  		Variables: map[string]string{
  1225  			"count": "3",
  1226  		},
  1227  	})
  1228  
  1229  	if _, err := ctx.Plan(); err != nil {
  1230  		t.Fatalf("err: %s", err)
  1231  	}
  1232  
  1233  	state, err := ctx.Apply()
  1234  	if err != nil {
  1235  		t.Fatalf("err: %s", err)
  1236  	}
  1237  
  1238  	actual := state.RootModule().Outputs["output"]
  1239  	expected := "bar0,bar1,bar2"
  1240  	if actual != expected {
  1241  		t.Fatalf("bad: \n%s", actual)
  1242  	}
  1243  
  1244  	// Apply again, reduce the count to 1
  1245  	{
  1246  		ctx := testContext2(t, &ContextOpts{
  1247  			Module: m,
  1248  			State:  state,
  1249  			Providers: map[string]ResourceProviderFactory{
  1250  				"aws": testProviderFuncFixed(p),
  1251  			},
  1252  			Variables: map[string]string{
  1253  				"count": "1",
  1254  			},
  1255  		})
  1256  
  1257  		if _, err := ctx.Plan(); err != nil {
  1258  			t.Fatalf("err: %s", err)
  1259  		}
  1260  
  1261  		state, err := ctx.Apply()
  1262  		if err != nil {
  1263  			t.Fatalf("err: %s", err)
  1264  		}
  1265  
  1266  		actual := state.RootModule().Outputs["output"]
  1267  		expected := "bar0"
  1268  		if actual != expected {
  1269  			t.Fatalf("bad: \n%s", actual)
  1270  		}
  1271  	}
  1272  }
  1273  
  1274  func TestContext2Apply_nilDiff(t *testing.T) {
  1275  	m := testModule(t, "apply-good")
  1276  	p := testProvider("aws")
  1277  	p.ApplyFn = testApplyFn
  1278  	p.DiffFn = testDiffFn
  1279  	ctx := testContext2(t, &ContextOpts{
  1280  		Module: m,
  1281  		Providers: map[string]ResourceProviderFactory{
  1282  			"aws": testProviderFuncFixed(p),
  1283  		},
  1284  	})
  1285  
  1286  	if _, err := ctx.Plan(); err != nil {
  1287  		t.Fatalf("err: %s", err)
  1288  	}
  1289  
  1290  	p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) {
  1291  		return nil, nil
  1292  	}
  1293  
  1294  	if _, err := ctx.Apply(); err == nil {
  1295  		t.Fatal("should error")
  1296  	}
  1297  }
  1298  
  1299  func TestContext2Apply_outputOrphan(t *testing.T) {
  1300  	m := testModule(t, "apply-output-orphan")
  1301  	p := testProvider("aws")
  1302  	p.ApplyFn = testApplyFn
  1303  	p.DiffFn = testDiffFn
  1304  
  1305  	state := &State{
  1306  		Modules: []*ModuleState{
  1307  			&ModuleState{
  1308  				Path: rootModulePath,
  1309  				Outputs: map[string]string{
  1310  					"foo": "bar",
  1311  					"bar": "baz",
  1312  				},
  1313  			},
  1314  		},
  1315  	}
  1316  
  1317  	ctx := testContext2(t, &ContextOpts{
  1318  		Module: m,
  1319  		Providers: map[string]ResourceProviderFactory{
  1320  			"aws": testProviderFuncFixed(p),
  1321  		},
  1322  		State: state,
  1323  	})
  1324  
  1325  	if _, err := ctx.Plan(); err != nil {
  1326  		t.Fatalf("err: %s", err)
  1327  	}
  1328  
  1329  	state, err := ctx.Apply()
  1330  	if err != nil {
  1331  		t.Fatalf("err: %s", err)
  1332  	}
  1333  
  1334  	actual := strings.TrimSpace(state.String())
  1335  	expected := strings.TrimSpace(testTerraformApplyOutputOrphanStr)
  1336  	if actual != expected {
  1337  		t.Fatalf("bad: \n%s", actual)
  1338  	}
  1339  }
  1340  
  1341  func TestContext2Apply_providerComputedVar(t *testing.T) {
  1342  	m := testModule(t, "apply-provider-computed")
  1343  	p := testProvider("aws")
  1344  	p.ApplyFn = testApplyFn
  1345  	p.DiffFn = testDiffFn
  1346  
  1347  	pTest := testProvider("test")
  1348  	pTest.ApplyFn = testApplyFn
  1349  	pTest.DiffFn = testDiffFn
  1350  
  1351  	ctx := testContext2(t, &ContextOpts{
  1352  		Module: m,
  1353  		Providers: map[string]ResourceProviderFactory{
  1354  			"aws":  testProviderFuncFixed(p),
  1355  			"test": testProviderFuncFixed(pTest),
  1356  		},
  1357  	})
  1358  
  1359  	p.ConfigureFn = func(c *ResourceConfig) error {
  1360  		if c.IsComputed("value") {
  1361  			return fmt.Errorf("value is computed")
  1362  		}
  1363  
  1364  		v, ok := c.Get("value")
  1365  		if !ok {
  1366  			return fmt.Errorf("value is not found")
  1367  		}
  1368  		if v != "yes" {
  1369  			return fmt.Errorf("value is not 'yes': %v", v)
  1370  		}
  1371  
  1372  		return nil
  1373  	}
  1374  
  1375  	if _, err := ctx.Plan(); err != nil {
  1376  		t.Fatalf("err: %s", err)
  1377  	}
  1378  
  1379  	if _, err := ctx.Apply(); err != nil {
  1380  		t.Fatalf("err: %s", err)
  1381  	}
  1382  }
  1383  
  1384  func TestContext2Apply_Provisioner_compute(t *testing.T) {
  1385  	m := testModule(t, "apply-provisioner-compute")
  1386  	p := testProvider("aws")
  1387  	pr := testProvisioner()
  1388  	p.ApplyFn = testApplyFn
  1389  	p.DiffFn = testDiffFn
  1390  	pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error {
  1391  		val, ok := c.Config["foo"]
  1392  		if !ok || val != "computed_dynamical" {
  1393  			t.Fatalf("bad value for foo: %v %#v", val, c)
  1394  		}
  1395  
  1396  		return nil
  1397  	}
  1398  	ctx := testContext2(t, &ContextOpts{
  1399  		Module: m,
  1400  		Providers: map[string]ResourceProviderFactory{
  1401  			"aws": testProviderFuncFixed(p),
  1402  		},
  1403  		Provisioners: map[string]ResourceProvisionerFactory{
  1404  			"shell": testProvisionerFuncFixed(pr),
  1405  		},
  1406  		Variables: map[string]string{
  1407  			"value": "1",
  1408  		},
  1409  	})
  1410  
  1411  	if _, err := ctx.Plan(); err != nil {
  1412  		t.Fatalf("err: %s", err)
  1413  	}
  1414  
  1415  	state, err := ctx.Apply()
  1416  	if err != nil {
  1417  		t.Fatalf("err: %s", err)
  1418  	}
  1419  
  1420  	actual := strings.TrimSpace(state.String())
  1421  	expected := strings.TrimSpace(testTerraformApplyProvisionerStr)
  1422  	if actual != expected {
  1423  		t.Fatalf("bad: \n%s", actual)
  1424  	}
  1425  
  1426  	// Verify apply was invoked
  1427  	if !pr.ApplyCalled {
  1428  		t.Fatalf("provisioner not invoked")
  1429  	}
  1430  }
  1431  
  1432  func TestContext2Apply_provisionerCreateFail(t *testing.T) {
  1433  	m := testModule(t, "apply-provisioner-fail-create")
  1434  	p := testProvider("aws")
  1435  	pr := testProvisioner()
  1436  	p.DiffFn = testDiffFn
  1437  
  1438  	p.ApplyFn = func(
  1439  		info *InstanceInfo,
  1440  		is *InstanceState,
  1441  		id *InstanceDiff) (*InstanceState, error) {
  1442  		is.ID = "foo"
  1443  		return is, fmt.Errorf("error")
  1444  	}
  1445  
  1446  	ctx := testContext2(t, &ContextOpts{
  1447  		Module: m,
  1448  		Providers: map[string]ResourceProviderFactory{
  1449  			"aws": testProviderFuncFixed(p),
  1450  		},
  1451  		Provisioners: map[string]ResourceProvisionerFactory{
  1452  			"shell": testProvisionerFuncFixed(pr),
  1453  		},
  1454  	})
  1455  
  1456  	if _, err := ctx.Plan(); err != nil {
  1457  		t.Fatalf("err: %s", err)
  1458  	}
  1459  
  1460  	state, err := ctx.Apply()
  1461  	if err == nil {
  1462  		t.Fatal("should error")
  1463  	}
  1464  
  1465  	actual := strings.TrimSpace(state.String())
  1466  	expected := strings.TrimSpace(testTerraformApplyProvisionerFailCreateStr)
  1467  	if actual != expected {
  1468  		t.Fatalf("bad: \n%s", actual)
  1469  	}
  1470  }
  1471  
  1472  func TestContext2Apply_provisionerCreateFailNoId(t *testing.T) {
  1473  	m := testModule(t, "apply-provisioner-fail-create")
  1474  	p := testProvider("aws")
  1475  	pr := testProvisioner()
  1476  	p.DiffFn = testDiffFn
  1477  
  1478  	p.ApplyFn = func(
  1479  		info *InstanceInfo,
  1480  		is *InstanceState,
  1481  		id *InstanceDiff) (*InstanceState, error) {
  1482  		return nil, fmt.Errorf("error")
  1483  	}
  1484  
  1485  	ctx := testContext2(t, &ContextOpts{
  1486  		Module: m,
  1487  		Providers: map[string]ResourceProviderFactory{
  1488  			"aws": testProviderFuncFixed(p),
  1489  		},
  1490  		Provisioners: map[string]ResourceProvisionerFactory{
  1491  			"shell": testProvisionerFuncFixed(pr),
  1492  		},
  1493  	})
  1494  
  1495  	if _, err := ctx.Plan(); err != nil {
  1496  		t.Fatalf("err: %s", err)
  1497  	}
  1498  
  1499  	state, err := ctx.Apply()
  1500  	if err == nil {
  1501  		t.Fatal("should error")
  1502  	}
  1503  
  1504  	actual := strings.TrimSpace(state.String())
  1505  	expected := strings.TrimSpace(testTerraformApplyProvisionerFailCreateNoIdStr)
  1506  	if actual != expected {
  1507  		t.Fatalf("bad: \n%s", actual)
  1508  	}
  1509  }
  1510  
  1511  func TestContext2Apply_provisionerFail(t *testing.T) {
  1512  	m := testModule(t, "apply-provisioner-fail")
  1513  	p := testProvider("aws")
  1514  	pr := testProvisioner()
  1515  	p.ApplyFn = testApplyFn
  1516  	p.DiffFn = testDiffFn
  1517  
  1518  	pr.ApplyFn = func(*InstanceState, *ResourceConfig) error {
  1519  		return fmt.Errorf("EXPLOSION")
  1520  	}
  1521  
  1522  	ctx := testContext2(t, &ContextOpts{
  1523  		Module: m,
  1524  		Providers: map[string]ResourceProviderFactory{
  1525  			"aws": testProviderFuncFixed(p),
  1526  		},
  1527  		Provisioners: map[string]ResourceProvisionerFactory{
  1528  			"shell": testProvisionerFuncFixed(pr),
  1529  		},
  1530  		Variables: map[string]string{
  1531  			"value": "1",
  1532  		},
  1533  	})
  1534  
  1535  	if _, err := ctx.Plan(); err != nil {
  1536  		t.Fatalf("err: %s", err)
  1537  	}
  1538  
  1539  	state, err := ctx.Apply()
  1540  	if err == nil {
  1541  		t.Fatal("should error")
  1542  	}
  1543  
  1544  	actual := strings.TrimSpace(state.String())
  1545  	expected := strings.TrimSpace(testTerraformApplyProvisionerFailStr)
  1546  	if actual != expected {
  1547  		t.Fatalf("bad: \n%s", actual)
  1548  	}
  1549  }
  1550  
  1551  func TestContext2Apply_provisionerFail_createBeforeDestroy(t *testing.T) {
  1552  	m := testModule(t, "apply-provisioner-fail-create-before")
  1553  	p := testProvider("aws")
  1554  	pr := testProvisioner()
  1555  	p.ApplyFn = testApplyFn
  1556  	p.DiffFn = testDiffFn
  1557  	pr.ApplyFn = func(*InstanceState, *ResourceConfig) error {
  1558  		return fmt.Errorf("EXPLOSION")
  1559  	}
  1560  
  1561  	state := &State{
  1562  		Modules: []*ModuleState{
  1563  			&ModuleState{
  1564  				Path: rootModulePath,
  1565  				Resources: map[string]*ResourceState{
  1566  					"aws_instance.bar": &ResourceState{
  1567  						Type: "aws_instance",
  1568  						Primary: &InstanceState{
  1569  							ID: "bar",
  1570  							Attributes: map[string]string{
  1571  								"require_new": "abc",
  1572  							},
  1573  						},
  1574  					},
  1575  				},
  1576  			},
  1577  		},
  1578  	}
  1579  	ctx := testContext2(t, &ContextOpts{
  1580  		Module: m,
  1581  		Providers: map[string]ResourceProviderFactory{
  1582  			"aws": testProviderFuncFixed(p),
  1583  		},
  1584  		Provisioners: map[string]ResourceProvisionerFactory{
  1585  			"shell": testProvisionerFuncFixed(pr),
  1586  		},
  1587  		State: state,
  1588  	})
  1589  
  1590  	if _, err := ctx.Plan(); err != nil {
  1591  		t.Fatalf("err: %s", err)
  1592  	}
  1593  
  1594  	state, err := ctx.Apply()
  1595  	if err == nil {
  1596  		t.Fatal("should error")
  1597  	}
  1598  
  1599  	actual := strings.TrimSpace(state.String())
  1600  	expected := strings.TrimSpace(testTerraformApplyProvisionerFailCreateBeforeDestroyStr)
  1601  	if actual != expected {
  1602  		t.Fatalf("bad: \n%s", actual)
  1603  	}
  1604  }
  1605  
  1606  func TestContext2Apply_error_createBeforeDestroy(t *testing.T) {
  1607  	m := testModule(t, "apply-error-create-before")
  1608  	p := testProvider("aws")
  1609  	state := &State{
  1610  		Modules: []*ModuleState{
  1611  			&ModuleState{
  1612  				Path: rootModulePath,
  1613  				Resources: map[string]*ResourceState{
  1614  					"aws_instance.bar": &ResourceState{
  1615  						Type: "aws_instance",
  1616  						Primary: &InstanceState{
  1617  							ID: "bar",
  1618  							Attributes: map[string]string{
  1619  								"require_new": "abc",
  1620  							},
  1621  						},
  1622  					},
  1623  				},
  1624  			},
  1625  		},
  1626  	}
  1627  	ctx := testContext2(t, &ContextOpts{
  1628  		Module: m,
  1629  		Providers: map[string]ResourceProviderFactory{
  1630  			"aws": testProviderFuncFixed(p),
  1631  		},
  1632  		State: state,
  1633  	})
  1634  	p.ApplyFn = func(info *InstanceInfo, is *InstanceState, id *InstanceDiff) (*InstanceState, error) {
  1635  		return nil, fmt.Errorf("error")
  1636  	}
  1637  	p.DiffFn = testDiffFn
  1638  
  1639  	if _, err := ctx.Plan(); err != nil {
  1640  		t.Fatalf("err: %s", err)
  1641  	}
  1642  
  1643  	state, err := ctx.Apply()
  1644  	if err == nil {
  1645  		t.Fatal("should have error")
  1646  	}
  1647  
  1648  	actual := strings.TrimSpace(state.String())
  1649  	expected := strings.TrimSpace(testTerraformApplyErrorCreateBeforeDestroyStr)
  1650  	if actual != expected {
  1651  		t.Fatalf("bad: \n%s\n\nExpected:\n\n%s", actual, expected)
  1652  	}
  1653  }
  1654  
  1655  func TestContext2Apply_errorDestroy_createBeforeDestroy(t *testing.T) {
  1656  	m := testModule(t, "apply-error-create-before")
  1657  	p := testProvider("aws")
  1658  	state := &State{
  1659  		Modules: []*ModuleState{
  1660  			&ModuleState{
  1661  				Path: rootModulePath,
  1662  				Resources: map[string]*ResourceState{
  1663  					"aws_instance.bar": &ResourceState{
  1664  						Type: "aws_instance",
  1665  						Primary: &InstanceState{
  1666  							ID: "bar",
  1667  							Attributes: map[string]string{
  1668  								"require_new": "abc",
  1669  							},
  1670  						},
  1671  					},
  1672  				},
  1673  			},
  1674  		},
  1675  	}
  1676  	ctx := testContext2(t, &ContextOpts{
  1677  		Module: m,
  1678  		Providers: map[string]ResourceProviderFactory{
  1679  			"aws": testProviderFuncFixed(p),
  1680  		},
  1681  		State: state,
  1682  	})
  1683  	p.ApplyFn = func(info *InstanceInfo, is *InstanceState, id *InstanceDiff) (*InstanceState, error) {
  1684  		// Fail the destroy!
  1685  		if id.Destroy {
  1686  			return is, fmt.Errorf("error")
  1687  		}
  1688  
  1689  		// Create should work
  1690  		is = &InstanceState{
  1691  			ID: "foo",
  1692  		}
  1693  		return is, nil
  1694  	}
  1695  	p.DiffFn = testDiffFn
  1696  
  1697  	if _, err := ctx.Plan(); err != nil {
  1698  		t.Fatalf("err: %s", err)
  1699  	}
  1700  
  1701  	state, err := ctx.Apply()
  1702  	if err == nil {
  1703  		t.Fatal("should have error")
  1704  	}
  1705  
  1706  	actual := strings.TrimSpace(state.String())
  1707  	expected := strings.TrimSpace(testTerraformApplyErrorDestroyCreateBeforeDestroyStr)
  1708  	if actual != expected {
  1709  		t.Fatalf("bad: actual:\n%s\n\nexpected:\n%s", actual, expected)
  1710  	}
  1711  }
  1712  
  1713  func TestContext2Apply_multiDepose_createBeforeDestroy(t *testing.T) {
  1714  	m := testModule(t, "apply-multi-depose-create-before-destroy")
  1715  	p := testProvider("aws")
  1716  	p.DiffFn = testDiffFn
  1717  	ps := map[string]ResourceProviderFactory{"aws": testProviderFuncFixed(p)}
  1718  	state := &State{
  1719  		Modules: []*ModuleState{
  1720  			&ModuleState{
  1721  				Path: rootModulePath,
  1722  				Resources: map[string]*ResourceState{
  1723  					"aws_instance.web": &ResourceState{
  1724  						Type:    "aws_instance",
  1725  						Primary: &InstanceState{ID: "foo"},
  1726  					},
  1727  				},
  1728  			},
  1729  		},
  1730  	}
  1731  
  1732  	ctx := testContext2(t, &ContextOpts{
  1733  		Module:    m,
  1734  		Providers: ps,
  1735  		State:     state,
  1736  	})
  1737  	createdInstanceId := "bar"
  1738  	// Create works
  1739  	createFunc := func(is *InstanceState) (*InstanceState, error) {
  1740  		return &InstanceState{ID: createdInstanceId}, nil
  1741  	}
  1742  	// Destroy starts broken
  1743  	destroyFunc := func(is *InstanceState) (*InstanceState, error) {
  1744  		return is, fmt.Errorf("destroy failed")
  1745  	}
  1746  	p.ApplyFn = func(info *InstanceInfo, is *InstanceState, id *InstanceDiff) (*InstanceState, error) {
  1747  		if id.Destroy {
  1748  			return destroyFunc(is)
  1749  		} else {
  1750  			return createFunc(is)
  1751  		}
  1752  	}
  1753  
  1754  	if _, err := ctx.Plan(); err != nil {
  1755  		t.Fatalf("err: %s", err)
  1756  	}
  1757  
  1758  	// Destroy is broken, so even though CBD successfully replaces the instance,
  1759  	// we'll have to save the Deposed instance to destroy later
  1760  	state, err := ctx.Apply()
  1761  	if err == nil {
  1762  		t.Fatal("should have error")
  1763  	}
  1764  
  1765  	checkStateString(t, state, `
  1766  aws_instance.web: (1 deposed)
  1767    ID = bar
  1768    Deposed ID 1 = foo
  1769  	`)
  1770  
  1771  	createdInstanceId = "baz"
  1772  	ctx = testContext2(t, &ContextOpts{
  1773  		Module:    m,
  1774  		Providers: ps,
  1775  		State:     state,
  1776  	})
  1777  
  1778  	if _, err := ctx.Plan(); err != nil {
  1779  		t.Fatalf("err: %s", err)
  1780  	}
  1781  
  1782  	// We're replacing the primary instance once again. Destroy is _still_
  1783  	// broken, so the Deposed list gets longer
  1784  	state, err = ctx.Apply()
  1785  	if err == nil {
  1786  		t.Fatal("should have error")
  1787  	}
  1788  
  1789  	checkStateString(t, state, `
  1790  aws_instance.web: (2 deposed)
  1791    ID = baz
  1792    Deposed ID 1 = foo
  1793    Deposed ID 2 = bar
  1794  	`)
  1795  
  1796  	// Destroy partially fixed!
  1797  	destroyFunc = func(is *InstanceState) (*InstanceState, error) {
  1798  		if is.ID == "foo" || is.ID == "baz" {
  1799  			return nil, nil
  1800  		} else {
  1801  			return is, fmt.Errorf("destroy partially failed")
  1802  		}
  1803  	}
  1804  
  1805  	createdInstanceId = "qux"
  1806  	if _, err := ctx.Plan(); err != nil {
  1807  		t.Fatalf("err: %s", err)
  1808  	}
  1809  	state, err = ctx.Apply()
  1810  	// Expect error because 1/2 of Deposed destroys failed
  1811  	if err == nil {
  1812  		t.Fatal("should have error")
  1813  	}
  1814  
  1815  	// foo and baz are now gone, bar sticks around
  1816  	checkStateString(t, state, `
  1817  aws_instance.web: (1 deposed)
  1818    ID = qux
  1819    Deposed ID 1 = bar
  1820  	`)
  1821  
  1822  	// Destroy working fully!
  1823  	destroyFunc = func(is *InstanceState) (*InstanceState, error) {
  1824  		return nil, nil
  1825  	}
  1826  
  1827  	createdInstanceId = "quux"
  1828  	if _, err := ctx.Plan(); err != nil {
  1829  		t.Fatalf("err: %s", err)
  1830  	}
  1831  	state, err = ctx.Apply()
  1832  	if err != nil {
  1833  		t.Fatal("should not have error:", err)
  1834  	}
  1835  
  1836  	// And finally the state is clean
  1837  	checkStateString(t, state, `
  1838  aws_instance.web:
  1839    ID = quux
  1840  	`)
  1841  }
  1842  
  1843  func TestContext2Apply_provisionerResourceRef(t *testing.T) {
  1844  	m := testModule(t, "apply-provisioner-resource-ref")
  1845  	p := testProvider("aws")
  1846  	pr := testProvisioner()
  1847  	p.ApplyFn = testApplyFn
  1848  	p.DiffFn = testDiffFn
  1849  	pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error {
  1850  		val, ok := c.Config["foo"]
  1851  		if !ok || val != "2" {
  1852  			t.Fatalf("bad value for foo: %v %#v", val, c)
  1853  		}
  1854  
  1855  		return nil
  1856  	}
  1857  
  1858  	ctx := testContext2(t, &ContextOpts{
  1859  		Module: m,
  1860  		Providers: map[string]ResourceProviderFactory{
  1861  			"aws": testProviderFuncFixed(p),
  1862  		},
  1863  		Provisioners: map[string]ResourceProvisionerFactory{
  1864  			"shell": testProvisionerFuncFixed(pr),
  1865  		},
  1866  	})
  1867  
  1868  	if _, err := ctx.Plan(); err != nil {
  1869  		t.Fatalf("err: %s", err)
  1870  	}
  1871  
  1872  	state, err := ctx.Apply()
  1873  	if err != nil {
  1874  		t.Fatalf("err: %s", err)
  1875  	}
  1876  
  1877  	actual := strings.TrimSpace(state.String())
  1878  	expected := strings.TrimSpace(testTerraformApplyProvisionerResourceRefStr)
  1879  	if actual != expected {
  1880  		t.Fatalf("bad: \n%s", actual)
  1881  	}
  1882  
  1883  	// Verify apply was invoked
  1884  	if !pr.ApplyCalled {
  1885  		t.Fatalf("provisioner not invoked")
  1886  	}
  1887  }
  1888  
  1889  func TestContext2Apply_provisionerSelfRef(t *testing.T) {
  1890  	m := testModule(t, "apply-provisioner-self-ref")
  1891  	p := testProvider("aws")
  1892  	pr := testProvisioner()
  1893  	p.ApplyFn = testApplyFn
  1894  	p.DiffFn = testDiffFn
  1895  	pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error {
  1896  		val, ok := c.Config["command"]
  1897  		if !ok || val != "bar" {
  1898  			t.Fatalf("bad value for command: %v %#v", val, c)
  1899  		}
  1900  
  1901  		return nil
  1902  	}
  1903  
  1904  	ctx := testContext2(t, &ContextOpts{
  1905  		Module: m,
  1906  		Providers: map[string]ResourceProviderFactory{
  1907  			"aws": testProviderFuncFixed(p),
  1908  		},
  1909  		Provisioners: map[string]ResourceProvisionerFactory{
  1910  			"shell": testProvisionerFuncFixed(pr),
  1911  		},
  1912  	})
  1913  
  1914  	if _, err := ctx.Plan(); err != nil {
  1915  		t.Fatalf("err: %s", err)
  1916  	}
  1917  
  1918  	state, err := ctx.Apply()
  1919  	if err != nil {
  1920  		t.Fatalf("err: %s", err)
  1921  	}
  1922  
  1923  	actual := strings.TrimSpace(state.String())
  1924  	expected := strings.TrimSpace(testTerraformApplyProvisionerSelfRefStr)
  1925  	if actual != expected {
  1926  		t.Fatalf("bad: \n%s", actual)
  1927  	}
  1928  
  1929  	// Verify apply was invoked
  1930  	if !pr.ApplyCalled {
  1931  		t.Fatalf("provisioner not invoked")
  1932  	}
  1933  }
  1934  
  1935  func TestContext2Apply_provisionerMultiSelfRef(t *testing.T) {
  1936  	var lock sync.Mutex
  1937  	commands := make([]string, 0, 5)
  1938  
  1939  	m := testModule(t, "apply-provisioner-multi-self-ref")
  1940  	p := testProvider("aws")
  1941  	pr := testProvisioner()
  1942  	p.ApplyFn = testApplyFn
  1943  	p.DiffFn = testDiffFn
  1944  	pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error {
  1945  		lock.Lock()
  1946  		defer lock.Unlock()
  1947  
  1948  		val, ok := c.Config["command"]
  1949  		if !ok {
  1950  			t.Fatalf("bad value for command: %v %#v", val, c)
  1951  		}
  1952  
  1953  		commands = append(commands, val.(string))
  1954  		return nil
  1955  	}
  1956  
  1957  	ctx := testContext2(t, &ContextOpts{
  1958  		Module: m,
  1959  		Providers: map[string]ResourceProviderFactory{
  1960  			"aws": testProviderFuncFixed(p),
  1961  		},
  1962  		Provisioners: map[string]ResourceProvisionerFactory{
  1963  			"shell": testProvisionerFuncFixed(pr),
  1964  		},
  1965  	})
  1966  
  1967  	if _, err := ctx.Plan(); err != nil {
  1968  		t.Fatalf("err: %s", err)
  1969  	}
  1970  
  1971  	state, err := ctx.Apply()
  1972  	if err != nil {
  1973  		t.Fatalf("err: %s", err)
  1974  	}
  1975  
  1976  	actual := strings.TrimSpace(state.String())
  1977  	expected := strings.TrimSpace(testTerraformApplyProvisionerMultiSelfRefStr)
  1978  	if actual != expected {
  1979  		t.Fatalf("bad: \n%s", actual)
  1980  	}
  1981  
  1982  	// Verify apply was invoked
  1983  	if !pr.ApplyCalled {
  1984  		t.Fatalf("provisioner not invoked")
  1985  	}
  1986  
  1987  	// Verify our result
  1988  	sort.Strings(commands)
  1989  	expectedCommands := []string{"number 0", "number 1", "number 2"}
  1990  	if !reflect.DeepEqual(commands, expectedCommands) {
  1991  		t.Fatalf("bad: %#v", commands)
  1992  	}
  1993  }
  1994  
  1995  // Provisioner should NOT run on a diff, only create
  1996  func TestContext2Apply_Provisioner_Diff(t *testing.T) {
  1997  	m := testModule(t, "apply-provisioner-diff")
  1998  	p := testProvider("aws")
  1999  	pr := testProvisioner()
  2000  	p.ApplyFn = testApplyFn
  2001  	p.DiffFn = testDiffFn
  2002  	pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error {
  2003  		return nil
  2004  	}
  2005  	ctx := testContext2(t, &ContextOpts{
  2006  		Module: m,
  2007  		Providers: map[string]ResourceProviderFactory{
  2008  			"aws": testProviderFuncFixed(p),
  2009  		},
  2010  		Provisioners: map[string]ResourceProvisionerFactory{
  2011  			"shell": testProvisionerFuncFixed(pr),
  2012  		},
  2013  	})
  2014  
  2015  	if _, err := ctx.Plan(); err != nil {
  2016  		t.Fatalf("err: %s", err)
  2017  	}
  2018  
  2019  	state, err := ctx.Apply()
  2020  	if err != nil {
  2021  		t.Fatalf("err: %s", err)
  2022  	}
  2023  
  2024  	actual := strings.TrimSpace(state.String())
  2025  	expected := strings.TrimSpace(testTerraformApplyProvisionerDiffStr)
  2026  	if actual != expected {
  2027  		t.Fatalf("bad: \n%s", actual)
  2028  	}
  2029  
  2030  	// Verify apply was invoked
  2031  	if !pr.ApplyCalled {
  2032  		t.Fatalf("provisioner not invoked")
  2033  	}
  2034  	pr.ApplyCalled = false
  2035  
  2036  	// Change the state to force a diff
  2037  	mod := state.RootModule()
  2038  	mod.Resources["aws_instance.bar"].Primary.Attributes["foo"] = "baz"
  2039  
  2040  	// Re-create context with state
  2041  	ctx = testContext2(t, &ContextOpts{
  2042  		Module: m,
  2043  		Providers: map[string]ResourceProviderFactory{
  2044  			"aws": testProviderFuncFixed(p),
  2045  		},
  2046  		Provisioners: map[string]ResourceProvisionerFactory{
  2047  			"shell": testProvisionerFuncFixed(pr),
  2048  		},
  2049  		State: state,
  2050  	})
  2051  
  2052  	if _, err := ctx.Plan(); err != nil {
  2053  		t.Fatalf("err: %s", err)
  2054  	}
  2055  
  2056  	state2, err := ctx.Apply()
  2057  	if err != nil {
  2058  		t.Fatalf("err: %s", err)
  2059  	}
  2060  
  2061  	actual = strings.TrimSpace(state2.String())
  2062  	if actual != expected {
  2063  		t.Fatalf("bad: \n%s", actual)
  2064  	}
  2065  
  2066  	// Verify apply was NOT invoked
  2067  	if pr.ApplyCalled {
  2068  		t.Fatalf("provisioner invoked")
  2069  	}
  2070  }
  2071  
  2072  func TestContext2Apply_outputDiffVars(t *testing.T) {
  2073  	m := testModule(t, "apply-good")
  2074  	p := testProvider("aws")
  2075  	s := &State{
  2076  		Modules: []*ModuleState{
  2077  			&ModuleState{
  2078  				Path: rootModulePath,
  2079  				Resources: map[string]*ResourceState{
  2080  					"aws_instance.baz": &ResourceState{
  2081  						Type: "aws_instance",
  2082  						Primary: &InstanceState{
  2083  							ID: "bar",
  2084  						},
  2085  					},
  2086  				},
  2087  			},
  2088  		},
  2089  	}
  2090  	ctx := testContext2(t, &ContextOpts{
  2091  		Module: m,
  2092  		Providers: map[string]ResourceProviderFactory{
  2093  			"aws": testProviderFuncFixed(p),
  2094  		},
  2095  		State: s,
  2096  	})
  2097  
  2098  	p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) {
  2099  		for k, ad := range d.Attributes {
  2100  			if ad.NewComputed {
  2101  				return nil, fmt.Errorf("%s: computed", k)
  2102  			}
  2103  		}
  2104  
  2105  		result := s.MergeDiff(d)
  2106  		result.ID = "foo"
  2107  		return result, nil
  2108  	}
  2109  	p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) {
  2110  		return &InstanceDiff{
  2111  			Attributes: map[string]*ResourceAttrDiff{
  2112  				"foo": &ResourceAttrDiff{
  2113  					NewComputed: true,
  2114  					Type:        DiffAttrOutput,
  2115  				},
  2116  				"bar": &ResourceAttrDiff{
  2117  					New: "baz",
  2118  				},
  2119  			},
  2120  		}, nil
  2121  	}
  2122  
  2123  	if _, err := ctx.Plan(); err != nil {
  2124  		t.Fatalf("err: %s", err)
  2125  	}
  2126  	if _, err := ctx.Apply(); err != nil {
  2127  		t.Fatalf("err: %s", err)
  2128  	}
  2129  }
  2130  
  2131  func TestContext2Apply_Provisioner_ConnInfo(t *testing.T) {
  2132  	m := testModule(t, "apply-provisioner-conninfo")
  2133  	p := testProvider("aws")
  2134  	pr := testProvisioner()
  2135  
  2136  	p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) {
  2137  		if s.Ephemeral.ConnInfo == nil {
  2138  			t.Fatalf("ConnInfo not initialized")
  2139  		}
  2140  
  2141  		result, _ := testApplyFn(info, s, d)
  2142  		result.Ephemeral.ConnInfo = map[string]string{
  2143  			"type": "ssh",
  2144  			"host": "127.0.0.1",
  2145  			"port": "22",
  2146  		}
  2147  		return result, nil
  2148  	}
  2149  	p.DiffFn = testDiffFn
  2150  
  2151  	pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error {
  2152  		conn := rs.Ephemeral.ConnInfo
  2153  		if conn["type"] != "telnet" {
  2154  			t.Fatalf("Bad: %#v", conn)
  2155  		}
  2156  		if conn["host"] != "127.0.0.1" {
  2157  			t.Fatalf("Bad: %#v", conn)
  2158  		}
  2159  		if conn["port"] != "2222" {
  2160  			t.Fatalf("Bad: %#v", conn)
  2161  		}
  2162  		if conn["user"] != "superuser" {
  2163  			t.Fatalf("Bad: %#v", conn)
  2164  		}
  2165  		if conn["pass"] != "test" {
  2166  			t.Fatalf("Bad: %#v", conn)
  2167  		}
  2168  
  2169  		return nil
  2170  	}
  2171  
  2172  	ctx := testContext2(t, &ContextOpts{
  2173  		Module: m,
  2174  		Providers: map[string]ResourceProviderFactory{
  2175  			"aws": testProviderFuncFixed(p),
  2176  		},
  2177  		Provisioners: map[string]ResourceProvisionerFactory{
  2178  			"shell": testProvisionerFuncFixed(pr),
  2179  		},
  2180  		Variables: map[string]string{
  2181  			"value": "1",
  2182  			"pass":  "test",
  2183  		},
  2184  	})
  2185  
  2186  	if _, err := ctx.Plan(); err != nil {
  2187  		t.Fatalf("err: %s", err)
  2188  	}
  2189  
  2190  	state, err := ctx.Apply()
  2191  	if err != nil {
  2192  		t.Fatalf("err: %s", err)
  2193  	}
  2194  
  2195  	actual := strings.TrimSpace(state.String())
  2196  	expected := strings.TrimSpace(testTerraformApplyProvisionerStr)
  2197  	if actual != expected {
  2198  		t.Fatalf("bad: \n%s", actual)
  2199  	}
  2200  
  2201  	// Verify apply was invoked
  2202  	if !pr.ApplyCalled {
  2203  		t.Fatalf("provisioner not invoked")
  2204  	}
  2205  }
  2206  
  2207  func TestContext2Apply_destroy(t *testing.T) {
  2208  	m := testModule(t, "apply-destroy")
  2209  	h := new(HookRecordApplyOrder)
  2210  	p := testProvider("aws")
  2211  	p.ApplyFn = testApplyFn
  2212  	p.DiffFn = testDiffFn
  2213  	ctx := testContext2(t, &ContextOpts{
  2214  		Module: m,
  2215  		Hooks:  []Hook{h},
  2216  		Providers: map[string]ResourceProviderFactory{
  2217  			"aws": testProviderFuncFixed(p),
  2218  		},
  2219  	})
  2220  
  2221  	// First plan and apply a create operation
  2222  	if _, err := ctx.Plan(); err != nil {
  2223  		t.Fatalf("err: %s", err)
  2224  	}
  2225  
  2226  	state, err := ctx.Apply()
  2227  	if err != nil {
  2228  		t.Fatalf("err: %s", err)
  2229  	}
  2230  
  2231  	// Next, plan and apply a destroy operation
  2232  	h.Active = true
  2233  	ctx = testContext2(t, &ContextOpts{
  2234  		Destroy: true,
  2235  		State:   state,
  2236  		Module:  m,
  2237  		Hooks:   []Hook{h},
  2238  		Providers: map[string]ResourceProviderFactory{
  2239  			"aws": testProviderFuncFixed(p),
  2240  		},
  2241  	})
  2242  
  2243  	if _, err := ctx.Plan(); err != nil {
  2244  		t.Fatalf("err: %s", err)
  2245  	}
  2246  
  2247  	state, err = ctx.Apply()
  2248  	if err != nil {
  2249  		t.Fatalf("err: %s", err)
  2250  	}
  2251  
  2252  	// Test that things were destroyed
  2253  	actual := strings.TrimSpace(state.String())
  2254  	expected := strings.TrimSpace(testTerraformApplyDestroyStr)
  2255  	if actual != expected {
  2256  		t.Fatalf("bad: \n%s", actual)
  2257  	}
  2258  
  2259  	// Test that things were destroyed _in the right order_
  2260  	expected2 := []string{"aws_instance.bar", "aws_instance.foo"}
  2261  	actual2 := h.IDs
  2262  	if !reflect.DeepEqual(actual2, expected2) {
  2263  		t.Fatalf("expected: %#v\n\ngot:%#v", expected2, actual2)
  2264  	}
  2265  }
  2266  
  2267  func TestContext2Apply_destroyNestedModule(t *testing.T) {
  2268  	m := testModule(t, "apply-destroy-nested-module")
  2269  	p := testProvider("aws")
  2270  	p.ApplyFn = testApplyFn
  2271  	p.DiffFn = testDiffFn
  2272  
  2273  	s := &State{
  2274  		Modules: []*ModuleState{
  2275  			&ModuleState{
  2276  				Path: []string{"root", "child", "subchild"},
  2277  				Resources: map[string]*ResourceState{
  2278  					"aws_instance.bar": &ResourceState{
  2279  						Type: "aws_instance",
  2280  						Primary: &InstanceState{
  2281  							ID: "bar",
  2282  						},
  2283  					},
  2284  				},
  2285  			},
  2286  		},
  2287  	}
  2288  
  2289  	ctx := testContext2(t, &ContextOpts{
  2290  		Module: m,
  2291  		Providers: map[string]ResourceProviderFactory{
  2292  			"aws": testProviderFuncFixed(p),
  2293  		},
  2294  		State: s,
  2295  	})
  2296  
  2297  	// First plan and apply a create operation
  2298  	if _, err := ctx.Plan(); err != nil {
  2299  		t.Fatalf("err: %s", err)
  2300  	}
  2301  
  2302  	state, err := ctx.Apply()
  2303  	if err != nil {
  2304  		t.Fatalf("err: %s", err)
  2305  	}
  2306  
  2307  	// Test that things were destroyed
  2308  	actual := strings.TrimSpace(state.String())
  2309  	expected := strings.TrimSpace(testTerraformApplyDestroyNestedModuleStr)
  2310  	if actual != expected {
  2311  		t.Fatalf("bad: \n%s", actual)
  2312  	}
  2313  }
  2314  
  2315  func TestContext2Apply_destroyDeeplyNestedModule(t *testing.T) {
  2316  	m := testModule(t, "apply-destroy-deeply-nested-module")
  2317  	p := testProvider("aws")
  2318  	p.ApplyFn = testApplyFn
  2319  	p.DiffFn = testDiffFn
  2320  
  2321  	s := &State{
  2322  		Modules: []*ModuleState{
  2323  			&ModuleState{
  2324  				Path: []string{"root", "child", "subchild", "subsubchild"},
  2325  				Resources: map[string]*ResourceState{
  2326  					"aws_instance.bar": &ResourceState{
  2327  						Type: "aws_instance",
  2328  						Primary: &InstanceState{
  2329  							ID: "bar",
  2330  						},
  2331  					},
  2332  				},
  2333  			},
  2334  		},
  2335  	}
  2336  
  2337  	ctx := testContext2(t, &ContextOpts{
  2338  		Module: m,
  2339  		Providers: map[string]ResourceProviderFactory{
  2340  			"aws": testProviderFuncFixed(p),
  2341  		},
  2342  		State: s,
  2343  	})
  2344  
  2345  	// First plan and apply a create operation
  2346  	if _, err := ctx.Plan(); err != nil {
  2347  		t.Fatalf("err: %s", err)
  2348  	}
  2349  
  2350  	state, err := ctx.Apply()
  2351  	if err != nil {
  2352  		t.Fatalf("err: %s", err)
  2353  	}
  2354  
  2355  	// Test that things were destroyed
  2356  	actual := strings.TrimSpace(state.String())
  2357  	expected := strings.TrimSpace(`
  2358  module.child.subchild.subsubchild:
  2359    <no state>
  2360  	`)
  2361  	if actual != expected {
  2362  		t.Fatalf("bad: \n%s", actual)
  2363  	}
  2364  }
  2365  
  2366  func TestContext2Apply_destroyOutputs(t *testing.T) {
  2367  	m := testModule(t, "apply-destroy-outputs")
  2368  	h := new(HookRecordApplyOrder)
  2369  	p := testProvider("aws")
  2370  	p.ApplyFn = testApplyFn
  2371  	p.DiffFn = testDiffFn
  2372  	ctx := testContext2(t, &ContextOpts{
  2373  		Module: m,
  2374  		Hooks:  []Hook{h},
  2375  		Providers: map[string]ResourceProviderFactory{
  2376  			"aws": testProviderFuncFixed(p),
  2377  		},
  2378  	})
  2379  
  2380  	// First plan and apply a create operation
  2381  	if _, err := ctx.Plan(); err != nil {
  2382  		t.Fatalf("err: %s", err)
  2383  	}
  2384  
  2385  	state, err := ctx.Apply()
  2386  
  2387  	if err != nil {
  2388  		t.Fatalf("err: %s", err)
  2389  	}
  2390  
  2391  	// Next, plan and apply a destroy operation
  2392  	h.Active = true
  2393  	ctx = testContext2(t, &ContextOpts{
  2394  		Destroy: true,
  2395  		State:   state,
  2396  		Module:  m,
  2397  		Hooks:   []Hook{h},
  2398  		Providers: map[string]ResourceProviderFactory{
  2399  			"aws": testProviderFuncFixed(p),
  2400  		},
  2401  	})
  2402  
  2403  	if _, err := ctx.Plan(); err != nil {
  2404  		t.Fatalf("err: %s", err)
  2405  	}
  2406  
  2407  	state, err = ctx.Apply()
  2408  	if err != nil {
  2409  		t.Fatalf("err: %s", err)
  2410  	}
  2411  
  2412  	mod := state.RootModule()
  2413  	if len(mod.Resources) > 0 {
  2414  		t.Fatalf("bad: %#v", mod)
  2415  	}
  2416  }
  2417  
  2418  func TestContext2Apply_destroyOrphan(t *testing.T) {
  2419  	m := testModule(t, "apply-error")
  2420  	p := testProvider("aws")
  2421  	s := &State{
  2422  		Modules: []*ModuleState{
  2423  			&ModuleState{
  2424  				Path: rootModulePath,
  2425  				Resources: map[string]*ResourceState{
  2426  					"aws_instance.baz": &ResourceState{
  2427  						Type: "aws_instance",
  2428  						Primary: &InstanceState{
  2429  							ID: "bar",
  2430  						},
  2431  					},
  2432  				},
  2433  			},
  2434  		},
  2435  	}
  2436  	ctx := testContext2(t, &ContextOpts{
  2437  		Module: m,
  2438  		Providers: map[string]ResourceProviderFactory{
  2439  			"aws": testProviderFuncFixed(p),
  2440  		},
  2441  		State: s,
  2442  	})
  2443  
  2444  	p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) {
  2445  		if d.Destroy {
  2446  			return nil, nil
  2447  		}
  2448  
  2449  		result := s.MergeDiff(d)
  2450  		result.ID = "foo"
  2451  		return result, nil
  2452  	}
  2453  	p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) {
  2454  		return &InstanceDiff{
  2455  			Attributes: map[string]*ResourceAttrDiff{
  2456  				"num": &ResourceAttrDiff{
  2457  					New: "bar",
  2458  				},
  2459  			},
  2460  		}, nil
  2461  	}
  2462  
  2463  	if _, err := ctx.Plan(); err != nil {
  2464  		t.Fatalf("err: %s", err)
  2465  	}
  2466  
  2467  	state, err := ctx.Apply()
  2468  	if err != nil {
  2469  		t.Fatalf("err: %s", err)
  2470  	}
  2471  
  2472  	mod := state.RootModule()
  2473  	if _, ok := mod.Resources["aws_instance.baz"]; ok {
  2474  		t.Fatalf("bad: %#v", mod.Resources)
  2475  	}
  2476  }
  2477  
  2478  func TestContext2Apply_destroyTaintedProvisioner(t *testing.T) {
  2479  	m := testModule(t, "apply-destroy-provisioner")
  2480  	p := testProvider("aws")
  2481  	pr := testProvisioner()
  2482  	p.ApplyFn = testApplyFn
  2483  	p.DiffFn = testDiffFn
  2484  
  2485  	called := false
  2486  	pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error {
  2487  		called = true
  2488  		return nil
  2489  	}
  2490  
  2491  	s := &State{
  2492  		Modules: []*ModuleState{
  2493  			&ModuleState{
  2494  				Path: rootModulePath,
  2495  				Resources: map[string]*ResourceState{
  2496  					"aws_instance.foo": &ResourceState{
  2497  						Type: "aws_instance",
  2498  						Tainted: []*InstanceState{
  2499  							&InstanceState{
  2500  								ID: "bar",
  2501  								Attributes: map[string]string{
  2502  									"id": "bar",
  2503  								},
  2504  							},
  2505  						},
  2506  					},
  2507  				},
  2508  			},
  2509  		},
  2510  	}
  2511  
  2512  	ctx := testContext2(t, &ContextOpts{
  2513  		Module: m,
  2514  		Providers: map[string]ResourceProviderFactory{
  2515  			"aws": testProviderFuncFixed(p),
  2516  		},
  2517  		Provisioners: map[string]ResourceProvisionerFactory{
  2518  			"shell": testProvisionerFuncFixed(pr),
  2519  		},
  2520  		State:   s,
  2521  		Destroy: true,
  2522  	})
  2523  
  2524  	if _, err := ctx.Plan(); err != nil {
  2525  		t.Fatalf("err: %s", err)
  2526  	}
  2527  
  2528  	state, err := ctx.Apply()
  2529  	if err != nil {
  2530  		t.Fatalf("err: %s", err)
  2531  	}
  2532  
  2533  	if called {
  2534  		t.Fatal("provisioner should not be called")
  2535  	}
  2536  
  2537  	actual := strings.TrimSpace(state.String())
  2538  	expected := strings.TrimSpace("<no state>")
  2539  	if actual != expected {
  2540  		t.Fatalf("bad: \n%s", actual)
  2541  	}
  2542  }
  2543  
  2544  func TestContext2Apply_error(t *testing.T) {
  2545  	errored := false
  2546  
  2547  	m := testModule(t, "apply-error")
  2548  	p := testProvider("aws")
  2549  	ctx := testContext2(t, &ContextOpts{
  2550  		Module: m,
  2551  		Providers: map[string]ResourceProviderFactory{
  2552  			"aws": testProviderFuncFixed(p),
  2553  		},
  2554  	})
  2555  
  2556  	p.ApplyFn = func(*InstanceInfo, *InstanceState, *InstanceDiff) (*InstanceState, error) {
  2557  		if errored {
  2558  			state := &InstanceState{
  2559  				ID: "bar",
  2560  			}
  2561  			return state, fmt.Errorf("error")
  2562  		}
  2563  		errored = true
  2564  
  2565  		return &InstanceState{
  2566  			ID: "foo",
  2567  			Attributes: map[string]string{
  2568  				"num": "2",
  2569  			},
  2570  		}, nil
  2571  	}
  2572  	p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) {
  2573  		return &InstanceDiff{
  2574  			Attributes: map[string]*ResourceAttrDiff{
  2575  				"num": &ResourceAttrDiff{
  2576  					New: "bar",
  2577  				},
  2578  			},
  2579  		}, nil
  2580  	}
  2581  
  2582  	if _, err := ctx.Plan(); err != nil {
  2583  		t.Fatalf("err: %s", err)
  2584  	}
  2585  
  2586  	state, err := ctx.Apply()
  2587  	if err == nil {
  2588  		t.Fatal("should have error")
  2589  	}
  2590  
  2591  	actual := strings.TrimSpace(state.String())
  2592  	expected := strings.TrimSpace(testTerraformApplyErrorStr)
  2593  	if actual != expected {
  2594  		t.Fatalf("bad: \n%s", actual)
  2595  	}
  2596  }
  2597  
  2598  func TestContext2Apply_errorPartial(t *testing.T) {
  2599  	errored := false
  2600  
  2601  	m := testModule(t, "apply-error")
  2602  	p := testProvider("aws")
  2603  	s := &State{
  2604  		Modules: []*ModuleState{
  2605  			&ModuleState{
  2606  				Path: rootModulePath,
  2607  				Resources: map[string]*ResourceState{
  2608  					"aws_instance.bar": &ResourceState{
  2609  						Type: "aws_instance",
  2610  						Primary: &InstanceState{
  2611  							ID: "bar",
  2612  						},
  2613  					},
  2614  				},
  2615  			},
  2616  		},
  2617  	}
  2618  	ctx := testContext2(t, &ContextOpts{
  2619  		Module: m,
  2620  		Providers: map[string]ResourceProviderFactory{
  2621  			"aws": testProviderFuncFixed(p),
  2622  		},
  2623  		State: s,
  2624  	})
  2625  
  2626  	p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) {
  2627  		if errored {
  2628  			return s, fmt.Errorf("error")
  2629  		}
  2630  		errored = true
  2631  
  2632  		return &InstanceState{
  2633  			ID: "foo",
  2634  			Attributes: map[string]string{
  2635  				"num": "2",
  2636  			},
  2637  		}, nil
  2638  	}
  2639  	p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) {
  2640  		return &InstanceDiff{
  2641  			Attributes: map[string]*ResourceAttrDiff{
  2642  				"num": &ResourceAttrDiff{
  2643  					New: "bar",
  2644  				},
  2645  			},
  2646  		}, nil
  2647  	}
  2648  
  2649  	if _, err := ctx.Plan(); err != nil {
  2650  		t.Fatalf("err: %s", err)
  2651  	}
  2652  
  2653  	state, err := ctx.Apply()
  2654  	if err == nil {
  2655  		t.Fatal("should have error")
  2656  	}
  2657  
  2658  	mod := state.RootModule()
  2659  	if len(mod.Resources) != 2 {
  2660  		t.Fatalf("bad: %#v", mod.Resources)
  2661  	}
  2662  
  2663  	actual := strings.TrimSpace(state.String())
  2664  	expected := strings.TrimSpace(testTerraformApplyErrorPartialStr)
  2665  	if actual != expected {
  2666  		t.Fatalf("bad: \n%s", actual)
  2667  	}
  2668  }
  2669  
  2670  func TestContext2Apply_hook(t *testing.T) {
  2671  	m := testModule(t, "apply-good")
  2672  	h := new(MockHook)
  2673  	p := testProvider("aws")
  2674  	p.ApplyFn = testApplyFn
  2675  	p.DiffFn = testDiffFn
  2676  	ctx := testContext2(t, &ContextOpts{
  2677  		Module: m,
  2678  		Hooks:  []Hook{h},
  2679  		Providers: map[string]ResourceProviderFactory{
  2680  			"aws": testProviderFuncFixed(p),
  2681  		},
  2682  	})
  2683  
  2684  	if _, err := ctx.Plan(); err != nil {
  2685  		t.Fatalf("err: %s", err)
  2686  	}
  2687  
  2688  	if _, err := ctx.Apply(); err != nil {
  2689  		t.Fatalf("err: %s", err)
  2690  	}
  2691  
  2692  	if !h.PreApplyCalled {
  2693  		t.Fatal("should be called")
  2694  	}
  2695  	if !h.PostApplyCalled {
  2696  		t.Fatal("should be called")
  2697  	}
  2698  	if !h.PostStateUpdateCalled {
  2699  		t.Fatalf("should call post state update")
  2700  	}
  2701  }
  2702  
  2703  func TestContext2Apply_hookOrphan(t *testing.T) {
  2704  	m := testModule(t, "apply-blank")
  2705  	h := new(MockHook)
  2706  	p := testProvider("aws")
  2707  	p.ApplyFn = testApplyFn
  2708  	p.DiffFn = testDiffFn
  2709  
  2710  	state := &State{
  2711  		Modules: []*ModuleState{
  2712  			&ModuleState{
  2713  				Path: rootModulePath,
  2714  				Resources: map[string]*ResourceState{
  2715  					"aws_instance.bar": &ResourceState{
  2716  						Type: "aws_instance",
  2717  						Primary: &InstanceState{
  2718  							ID: "bar",
  2719  						},
  2720  					},
  2721  				},
  2722  			},
  2723  		},
  2724  	}
  2725  
  2726  	ctx := testContext2(t, &ContextOpts{
  2727  		Module: m,
  2728  		State:  state,
  2729  		Hooks:  []Hook{h},
  2730  		Providers: map[string]ResourceProviderFactory{
  2731  			"aws": testProviderFuncFixed(p),
  2732  		},
  2733  	})
  2734  
  2735  	if _, err := ctx.Plan(); err != nil {
  2736  		t.Fatalf("err: %s", err)
  2737  	}
  2738  
  2739  	if _, err := ctx.Apply(); err != nil {
  2740  		t.Fatalf("err: %s", err)
  2741  	}
  2742  
  2743  	if !h.PreApplyCalled {
  2744  		t.Fatal("should be called")
  2745  	}
  2746  	if !h.PostApplyCalled {
  2747  		t.Fatal("should be called")
  2748  	}
  2749  	if !h.PostStateUpdateCalled {
  2750  		t.Fatalf("should call post state update")
  2751  	}
  2752  }
  2753  
  2754  func TestContext2Apply_idAttr(t *testing.T) {
  2755  	m := testModule(t, "apply-idattr")
  2756  	p := testProvider("aws")
  2757  	ctx := testContext2(t, &ContextOpts{
  2758  		Module: m,
  2759  		Providers: map[string]ResourceProviderFactory{
  2760  			"aws": testProviderFuncFixed(p),
  2761  		},
  2762  	})
  2763  
  2764  	p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) {
  2765  		result := s.MergeDiff(d)
  2766  		result.ID = "foo"
  2767  		result.Attributes = map[string]string{
  2768  			"id": "bar",
  2769  		}
  2770  
  2771  		return result, nil
  2772  	}
  2773  	p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) {
  2774  		return &InstanceDiff{
  2775  			Attributes: map[string]*ResourceAttrDiff{
  2776  				"num": &ResourceAttrDiff{
  2777  					New: "bar",
  2778  				},
  2779  			},
  2780  		}, nil
  2781  	}
  2782  
  2783  	if _, err := ctx.Plan(); err != nil {
  2784  		t.Fatalf("err: %s", err)
  2785  	}
  2786  
  2787  	state, err := ctx.Apply()
  2788  	if err != nil {
  2789  		t.Fatalf("err: %s", err)
  2790  	}
  2791  
  2792  	mod := state.RootModule()
  2793  	rs, ok := mod.Resources["aws_instance.foo"]
  2794  	if !ok {
  2795  		t.Fatal("not in state")
  2796  	}
  2797  	if rs.Primary.ID != "foo" {
  2798  		t.Fatalf("bad: %#v", rs.Primary.ID)
  2799  	}
  2800  	if rs.Primary.Attributes["id"] != "foo" {
  2801  		t.Fatalf("bad: %#v", rs.Primary.Attributes)
  2802  	}
  2803  }
  2804  
  2805  func TestContext2Apply_output(t *testing.T) {
  2806  	m := testModule(t, "apply-output")
  2807  	p := testProvider("aws")
  2808  	p.ApplyFn = testApplyFn
  2809  	p.DiffFn = testDiffFn
  2810  	ctx := testContext2(t, &ContextOpts{
  2811  		Module: m,
  2812  		Providers: map[string]ResourceProviderFactory{
  2813  			"aws": testProviderFuncFixed(p),
  2814  		},
  2815  	})
  2816  
  2817  	if _, err := ctx.Plan(); err != nil {
  2818  		t.Fatalf("err: %s", err)
  2819  	}
  2820  
  2821  	state, err := ctx.Apply()
  2822  	if err != nil {
  2823  		t.Fatalf("err: %s", err)
  2824  	}
  2825  
  2826  	actual := strings.TrimSpace(state.String())
  2827  	expected := strings.TrimSpace(testTerraformApplyOutputStr)
  2828  	if actual != expected {
  2829  		t.Fatalf("bad: \n%s", actual)
  2830  	}
  2831  }
  2832  
  2833  func TestContext2Apply_outputInvalid(t *testing.T) {
  2834  	m := testModule(t, "apply-output-invalid")
  2835  	p := testProvider("aws")
  2836  	p.ApplyFn = testApplyFn
  2837  	p.DiffFn = testDiffFn
  2838  	ctx := testContext2(t, &ContextOpts{
  2839  		Module: m,
  2840  		Providers: map[string]ResourceProviderFactory{
  2841  			"aws": testProviderFuncFixed(p),
  2842  		},
  2843  	})
  2844  
  2845  	_, err := ctx.Plan()
  2846  	if err == nil {
  2847  		t.Fatalf("err: %s", err)
  2848  	}
  2849  	if !strings.Contains(err.Error(), "is not a string") {
  2850  		t.Fatalf("err: %s", err)
  2851  	}
  2852  }
  2853  
  2854  func TestContext2Apply_outputList(t *testing.T) {
  2855  	m := testModule(t, "apply-output-list")
  2856  	p := testProvider("aws")
  2857  	p.ApplyFn = testApplyFn
  2858  	p.DiffFn = testDiffFn
  2859  	ctx := testContext2(t, &ContextOpts{
  2860  		Module: m,
  2861  		Providers: map[string]ResourceProviderFactory{
  2862  			"aws": testProviderFuncFixed(p),
  2863  		},
  2864  	})
  2865  
  2866  	if _, err := ctx.Plan(); err != nil {
  2867  		t.Fatalf("err: %s", err)
  2868  	}
  2869  
  2870  	state, err := ctx.Apply()
  2871  	if err != nil {
  2872  		t.Fatalf("err: %s", err)
  2873  	}
  2874  
  2875  	actual := strings.TrimSpace(state.String())
  2876  	expected := strings.TrimSpace(testTerraformApplyOutputListStr)
  2877  	if actual != expected {
  2878  		t.Fatalf("bad: \n%s", actual)
  2879  	}
  2880  }
  2881  
  2882  func TestContext2Apply_outputMulti(t *testing.T) {
  2883  	m := testModule(t, "apply-output-multi")
  2884  	p := testProvider("aws")
  2885  	p.ApplyFn = testApplyFn
  2886  	p.DiffFn = testDiffFn
  2887  	ctx := testContext2(t, &ContextOpts{
  2888  		Module: m,
  2889  		Providers: map[string]ResourceProviderFactory{
  2890  			"aws": testProviderFuncFixed(p),
  2891  		},
  2892  	})
  2893  
  2894  	if _, err := ctx.Plan(); err != nil {
  2895  		t.Fatalf("err: %s", err)
  2896  	}
  2897  
  2898  	state, err := ctx.Apply()
  2899  	if err != nil {
  2900  		t.Fatalf("err: %s", err)
  2901  	}
  2902  
  2903  	actual := strings.TrimSpace(state.String())
  2904  	expected := strings.TrimSpace(testTerraformApplyOutputMultiStr)
  2905  	if actual != expected {
  2906  		t.Fatalf("bad: \n%s", actual)
  2907  	}
  2908  }
  2909  
  2910  func TestContext2Apply_outputMultiIndex(t *testing.T) {
  2911  	m := testModule(t, "apply-output-multi-index")
  2912  	p := testProvider("aws")
  2913  	p.ApplyFn = testApplyFn
  2914  	p.DiffFn = testDiffFn
  2915  	ctx := testContext2(t, &ContextOpts{
  2916  		Module: m,
  2917  		Providers: map[string]ResourceProviderFactory{
  2918  			"aws": testProviderFuncFixed(p),
  2919  		},
  2920  	})
  2921  
  2922  	if _, err := ctx.Plan(); err != nil {
  2923  		t.Fatalf("err: %s", err)
  2924  	}
  2925  
  2926  	state, err := ctx.Apply()
  2927  	if err != nil {
  2928  		t.Fatalf("err: %s", err)
  2929  	}
  2930  
  2931  	actual := strings.TrimSpace(state.String())
  2932  	expected := strings.TrimSpace(testTerraformApplyOutputMultiIndexStr)
  2933  	if actual != expected {
  2934  		t.Fatalf("bad: \n%s", actual)
  2935  	}
  2936  }
  2937  
  2938  func TestContext2Apply_taint(t *testing.T) {
  2939  	m := testModule(t, "apply-taint")
  2940  	p := testProvider("aws")
  2941  
  2942  	// destroyCount tests against regression of
  2943  	// https://github.com/hashicorp/terraform/issues/1056
  2944  	var destroyCount = int32(0)
  2945  	var once sync.Once
  2946  	simulateProviderDelay := func() {
  2947  		time.Sleep(10 * time.Millisecond)
  2948  	}
  2949  
  2950  	p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) {
  2951  		once.Do(simulateProviderDelay)
  2952  		if d.Destroy {
  2953  			atomic.AddInt32(&destroyCount, 1)
  2954  		}
  2955  		return testApplyFn(info, s, d)
  2956  	}
  2957  	p.DiffFn = testDiffFn
  2958  	s := &State{
  2959  		Modules: []*ModuleState{
  2960  			&ModuleState{
  2961  				Path: rootModulePath,
  2962  				Resources: map[string]*ResourceState{
  2963  					"aws_instance.bar": &ResourceState{
  2964  						Type: "aws_instance",
  2965  						Tainted: []*InstanceState{
  2966  							&InstanceState{
  2967  								ID: "baz",
  2968  								Attributes: map[string]string{
  2969  									"num":  "2",
  2970  									"type": "aws_instance",
  2971  								},
  2972  							},
  2973  						},
  2974  					},
  2975  				},
  2976  			},
  2977  		},
  2978  	}
  2979  	ctx := testContext2(t, &ContextOpts{
  2980  		Module: m,
  2981  		Providers: map[string]ResourceProviderFactory{
  2982  			"aws": testProviderFuncFixed(p),
  2983  		},
  2984  		State: s,
  2985  	})
  2986  
  2987  	if _, err := ctx.Plan(); err != nil {
  2988  		t.Fatalf("err: %s", err)
  2989  	}
  2990  
  2991  	state, err := ctx.Apply()
  2992  	if err != nil {
  2993  		t.Fatalf("err: %s", err)
  2994  	}
  2995  
  2996  	actual := strings.TrimSpace(state.String())
  2997  	expected := strings.TrimSpace(testTerraformApplyTaintStr)
  2998  	if actual != expected {
  2999  		t.Fatalf("bad:\n%s", actual)
  3000  	}
  3001  
  3002  	if destroyCount != 1 {
  3003  		t.Fatalf("Expected 1 destroy, got %d", destroyCount)
  3004  	}
  3005  }
  3006  
  3007  func TestContext2Apply_taintDep(t *testing.T) {
  3008  	m := testModule(t, "apply-taint-dep")
  3009  	p := testProvider("aws")
  3010  	p.ApplyFn = testApplyFn
  3011  	p.DiffFn = testDiffFn
  3012  	s := &State{
  3013  		Modules: []*ModuleState{
  3014  			&ModuleState{
  3015  				Path: rootModulePath,
  3016  				Resources: map[string]*ResourceState{
  3017  					"aws_instance.foo": &ResourceState{
  3018  						Type: "aws_instance",
  3019  						Tainted: []*InstanceState{
  3020  							&InstanceState{
  3021  								ID: "baz",
  3022  								Attributes: map[string]string{
  3023  									"num":  "2",
  3024  									"type": "aws_instance",
  3025  								},
  3026  							},
  3027  						},
  3028  					},
  3029  					"aws_instance.bar": &ResourceState{
  3030  						Type: "aws_instance",
  3031  						Primary: &InstanceState{
  3032  							ID: "bar",
  3033  							Attributes: map[string]string{
  3034  								"foo":  "baz",
  3035  								"num":  "2",
  3036  								"type": "aws_instance",
  3037  							},
  3038  						},
  3039  					},
  3040  				},
  3041  			},
  3042  		},
  3043  	}
  3044  	ctx := testContext2(t, &ContextOpts{
  3045  		Module: m,
  3046  		Providers: map[string]ResourceProviderFactory{
  3047  			"aws": testProviderFuncFixed(p),
  3048  		},
  3049  		State: s,
  3050  	})
  3051  
  3052  	if p, err := ctx.Plan(); err != nil {
  3053  		t.Fatalf("err: %s", err)
  3054  	} else {
  3055  		t.Logf("plan: %s", p)
  3056  	}
  3057  
  3058  	state, err := ctx.Apply()
  3059  	if err != nil {
  3060  		t.Fatalf("err: %s", err)
  3061  	}
  3062  
  3063  	actual := strings.TrimSpace(state.String())
  3064  	expected := strings.TrimSpace(testTerraformApplyTaintDepStr)
  3065  	if actual != expected {
  3066  		t.Fatalf("bad:\n%s", actual)
  3067  	}
  3068  }
  3069  
  3070  func TestContext2Apply_taintDepRequiresNew(t *testing.T) {
  3071  	m := testModule(t, "apply-taint-dep-requires-new")
  3072  	p := testProvider("aws")
  3073  	p.ApplyFn = testApplyFn
  3074  	p.DiffFn = testDiffFn
  3075  	s := &State{
  3076  		Modules: []*ModuleState{
  3077  			&ModuleState{
  3078  				Path: rootModulePath,
  3079  				Resources: map[string]*ResourceState{
  3080  					"aws_instance.foo": &ResourceState{
  3081  						Type: "aws_instance",
  3082  						Tainted: []*InstanceState{
  3083  							&InstanceState{
  3084  								ID: "baz",
  3085  								Attributes: map[string]string{
  3086  									"num":  "2",
  3087  									"type": "aws_instance",
  3088  								},
  3089  							},
  3090  						},
  3091  					},
  3092  					"aws_instance.bar": &ResourceState{
  3093  						Type: "aws_instance",
  3094  						Primary: &InstanceState{
  3095  							ID: "bar",
  3096  							Attributes: map[string]string{
  3097  								"foo":  "baz",
  3098  								"num":  "2",
  3099  								"type": "aws_instance",
  3100  							},
  3101  						},
  3102  					},
  3103  				},
  3104  			},
  3105  		},
  3106  	}
  3107  	ctx := testContext2(t, &ContextOpts{
  3108  		Module: m,
  3109  		Providers: map[string]ResourceProviderFactory{
  3110  			"aws": testProviderFuncFixed(p),
  3111  		},
  3112  		State: s,
  3113  	})
  3114  
  3115  	if p, err := ctx.Plan(); err != nil {
  3116  		t.Fatalf("err: %s", err)
  3117  	} else {
  3118  		t.Logf("plan: %s", p)
  3119  	}
  3120  
  3121  	state, err := ctx.Apply()
  3122  	if err != nil {
  3123  		t.Fatalf("err: %s", err)
  3124  	}
  3125  
  3126  	actual := strings.TrimSpace(state.String())
  3127  	expected := strings.TrimSpace(testTerraformApplyTaintDepRequireNewStr)
  3128  	if actual != expected {
  3129  		t.Fatalf("bad:\n%s", actual)
  3130  	}
  3131  }
  3132  
  3133  func TestContext2Apply_targeted(t *testing.T) {
  3134  	m := testModule(t, "apply-targeted")
  3135  	p := testProvider("aws")
  3136  	p.ApplyFn = testApplyFn
  3137  	p.DiffFn = testDiffFn
  3138  	ctx := testContext2(t, &ContextOpts{
  3139  		Module: m,
  3140  		Providers: map[string]ResourceProviderFactory{
  3141  			"aws": testProviderFuncFixed(p),
  3142  		},
  3143  		Targets: []string{"aws_instance.foo"},
  3144  	})
  3145  
  3146  	if _, err := ctx.Plan(); err != nil {
  3147  		t.Fatalf("err: %s", err)
  3148  	}
  3149  
  3150  	state, err := ctx.Apply()
  3151  	if err != nil {
  3152  		t.Fatalf("err: %s", err)
  3153  	}
  3154  
  3155  	mod := state.RootModule()
  3156  	if len(mod.Resources) != 1 {
  3157  		t.Fatalf("expected 1 resource, got: %#v", mod.Resources)
  3158  	}
  3159  
  3160  	checkStateString(t, state, `
  3161  aws_instance.foo:
  3162    ID = foo
  3163    num = 2
  3164    type = aws_instance
  3165  	`)
  3166  }
  3167  
  3168  func TestContext2Apply_targetedCount(t *testing.T) {
  3169  	m := testModule(t, "apply-targeted-count")
  3170  	p := testProvider("aws")
  3171  	p.ApplyFn = testApplyFn
  3172  	p.DiffFn = testDiffFn
  3173  	ctx := testContext2(t, &ContextOpts{
  3174  		Module: m,
  3175  		Providers: map[string]ResourceProviderFactory{
  3176  			"aws": testProviderFuncFixed(p),
  3177  		},
  3178  		Targets: []string{"aws_instance.foo"},
  3179  	})
  3180  
  3181  	if _, err := ctx.Plan(); err != nil {
  3182  		t.Fatalf("err: %s", err)
  3183  	}
  3184  
  3185  	state, err := ctx.Apply()
  3186  	if err != nil {
  3187  		t.Fatalf("err: %s", err)
  3188  	}
  3189  
  3190  	checkStateString(t, state, `
  3191  aws_instance.foo.0:
  3192    ID = foo
  3193  aws_instance.foo.1:
  3194    ID = foo
  3195  aws_instance.foo.2:
  3196    ID = foo
  3197  	`)
  3198  }
  3199  
  3200  func TestContext2Apply_targetedCountIndex(t *testing.T) {
  3201  	m := testModule(t, "apply-targeted-count")
  3202  	p := testProvider("aws")
  3203  	p.ApplyFn = testApplyFn
  3204  	p.DiffFn = testDiffFn
  3205  	ctx := testContext2(t, &ContextOpts{
  3206  		Module: m,
  3207  		Providers: map[string]ResourceProviderFactory{
  3208  			"aws": testProviderFuncFixed(p),
  3209  		},
  3210  		Targets: []string{"aws_instance.foo[1]"},
  3211  	})
  3212  
  3213  	if _, err := ctx.Plan(); err != nil {
  3214  		t.Fatalf("err: %s", err)
  3215  	}
  3216  
  3217  	state, err := ctx.Apply()
  3218  	if err != nil {
  3219  		t.Fatalf("err: %s", err)
  3220  	}
  3221  
  3222  	checkStateString(t, state, `
  3223  aws_instance.foo.1:
  3224    ID = foo
  3225  	`)
  3226  }
  3227  
  3228  func TestContext2Apply_targetedDestroy(t *testing.T) {
  3229  	m := testModule(t, "apply-targeted")
  3230  	p := testProvider("aws")
  3231  	p.ApplyFn = testApplyFn
  3232  	p.DiffFn = testDiffFn
  3233  	ctx := testContext2(t, &ContextOpts{
  3234  		Module: m,
  3235  		Providers: map[string]ResourceProviderFactory{
  3236  			"aws": testProviderFuncFixed(p),
  3237  		},
  3238  		State: &State{
  3239  			Modules: []*ModuleState{
  3240  				&ModuleState{
  3241  					Path: rootModulePath,
  3242  					Resources: map[string]*ResourceState{
  3243  						"aws_instance.foo": resourceState("aws_instance", "i-bcd345"),
  3244  						"aws_instance.bar": resourceState("aws_instance", "i-abc123"),
  3245  					},
  3246  				},
  3247  			},
  3248  		},
  3249  		Targets: []string{"aws_instance.foo"},
  3250  		Destroy: true,
  3251  	})
  3252  
  3253  	if _, err := ctx.Plan(); err != nil {
  3254  		t.Fatalf("err: %s", err)
  3255  	}
  3256  
  3257  	state, err := ctx.Apply()
  3258  	if err != nil {
  3259  		t.Fatalf("err: %s", err)
  3260  	}
  3261  
  3262  	mod := state.RootModule()
  3263  	if len(mod.Resources) != 1 {
  3264  		t.Fatalf("expected 1 resource, got: %#v", mod.Resources)
  3265  	}
  3266  
  3267  	checkStateString(t, state, `
  3268  aws_instance.bar:
  3269    ID = i-abc123
  3270  	`)
  3271  }
  3272  
  3273  func TestContext2Apply_targetedDestroyCountIndex(t *testing.T) {
  3274  	m := testModule(t, "apply-targeted-count")
  3275  	p := testProvider("aws")
  3276  	p.ApplyFn = testApplyFn
  3277  	p.DiffFn = testDiffFn
  3278  	ctx := testContext2(t, &ContextOpts{
  3279  		Module: m,
  3280  		Providers: map[string]ResourceProviderFactory{
  3281  			"aws": testProviderFuncFixed(p),
  3282  		},
  3283  		State: &State{
  3284  			Modules: []*ModuleState{
  3285  				&ModuleState{
  3286  					Path: rootModulePath,
  3287  					Resources: map[string]*ResourceState{
  3288  						"aws_instance.foo.0": resourceState("aws_instance", "i-bcd345"),
  3289  						"aws_instance.foo.1": resourceState("aws_instance", "i-bcd345"),
  3290  						"aws_instance.foo.2": resourceState("aws_instance", "i-bcd345"),
  3291  						"aws_instance.bar.0": resourceState("aws_instance", "i-abc123"),
  3292  						"aws_instance.bar.1": resourceState("aws_instance", "i-abc123"),
  3293  						"aws_instance.bar.2": resourceState("aws_instance", "i-abc123"),
  3294  					},
  3295  				},
  3296  			},
  3297  		},
  3298  		Targets: []string{
  3299  			"aws_instance.foo[2]",
  3300  			"aws_instance.bar[1]",
  3301  		},
  3302  		Destroy: true,
  3303  	})
  3304  
  3305  	if _, err := ctx.Plan(); err != nil {
  3306  		t.Fatalf("err: %s", err)
  3307  	}
  3308  
  3309  	state, err := ctx.Apply()
  3310  	if err != nil {
  3311  		t.Fatalf("err: %s", err)
  3312  	}
  3313  
  3314  	checkStateString(t, state, `
  3315  aws_instance.bar.0:
  3316    ID = i-abc123
  3317  aws_instance.bar.2:
  3318    ID = i-abc123
  3319  aws_instance.foo.0:
  3320    ID = i-bcd345
  3321  aws_instance.foo.1:
  3322    ID = i-bcd345
  3323  	`)
  3324  }
  3325  
  3326  func TestContext2Apply_targetedModule(t *testing.T) {
  3327  	m := testModule(t, "apply-targeted-module")
  3328  	p := testProvider("aws")
  3329  	p.ApplyFn = testApplyFn
  3330  	p.DiffFn = testDiffFn
  3331  	ctx := testContext2(t, &ContextOpts{
  3332  		Module: m,
  3333  		Providers: map[string]ResourceProviderFactory{
  3334  			"aws": testProviderFuncFixed(p),
  3335  		},
  3336  		Targets: []string{"module.child"},
  3337  	})
  3338  
  3339  	if _, err := ctx.Plan(); err != nil {
  3340  		t.Fatalf("err: %s", err)
  3341  	}
  3342  
  3343  	state, err := ctx.Apply()
  3344  	if err != nil {
  3345  		t.Fatalf("err: %s", err)
  3346  	}
  3347  
  3348  	mod := state.ModuleByPath([]string{"root", "child"})
  3349  	if mod == nil {
  3350  		t.Fatalf("no child module found in the state!\n\n%#v", state)
  3351  	}
  3352  	if len(mod.Resources) != 2 {
  3353  		t.Fatalf("expected 2 resources, got: %#v", mod.Resources)
  3354  	}
  3355  
  3356  	checkStateString(t, state, `
  3357  <no state>
  3358  module.child:
  3359    aws_instance.bar:
  3360      ID = foo
  3361      num = 2
  3362      type = aws_instance
  3363    aws_instance.foo:
  3364      ID = foo
  3365      num = 2
  3366      type = aws_instance
  3367  	`)
  3368  }
  3369  
  3370  // GH-1858
  3371  func TestContext2Apply_targetedModuleDep(t *testing.T) {
  3372  	m := testModule(t, "apply-targeted-module-dep")
  3373  	p := testProvider("aws")
  3374  	p.ApplyFn = testApplyFn
  3375  	p.DiffFn = testDiffFn
  3376  	ctx := testContext2(t, &ContextOpts{
  3377  		Module: m,
  3378  		Providers: map[string]ResourceProviderFactory{
  3379  			"aws": testProviderFuncFixed(p),
  3380  		},
  3381  		Targets: []string{"aws_instance.foo"},
  3382  	})
  3383  
  3384  	if _, err := ctx.Plan(); err != nil {
  3385  		t.Fatalf("err: %s", err)
  3386  	}
  3387  
  3388  	state, err := ctx.Apply()
  3389  	if err != nil {
  3390  		t.Fatalf("err: %s", err)
  3391  	}
  3392  
  3393  	checkStateString(t, state, `
  3394  aws_instance.foo:
  3395    ID = foo
  3396    foo = foo
  3397    type = aws_instance
  3398  
  3399    Dependencies:
  3400      module.child
  3401  
  3402  module.child:
  3403    aws_instance.mod:
  3404      ID = foo
  3405  
  3406    Outputs:
  3407  
  3408    output = foo
  3409  	`)
  3410  }
  3411  
  3412  func TestContext2Apply_targetedModuleResource(t *testing.T) {
  3413  	m := testModule(t, "apply-targeted-module-resource")
  3414  	p := testProvider("aws")
  3415  	p.ApplyFn = testApplyFn
  3416  	p.DiffFn = testDiffFn
  3417  	ctx := testContext2(t, &ContextOpts{
  3418  		Module: m,
  3419  		Providers: map[string]ResourceProviderFactory{
  3420  			"aws": testProviderFuncFixed(p),
  3421  		},
  3422  		Targets: []string{"module.child.aws_instance.foo"},
  3423  	})
  3424  
  3425  	if _, err := ctx.Plan(); err != nil {
  3426  		t.Fatalf("err: %s", err)
  3427  	}
  3428  
  3429  	state, err := ctx.Apply()
  3430  	if err != nil {
  3431  		t.Fatalf("err: %s", err)
  3432  	}
  3433  
  3434  	mod := state.ModuleByPath([]string{"root", "child"})
  3435  	if len(mod.Resources) != 1 {
  3436  		t.Fatalf("expected 1 resource, got: %#v", mod.Resources)
  3437  	}
  3438  
  3439  	checkStateString(t, state, `
  3440  <no state>
  3441  module.child:
  3442    aws_instance.foo:
  3443      ID = foo
  3444      num = 2
  3445      type = aws_instance
  3446  	`)
  3447  }
  3448  
  3449  func TestContext2Apply_unknownAttribute(t *testing.T) {
  3450  	m := testModule(t, "apply-unknown")
  3451  	p := testProvider("aws")
  3452  	p.ApplyFn = testApplyFn
  3453  	p.DiffFn = testDiffFn
  3454  	ctx := testContext2(t, &ContextOpts{
  3455  		Module: m,
  3456  		Providers: map[string]ResourceProviderFactory{
  3457  			"aws": testProviderFuncFixed(p),
  3458  		},
  3459  	})
  3460  
  3461  	if _, err := ctx.Plan(); err != nil {
  3462  		t.Fatalf("err: %s", err)
  3463  	}
  3464  
  3465  	state, err := ctx.Apply()
  3466  	if err == nil {
  3467  		t.Fatal("should error")
  3468  	}
  3469  
  3470  	actual := strings.TrimSpace(state.String())
  3471  	expected := strings.TrimSpace(testTerraformApplyUnknownAttrStr)
  3472  	if actual != expected {
  3473  		t.Fatalf("bad: \n%s", actual)
  3474  	}
  3475  }
  3476  
  3477  func TestContext2Apply_unknownAttributeInterpolate(t *testing.T) {
  3478  	m := testModule(t, "apply-unknown-interpolate")
  3479  	p := testProvider("aws")
  3480  	p.ApplyFn = testApplyFn
  3481  	p.DiffFn = testDiffFn
  3482  	ctx := testContext2(t, &ContextOpts{
  3483  		Module: m,
  3484  		Providers: map[string]ResourceProviderFactory{
  3485  			"aws": testProviderFuncFixed(p),
  3486  		},
  3487  	})
  3488  
  3489  	if _, err := ctx.Plan(); err == nil {
  3490  		t.Fatal("should error")
  3491  	}
  3492  }
  3493  
  3494  func TestContext2Apply_vars(t *testing.T) {
  3495  	m := testModule(t, "apply-vars")
  3496  	p := testProvider("aws")
  3497  	p.ApplyFn = testApplyFn
  3498  	p.DiffFn = testDiffFn
  3499  	ctx := testContext2(t, &ContextOpts{
  3500  		Module: m,
  3501  		Providers: map[string]ResourceProviderFactory{
  3502  			"aws": testProviderFuncFixed(p),
  3503  		},
  3504  		Variables: map[string]string{
  3505  			"foo":            "us-west-2",
  3506  			"amis.us-east-1": "override",
  3507  		},
  3508  	})
  3509  
  3510  	w, e := ctx.Validate()
  3511  	if len(w) > 0 {
  3512  		t.Fatalf("bad: %#v", w)
  3513  	}
  3514  	if len(e) > 0 {
  3515  		t.Fatalf("bad: %s", e)
  3516  	}
  3517  
  3518  	if _, err := ctx.Plan(); err != nil {
  3519  		t.Fatalf("err: %s", err)
  3520  	}
  3521  
  3522  	state, err := ctx.Apply()
  3523  	if err != nil {
  3524  		t.Fatalf("err: %s", err)
  3525  	}
  3526  
  3527  	actual := strings.TrimSpace(state.String())
  3528  	expected := strings.TrimSpace(testTerraformApplyVarsStr)
  3529  	if actual != expected {
  3530  		t.Fatalf("bad: \n%s", actual)
  3531  	}
  3532  }
  3533  
  3534  func TestContext2Apply_varsEnv(t *testing.T) {
  3535  	// Set the env var
  3536  	old := tempEnv(t, "TF_VAR_ami", "baz")
  3537  	defer os.Setenv("TF_VAR_ami", old)
  3538  
  3539  	m := testModule(t, "apply-vars-env")
  3540  	p := testProvider("aws")
  3541  	p.ApplyFn = testApplyFn
  3542  	p.DiffFn = testDiffFn
  3543  	ctx := testContext2(t, &ContextOpts{
  3544  		Module: m,
  3545  		Providers: map[string]ResourceProviderFactory{
  3546  			"aws": testProviderFuncFixed(p),
  3547  		},
  3548  	})
  3549  
  3550  	w, e := ctx.Validate()
  3551  	if len(w) > 0 {
  3552  		t.Fatalf("bad: %#v", w)
  3553  	}
  3554  	if len(e) > 0 {
  3555  		t.Fatalf("bad: %s", e)
  3556  	}
  3557  
  3558  	if _, err := ctx.Plan(); err != nil {
  3559  		t.Fatalf("err: %s", err)
  3560  	}
  3561  
  3562  	state, err := ctx.Apply()
  3563  	if err != nil {
  3564  		t.Fatalf("err: %s", err)
  3565  	}
  3566  
  3567  	actual := strings.TrimSpace(state.String())
  3568  	expected := strings.TrimSpace(testTerraformApplyVarsEnvStr)
  3569  	if actual != expected {
  3570  		t.Fatalf("bad: \n%s", actual)
  3571  	}
  3572  }
  3573  
  3574  func TestContext2Apply_createBefore_depends(t *testing.T) {
  3575  	m := testModule(t, "apply-depends-create-before")
  3576  	h := new(HookRecordApplyOrder)
  3577  	p := testProvider("aws")
  3578  	p.ApplyFn = testApplyFn
  3579  	p.DiffFn = testDiffFn
  3580  	state := &State{
  3581  		Modules: []*ModuleState{
  3582  			&ModuleState{
  3583  				Path: rootModulePath,
  3584  				Resources: map[string]*ResourceState{
  3585  					"aws_instance.web": &ResourceState{
  3586  						Type: "aws_instance",
  3587  						Primary: &InstanceState{
  3588  							ID: "bar",
  3589  							Attributes: map[string]string{
  3590  								"require_new": "ami-old",
  3591  							},
  3592  						},
  3593  					},
  3594  					"aws_instance.lb": &ResourceState{
  3595  						Type: "aws_instance",
  3596  						Primary: &InstanceState{
  3597  							ID: "baz",
  3598  							Attributes: map[string]string{
  3599  								"instance": "bar",
  3600  							},
  3601  						},
  3602  					},
  3603  				},
  3604  			},
  3605  		},
  3606  	}
  3607  	ctx := testContext2(t, &ContextOpts{
  3608  		Module: m,
  3609  		Hooks:  []Hook{h},
  3610  		Providers: map[string]ResourceProviderFactory{
  3611  			"aws": testProviderFuncFixed(p),
  3612  		},
  3613  		State: state,
  3614  	})
  3615  
  3616  	if _, err := ctx.Plan(); err != nil {
  3617  		t.Fatalf("err: %s", err)
  3618  	}
  3619  
  3620  	h.Active = true
  3621  	state, err := ctx.Apply()
  3622  	if err != nil {
  3623  		t.Fatalf("err: %s", err)
  3624  	}
  3625  
  3626  	mod := state.RootModule()
  3627  	if len(mod.Resources) < 2 {
  3628  		t.Fatalf("bad: %#v", mod.Resources)
  3629  	}
  3630  
  3631  	actual := strings.TrimSpace(state.String())
  3632  	expected := strings.TrimSpace(testTerraformApplyDependsCreateBeforeStr)
  3633  	if actual != expected {
  3634  		t.Fatalf("bad: \n%s\n%s", actual, expected)
  3635  	}
  3636  
  3637  	// Test that things were managed _in the right order_
  3638  	order := h.States
  3639  	diffs := h.Diffs
  3640  	if order[0].ID != "" || diffs[0].Destroy {
  3641  		t.Fatalf("should create new instance first: %#v", order)
  3642  	}
  3643  
  3644  	if order[1].ID != "baz" {
  3645  		t.Fatalf("update must happen after create: %#v", order)
  3646  	}
  3647  
  3648  	if order[2].ID != "bar" || !diffs[2].Destroy {
  3649  		t.Fatalf("destroy must happen after update: %#v", order)
  3650  	}
  3651  }
  3652  
  3653  func TestContext2Apply_singleDestroy(t *testing.T) {
  3654  	m := testModule(t, "apply-depends-create-before")
  3655  	h := new(HookRecordApplyOrder)
  3656  	p := testProvider("aws")
  3657  
  3658  	invokeCount := 0
  3659  	p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) {
  3660  		invokeCount++
  3661  		switch invokeCount {
  3662  		case 1:
  3663  			if d.Destroy {
  3664  				t.Fatalf("should not destroy")
  3665  			}
  3666  			if s.ID != "" {
  3667  				t.Fatalf("should not have ID")
  3668  			}
  3669  		case 2:
  3670  			if d.Destroy {
  3671  				t.Fatalf("should not destroy")
  3672  			}
  3673  			if s.ID != "baz" {
  3674  				t.Fatalf("should have id")
  3675  			}
  3676  		case 3:
  3677  			if !d.Destroy {
  3678  				t.Fatalf("should destroy")
  3679  			}
  3680  			if s.ID == "" {
  3681  				t.Fatalf("should have ID")
  3682  			}
  3683  		default:
  3684  			t.Fatalf("bad invoke count %d", invokeCount)
  3685  		}
  3686  		return testApplyFn(info, s, d)
  3687  	}
  3688  	p.DiffFn = testDiffFn
  3689  	state := &State{
  3690  		Modules: []*ModuleState{
  3691  			&ModuleState{
  3692  				Path: rootModulePath,
  3693  				Resources: map[string]*ResourceState{
  3694  					"aws_instance.web": &ResourceState{
  3695  						Type: "aws_instance",
  3696  						Primary: &InstanceState{
  3697  							ID: "bar",
  3698  							Attributes: map[string]string{
  3699  								"require_new": "ami-old",
  3700  							},
  3701  						},
  3702  					},
  3703  					"aws_instance.lb": &ResourceState{
  3704  						Type: "aws_instance",
  3705  						Primary: &InstanceState{
  3706  							ID: "baz",
  3707  							Attributes: map[string]string{
  3708  								"instance": "bar",
  3709  							},
  3710  						},
  3711  					},
  3712  				},
  3713  			},
  3714  		},
  3715  	}
  3716  	ctx := testContext2(t, &ContextOpts{
  3717  		Module: m,
  3718  		Hooks:  []Hook{h},
  3719  		Providers: map[string]ResourceProviderFactory{
  3720  			"aws": testProviderFuncFixed(p),
  3721  		},
  3722  		State: state,
  3723  	})
  3724  
  3725  	if _, err := ctx.Plan(); err != nil {
  3726  		t.Fatalf("err: %s", err)
  3727  	}
  3728  
  3729  	h.Active = true
  3730  	state, err := ctx.Apply()
  3731  	if err != nil {
  3732  		t.Fatalf("err: %s", err)
  3733  	}
  3734  
  3735  	if invokeCount != 3 {
  3736  		t.Fatalf("bad: %d", invokeCount)
  3737  	}
  3738  }