github.com/turtlemonvh/terraform@v0.6.9-0.20151204001754-8e40b6b855e8/terraform/context_plan_test.go (about)

     1  package terraform
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"os"
     7  	"reflect"
     8  	"sort"
     9  	"strings"
    10  	"sync"
    11  	"testing"
    12  )
    13  
    14  func TestContext2Plan(t *testing.T) {
    15  	m := testModule(t, "plan-good")
    16  	p := testProvider("aws")
    17  	p.DiffFn = testDiffFn
    18  	ctx := testContext2(t, &ContextOpts{
    19  		Module: m,
    20  		Providers: map[string]ResourceProviderFactory{
    21  			"aws": testProviderFuncFixed(p),
    22  		},
    23  	})
    24  
    25  	plan, err := ctx.Plan()
    26  	if err != nil {
    27  		t.Fatalf("err: %s", err)
    28  	}
    29  
    30  	if len(plan.Diff.RootModule().Resources) < 2 {
    31  		t.Fatalf("bad: %#v", plan.Diff.RootModule().Resources)
    32  	}
    33  
    34  	actual := strings.TrimSpace(plan.String())
    35  	expected := strings.TrimSpace(testTerraformPlanStr)
    36  	if actual != expected {
    37  		t.Fatalf("bad:\n%s", actual)
    38  	}
    39  }
    40  
    41  func TestContext2Plan_createBefore_maintainRoot(t *testing.T) {
    42  	m := testModule(t, "plan-cbd-maintain-root")
    43  	p := testProvider("aws")
    44  	p.DiffFn = testDiffFn
    45  	ctx := testContext2(t, &ContextOpts{
    46  		Module: m,
    47  		Providers: map[string]ResourceProviderFactory{
    48  			"aws": testProviderFuncFixed(p),
    49  		},
    50  		Variables: map[string]string{
    51  			"in": "a,b,c",
    52  		},
    53  	})
    54  
    55  	plan, err := ctx.Plan()
    56  	if err != nil {
    57  		t.Fatalf("err: %s", err)
    58  	}
    59  
    60  	actual := strings.TrimSpace(plan.String())
    61  	expected := strings.TrimSpace(`
    62  DIFF:
    63  
    64  CREATE: aws_instance.bar.0
    65  CREATE: aws_instance.bar.1
    66  CREATE: aws_instance.foo.0
    67  CREATE: aws_instance.foo.1
    68  
    69  STATE:
    70  
    71  <no state>
    72  		`)
    73  	if actual != expected {
    74  		t.Fatalf("expected:\n%s, got:\n%s", expected, actual)
    75  	}
    76  }
    77  
    78  func TestContext2Plan_emptyDiff(t *testing.T) {
    79  	m := testModule(t, "plan-empty")
    80  	p := testProvider("aws")
    81  	p.DiffFn = func(
    82  		info *InstanceInfo,
    83  		s *InstanceState,
    84  		c *ResourceConfig) (*InstanceDiff, error) {
    85  		return nil, nil
    86  	}
    87  
    88  	ctx := testContext2(t, &ContextOpts{
    89  		Module: m,
    90  		Providers: map[string]ResourceProviderFactory{
    91  			"aws": testProviderFuncFixed(p),
    92  		},
    93  	})
    94  
    95  	plan, err := ctx.Plan()
    96  	if err != nil {
    97  		t.Fatalf("err: %s", err)
    98  	}
    99  
   100  	actual := strings.TrimSpace(plan.String())
   101  	expected := strings.TrimSpace(testTerraformPlanEmptyStr)
   102  	if actual != expected {
   103  		t.Fatalf("bad:\n%s", actual)
   104  	}
   105  }
   106  
   107  func TestContext2Plan_minimal(t *testing.T) {
   108  	m := testModule(t, "plan-empty")
   109  	p := testProvider("aws")
   110  	p.DiffFn = testDiffFn
   111  	ctx := testContext2(t, &ContextOpts{
   112  		Module: m,
   113  		Providers: map[string]ResourceProviderFactory{
   114  			"aws": testProviderFuncFixed(p),
   115  		},
   116  	})
   117  
   118  	plan, err := ctx.Plan()
   119  	if err != nil {
   120  		t.Fatalf("err: %s", err)
   121  	}
   122  
   123  	actual := strings.TrimSpace(plan.String())
   124  	expected := strings.TrimSpace(testTerraformPlanEmptyStr)
   125  	if actual != expected {
   126  		t.Fatalf("bad:\n%s", actual)
   127  	}
   128  }
   129  
   130  func TestContext2Plan_modules(t *testing.T) {
   131  	m := testModule(t, "plan-modules")
   132  	p := testProvider("aws")
   133  	p.DiffFn = testDiffFn
   134  	ctx := testContext2(t, &ContextOpts{
   135  		Module: m,
   136  		Providers: map[string]ResourceProviderFactory{
   137  			"aws": testProviderFuncFixed(p),
   138  		},
   139  	})
   140  
   141  	plan, err := ctx.Plan()
   142  	if err != nil {
   143  		t.Fatalf("err: %s", err)
   144  	}
   145  
   146  	actual := strings.TrimSpace(plan.String())
   147  	expected := strings.TrimSpace(testTerraformPlanModulesStr)
   148  	if actual != expected {
   149  		t.Fatalf("bad:\n%s", actual)
   150  	}
   151  }
   152  
   153  // GH-1475
   154  func TestContext2Plan_moduleCycle(t *testing.T) {
   155  	m := testModule(t, "plan-module-cycle")
   156  	p := testProvider("aws")
   157  	p.DiffFn = testDiffFn
   158  	ctx := testContext2(t, &ContextOpts{
   159  		Module: m,
   160  		Providers: map[string]ResourceProviderFactory{
   161  			"aws": testProviderFuncFixed(p),
   162  		},
   163  	})
   164  
   165  	plan, err := ctx.Plan()
   166  	if err != nil {
   167  		t.Fatalf("err: %s", err)
   168  	}
   169  
   170  	actual := strings.TrimSpace(plan.String())
   171  	expected := strings.TrimSpace(testTerraformPlanModuleCycleStr)
   172  	if actual != expected {
   173  		t.Fatalf("bad:\n%s", actual)
   174  	}
   175  }
   176  
   177  func TestContext2Plan_moduleDeadlock(t *testing.T) {
   178  	testCheckDeadlock(t, func() {
   179  		m := testModule(t, "plan-module-deadlock")
   180  		p := testProvider("aws")
   181  		p.DiffFn = testDiffFn
   182  
   183  		ctx := testContext2(t, &ContextOpts{
   184  			Module: m,
   185  			Providers: map[string]ResourceProviderFactory{
   186  				"aws": testProviderFuncFixed(p),
   187  			},
   188  		})
   189  
   190  		plan, err := ctx.Plan()
   191  		if err != nil {
   192  			t.Fatalf("err: %s", err)
   193  		}
   194  
   195  		actual := strings.TrimSpace(plan.String())
   196  		expected := strings.TrimSpace(`
   197  DIFF:
   198  
   199  module.child:
   200    CREATE: aws_instance.foo.0
   201    CREATE: aws_instance.foo.1
   202    CREATE: aws_instance.foo.2
   203  
   204  STATE:
   205  
   206  <no state>
   207  		`)
   208  		if actual != expected {
   209  			t.Fatalf("expected:\n%sgot:\n%s", expected, actual)
   210  		}
   211  	})
   212  }
   213  
   214  func TestContext2Plan_moduleInput(t *testing.T) {
   215  	m := testModule(t, "plan-module-input")
   216  	p := testProvider("aws")
   217  	p.DiffFn = testDiffFn
   218  	ctx := testContext2(t, &ContextOpts{
   219  		Module: m,
   220  		Providers: map[string]ResourceProviderFactory{
   221  			"aws": testProviderFuncFixed(p),
   222  		},
   223  	})
   224  
   225  	plan, err := ctx.Plan()
   226  	if err != nil {
   227  		t.Fatalf("err: %s", err)
   228  	}
   229  
   230  	actual := strings.TrimSpace(plan.String())
   231  	expected := strings.TrimSpace(testTerraformPlanModuleInputStr)
   232  	if actual != expected {
   233  		t.Fatalf("bad:\n%s", actual)
   234  	}
   235  }
   236  
   237  func TestContext2Plan_moduleInputComputed(t *testing.T) {
   238  	m := testModule(t, "plan-module-input-computed")
   239  	p := testProvider("aws")
   240  	p.DiffFn = testDiffFn
   241  	ctx := testContext2(t, &ContextOpts{
   242  		Module: m,
   243  		Providers: map[string]ResourceProviderFactory{
   244  			"aws": testProviderFuncFixed(p),
   245  		},
   246  	})
   247  
   248  	plan, err := ctx.Plan()
   249  	if err != nil {
   250  		t.Fatalf("err: %s", err)
   251  	}
   252  
   253  	actual := strings.TrimSpace(plan.String())
   254  	expected := strings.TrimSpace(testTerraformPlanModuleInputComputedStr)
   255  	if actual != expected {
   256  		t.Fatalf("bad:\n%s", actual)
   257  	}
   258  }
   259  
   260  func TestContext2Plan_moduleInputFromVar(t *testing.T) {
   261  	m := testModule(t, "plan-module-input-var")
   262  	p := testProvider("aws")
   263  	p.DiffFn = testDiffFn
   264  	ctx := testContext2(t, &ContextOpts{
   265  		Module: m,
   266  		Providers: map[string]ResourceProviderFactory{
   267  			"aws": testProviderFuncFixed(p),
   268  		},
   269  		Variables: map[string]string{
   270  			"foo": "52",
   271  		},
   272  	})
   273  
   274  	plan, err := ctx.Plan()
   275  	if err != nil {
   276  		t.Fatalf("err: %s", err)
   277  	}
   278  
   279  	actual := strings.TrimSpace(plan.String())
   280  	expected := strings.TrimSpace(testTerraformPlanModuleInputVarStr)
   281  	if actual != expected {
   282  		t.Fatalf("bad:\n%s", actual)
   283  	}
   284  }
   285  
   286  func TestContext2Plan_moduleMultiVar(t *testing.T) {
   287  	m := testModule(t, "plan-module-multi-var")
   288  	p := testProvider("aws")
   289  	p.DiffFn = testDiffFn
   290  	ctx := testContext2(t, &ContextOpts{
   291  		Module: m,
   292  		Providers: map[string]ResourceProviderFactory{
   293  			"aws": testProviderFuncFixed(p),
   294  		},
   295  	})
   296  
   297  	plan, err := ctx.Plan()
   298  	if err != nil {
   299  		t.Fatalf("err: %s", err)
   300  	}
   301  
   302  	actual := strings.TrimSpace(plan.String())
   303  	expected := strings.TrimSpace(testTerraformPlanModuleMultiVarStr)
   304  	if actual != expected {
   305  		t.Fatalf("bad:\n%s", actual)
   306  	}
   307  }
   308  
   309  func TestContext2Plan_moduleOrphans(t *testing.T) {
   310  	m := testModule(t, "plan-modules-remove")
   311  	p := testProvider("aws")
   312  	p.DiffFn = testDiffFn
   313  	s := &State{
   314  		Modules: []*ModuleState{
   315  			&ModuleState{
   316  				Path: []string{"root", "child"},
   317  				Resources: map[string]*ResourceState{
   318  					"aws_instance.foo": &ResourceState{
   319  						Type: "aws_instance",
   320  						Primary: &InstanceState{
   321  							ID: "baz",
   322  						},
   323  					},
   324  				},
   325  			},
   326  		},
   327  	}
   328  	ctx := testContext2(t, &ContextOpts{
   329  		Module: m,
   330  		Providers: map[string]ResourceProviderFactory{
   331  			"aws": testProviderFuncFixed(p),
   332  		},
   333  		State: s,
   334  	})
   335  
   336  	plan, err := ctx.Plan()
   337  	if err != nil {
   338  		t.Fatalf("err: %s", err)
   339  	}
   340  
   341  	actual := strings.TrimSpace(plan.String())
   342  	expected := strings.TrimSpace(testTerraformPlanModuleOrphansStr)
   343  	if actual != expected {
   344  		t.Fatalf("bad:\n%s", actual)
   345  	}
   346  }
   347  
   348  func TestContext2Plan_moduleProviderInherit(t *testing.T) {
   349  	var l sync.Mutex
   350  	var calls []string
   351  
   352  	m := testModule(t, "plan-module-provider-inherit")
   353  	ctx := testContext2(t, &ContextOpts{
   354  		Module: m,
   355  		Providers: map[string]ResourceProviderFactory{
   356  			"aws": func() (ResourceProvider, error) {
   357  				l.Lock()
   358  				defer l.Unlock()
   359  
   360  				p := testProvider("aws")
   361  				p.ConfigureFn = func(c *ResourceConfig) error {
   362  					if v, ok := c.Get("from"); !ok || v.(string) != "root" {
   363  						return fmt.Errorf("bad")
   364  					}
   365  
   366  					return nil
   367  				}
   368  				p.DiffFn = func(
   369  					info *InstanceInfo,
   370  					state *InstanceState,
   371  					c *ResourceConfig) (*InstanceDiff, error) {
   372  					v, _ := c.Get("from")
   373  					calls = append(calls, v.(string))
   374  					return testDiffFn(info, state, c)
   375  				}
   376  				return p, nil
   377  			},
   378  		},
   379  	})
   380  
   381  	_, err := ctx.Plan()
   382  	if err != nil {
   383  		t.Fatalf("err: %s", err)
   384  	}
   385  
   386  	actual := calls
   387  	sort.Strings(actual)
   388  	expected := []string{"child", "root"}
   389  	if !reflect.DeepEqual(actual, expected) {
   390  		t.Fatalf("bad: %#v", actual)
   391  	}
   392  }
   393  
   394  func TestContext2Plan_moduleProviderDefaults(t *testing.T) {
   395  	var l sync.Mutex
   396  	var calls []string
   397  	toCount := 0
   398  
   399  	m := testModule(t, "plan-module-provider-defaults")
   400  	ctx := testContext2(t, &ContextOpts{
   401  		Module: m,
   402  		Providers: map[string]ResourceProviderFactory{
   403  			"aws": func() (ResourceProvider, error) {
   404  				l.Lock()
   405  				defer l.Unlock()
   406  
   407  				p := testProvider("aws")
   408  				p.ConfigureFn = func(c *ResourceConfig) error {
   409  					if v, ok := c.Get("from"); !ok || v.(string) != "root" {
   410  						return fmt.Errorf("bad")
   411  					}
   412  					if v, ok := c.Get("to"); ok && v.(string) == "child" {
   413  						toCount++
   414  					}
   415  
   416  					return nil
   417  				}
   418  				p.DiffFn = func(
   419  					info *InstanceInfo,
   420  					state *InstanceState,
   421  					c *ResourceConfig) (*InstanceDiff, error) {
   422  					v, _ := c.Get("from")
   423  					calls = append(calls, v.(string))
   424  					return testDiffFn(info, state, c)
   425  				}
   426  				return p, nil
   427  			},
   428  		},
   429  	})
   430  
   431  	_, err := ctx.Plan()
   432  	if err != nil {
   433  		t.Fatalf("err: %s", err)
   434  	}
   435  
   436  	if toCount != 1 {
   437  		t.Fatalf(
   438  			"provider in child didn't set proper config\n\n"+
   439  				"toCount: %d", toCount)
   440  	}
   441  
   442  	actual := calls
   443  	sort.Strings(actual)
   444  	expected := []string{"child", "root"}
   445  	if !reflect.DeepEqual(actual, expected) {
   446  		t.Fatalf("bad: %#v", actual)
   447  	}
   448  }
   449  
   450  func TestContext2Plan_moduleProviderDefaultsVar(t *testing.T) {
   451  	var l sync.Mutex
   452  	var calls []string
   453  
   454  	m := testModule(t, "plan-module-provider-defaults-var")
   455  	ctx := testContext2(t, &ContextOpts{
   456  		Module: m,
   457  		Providers: map[string]ResourceProviderFactory{
   458  			"aws": func() (ResourceProvider, error) {
   459  				l.Lock()
   460  				defer l.Unlock()
   461  
   462  				p := testProvider("aws")
   463  				p.ConfigureFn = func(c *ResourceConfig) error {
   464  					var buf bytes.Buffer
   465  					if v, ok := c.Get("from"); ok {
   466  						buf.WriteString(v.(string) + "\n")
   467  					}
   468  					if v, ok := c.Get("to"); ok {
   469  						buf.WriteString(v.(string) + "\n")
   470  					}
   471  
   472  					calls = append(calls, buf.String())
   473  					return nil
   474  				}
   475  				p.DiffFn = testDiffFn
   476  				return p, nil
   477  			},
   478  		},
   479  		Variables: map[string]string{
   480  			"foo": "root",
   481  		},
   482  	})
   483  
   484  	_, err := ctx.Plan()
   485  	if err != nil {
   486  		t.Fatalf("err: %s", err)
   487  	}
   488  
   489  	expected := []string{
   490  		"root\n",
   491  		"root\nchild\n",
   492  	}
   493  	if !reflect.DeepEqual(calls, expected) {
   494  		t.Fatalf("BAD: %#v", calls)
   495  	}
   496  }
   497  
   498  func TestContext2Plan_moduleVar(t *testing.T) {
   499  	m := testModule(t, "plan-module-var")
   500  	p := testProvider("aws")
   501  	p.DiffFn = testDiffFn
   502  	ctx := testContext2(t, &ContextOpts{
   503  		Module: m,
   504  		Providers: map[string]ResourceProviderFactory{
   505  			"aws": testProviderFuncFixed(p),
   506  		},
   507  	})
   508  
   509  	plan, err := ctx.Plan()
   510  	if err != nil {
   511  		t.Fatalf("err: %s", err)
   512  	}
   513  
   514  	actual := strings.TrimSpace(plan.String())
   515  	expected := strings.TrimSpace(testTerraformPlanModuleVarStr)
   516  	if actual != expected {
   517  		t.Fatalf("bad:\n%s", actual)
   518  	}
   519  }
   520  
   521  func TestContext2Plan_moduleVarComputed(t *testing.T) {
   522  	m := testModule(t, "plan-module-var-computed")
   523  	p := testProvider("aws")
   524  	p.DiffFn = testDiffFn
   525  	ctx := testContext2(t, &ContextOpts{
   526  		Module: m,
   527  		Providers: map[string]ResourceProviderFactory{
   528  			"aws": testProviderFuncFixed(p),
   529  		},
   530  	})
   531  
   532  	plan, err := ctx.Plan()
   533  	if err != nil {
   534  		t.Fatalf("err: %s", err)
   535  	}
   536  
   537  	actual := strings.TrimSpace(plan.String())
   538  	expected := strings.TrimSpace(testTerraformPlanModuleVarComputedStr)
   539  	if actual != expected {
   540  		t.Fatalf("bad:\n%s", actual)
   541  	}
   542  }
   543  
   544  func TestContext2Plan_nil(t *testing.T) {
   545  	m := testModule(t, "plan-nil")
   546  	p := testProvider("aws")
   547  	p.DiffFn = testDiffFn
   548  	ctx := testContext2(t, &ContextOpts{
   549  		Module: m,
   550  		Providers: map[string]ResourceProviderFactory{
   551  			"aws": testProviderFuncFixed(p),
   552  		},
   553  		State: &State{
   554  			Modules: []*ModuleState{
   555  				&ModuleState{
   556  					Path: rootModulePath,
   557  					Resources: map[string]*ResourceState{
   558  						"aws_instance.foo": &ResourceState{
   559  							Type: "aws_instance",
   560  							Primary: &InstanceState{
   561  								ID: "bar",
   562  							},
   563  						},
   564  					},
   565  				},
   566  			},
   567  		},
   568  	})
   569  
   570  	plan, err := ctx.Plan()
   571  	if err != nil {
   572  		t.Fatalf("err: %s", err)
   573  	}
   574  	if len(plan.Diff.RootModule().Resources) != 0 {
   575  		t.Fatalf("bad: %#v", plan.Diff.RootModule().Resources)
   576  	}
   577  }
   578  
   579  func TestContext2Plan_preventDestroy_bad(t *testing.T) {
   580  	m := testModule(t, "plan-prevent-destroy-bad")
   581  	p := testProvider("aws")
   582  	p.DiffFn = testDiffFn
   583  	ctx := testContext2(t, &ContextOpts{
   584  		Module: m,
   585  		Providers: map[string]ResourceProviderFactory{
   586  			"aws": testProviderFuncFixed(p),
   587  		},
   588  		State: &State{
   589  			Modules: []*ModuleState{
   590  				&ModuleState{
   591  					Path: rootModulePath,
   592  					Resources: map[string]*ResourceState{
   593  						"aws_instance.foo": &ResourceState{
   594  							Type: "aws_instance",
   595  							Primary: &InstanceState{
   596  								ID: "i-abc123",
   597  							},
   598  						},
   599  					},
   600  				},
   601  			},
   602  		},
   603  	})
   604  
   605  	plan, err := ctx.Plan()
   606  
   607  	expectedErr := "aws_instance.foo: the plan would destroy"
   608  	if !strings.Contains(fmt.Sprintf("%s", err), expectedErr) {
   609  		t.Fatalf("expected err would contain %q\nerr: %s\nplan: %s",
   610  			expectedErr, err, plan)
   611  	}
   612  }
   613  
   614  func TestContext2Plan_preventDestroy_good(t *testing.T) {
   615  	m := testModule(t, "plan-prevent-destroy-good")
   616  	p := testProvider("aws")
   617  	p.DiffFn = testDiffFn
   618  	ctx := testContext2(t, &ContextOpts{
   619  		Module: m,
   620  		Providers: map[string]ResourceProviderFactory{
   621  			"aws": testProviderFuncFixed(p),
   622  		},
   623  		State: &State{
   624  			Modules: []*ModuleState{
   625  				&ModuleState{
   626  					Path: rootModulePath,
   627  					Resources: map[string]*ResourceState{
   628  						"aws_instance.foo": &ResourceState{
   629  							Type: "aws_instance",
   630  							Primary: &InstanceState{
   631  								ID: "i-abc123",
   632  							},
   633  						},
   634  					},
   635  				},
   636  			},
   637  		},
   638  	})
   639  
   640  	plan, err := ctx.Plan()
   641  	if err != nil {
   642  		t.Fatalf("err: %s", err)
   643  	}
   644  	if !plan.Diff.Empty() {
   645  		t.Fatalf("Expected empty plan, got %s", plan.String())
   646  	}
   647  }
   648  
   649  func TestContext2Plan_preventDestroy_destroyPlan(t *testing.T) {
   650  	m := testModule(t, "plan-prevent-destroy-good")
   651  	p := testProvider("aws")
   652  	p.DiffFn = testDiffFn
   653  	ctx := testContext2(t, &ContextOpts{
   654  		Module: m,
   655  		Providers: map[string]ResourceProviderFactory{
   656  			"aws": testProviderFuncFixed(p),
   657  		},
   658  		State: &State{
   659  			Modules: []*ModuleState{
   660  				&ModuleState{
   661  					Path: rootModulePath,
   662  					Resources: map[string]*ResourceState{
   663  						"aws_instance.foo": &ResourceState{
   664  							Type: "aws_instance",
   665  							Primary: &InstanceState{
   666  								ID: "i-abc123",
   667  							},
   668  						},
   669  					},
   670  				},
   671  			},
   672  		},
   673  		Destroy: true,
   674  	})
   675  
   676  	plan, err := ctx.Plan()
   677  
   678  	expectedErr := "aws_instance.foo: the plan would destroy"
   679  	if !strings.Contains(fmt.Sprintf("%s", err), expectedErr) {
   680  		t.Fatalf("expected err would contain %q\nerr: %s\nplan: %s",
   681  			expectedErr, err, plan)
   682  	}
   683  }
   684  
   685  func TestContext2Plan_computed(t *testing.T) {
   686  	m := testModule(t, "plan-computed")
   687  	p := testProvider("aws")
   688  	p.DiffFn = testDiffFn
   689  	ctx := testContext2(t, &ContextOpts{
   690  		Module: m,
   691  		Providers: map[string]ResourceProviderFactory{
   692  			"aws": testProviderFuncFixed(p),
   693  		},
   694  	})
   695  
   696  	plan, err := ctx.Plan()
   697  	if err != nil {
   698  		t.Fatalf("err: %s", err)
   699  	}
   700  
   701  	actual := strings.TrimSpace(plan.String())
   702  	expected := strings.TrimSpace(testTerraformPlanComputedStr)
   703  	if actual != expected {
   704  		t.Fatalf("bad:\n%s", actual)
   705  	}
   706  }
   707  
   708  func TestContext2Plan_computedList(t *testing.T) {
   709  	m := testModule(t, "plan-computed-list")
   710  	p := testProvider("aws")
   711  	p.DiffFn = testDiffFn
   712  	ctx := testContext2(t, &ContextOpts{
   713  		Module: m,
   714  		Providers: map[string]ResourceProviderFactory{
   715  			"aws": testProviderFuncFixed(p),
   716  		},
   717  	})
   718  
   719  	plan, err := ctx.Plan()
   720  	if err != nil {
   721  		t.Fatalf("err: %s", err)
   722  	}
   723  
   724  	actual := strings.TrimSpace(plan.String())
   725  	expected := strings.TrimSpace(testTerraformPlanComputedListStr)
   726  	if actual != expected {
   727  		t.Fatalf("bad:\n%s", actual)
   728  	}
   729  }
   730  
   731  func TestContext2Plan_count(t *testing.T) {
   732  	m := testModule(t, "plan-count")
   733  	p := testProvider("aws")
   734  	p.DiffFn = testDiffFn
   735  	ctx := testContext2(t, &ContextOpts{
   736  		Module: m,
   737  		Providers: map[string]ResourceProviderFactory{
   738  			"aws": testProviderFuncFixed(p),
   739  		},
   740  	})
   741  
   742  	plan, err := ctx.Plan()
   743  	if err != nil {
   744  		t.Fatalf("err: %s", err)
   745  	}
   746  
   747  	if len(plan.Diff.RootModule().Resources) < 6 {
   748  		t.Fatalf("bad: %#v", plan.Diff.RootModule().Resources)
   749  	}
   750  
   751  	actual := strings.TrimSpace(plan.String())
   752  	expected := strings.TrimSpace(testTerraformPlanCountStr)
   753  	if actual != expected {
   754  		t.Fatalf("bad:\n%s", actual)
   755  	}
   756  }
   757  
   758  func TestContext2Plan_countComputed(t *testing.T) {
   759  	m := testModule(t, "plan-count-computed")
   760  	p := testProvider("aws")
   761  	p.DiffFn = testDiffFn
   762  	ctx := testContext2(t, &ContextOpts{
   763  		Module: m,
   764  		Providers: map[string]ResourceProviderFactory{
   765  			"aws": testProviderFuncFixed(p),
   766  		},
   767  	})
   768  
   769  	_, err := ctx.Plan()
   770  	if err == nil {
   771  		t.Fatal("should error")
   772  	}
   773  }
   774  
   775  func TestContext2Plan_countIndex(t *testing.T) {
   776  	m := testModule(t, "plan-count-index")
   777  	p := testProvider("aws")
   778  	p.DiffFn = testDiffFn
   779  	ctx := testContext2(t, &ContextOpts{
   780  		Module: m,
   781  		Providers: map[string]ResourceProviderFactory{
   782  			"aws": testProviderFuncFixed(p),
   783  		},
   784  	})
   785  
   786  	plan, err := ctx.Plan()
   787  	if err != nil {
   788  		t.Fatalf("err: %s", err)
   789  	}
   790  
   791  	actual := strings.TrimSpace(plan.String())
   792  	expected := strings.TrimSpace(testTerraformPlanCountIndexStr)
   793  	if actual != expected {
   794  		t.Fatalf("bad:\n%s", actual)
   795  	}
   796  }
   797  
   798  func TestContext2Plan_countIndexZero(t *testing.T) {
   799  	m := testModule(t, "plan-count-index-zero")
   800  	p := testProvider("aws")
   801  	p.DiffFn = testDiffFn
   802  	ctx := testContext2(t, &ContextOpts{
   803  		Module: m,
   804  		Providers: map[string]ResourceProviderFactory{
   805  			"aws": testProviderFuncFixed(p),
   806  		},
   807  	})
   808  
   809  	plan, err := ctx.Plan()
   810  	if err != nil {
   811  		t.Fatalf("err: %s", err)
   812  	}
   813  
   814  	actual := strings.TrimSpace(plan.String())
   815  	expected := strings.TrimSpace(testTerraformPlanCountIndexZeroStr)
   816  	if actual != expected {
   817  		t.Fatalf("bad:\n%s", actual)
   818  	}
   819  }
   820  
   821  func TestContext2Plan_countVar(t *testing.T) {
   822  	m := testModule(t, "plan-count-var")
   823  	p := testProvider("aws")
   824  	p.DiffFn = testDiffFn
   825  	ctx := testContext2(t, &ContextOpts{
   826  		Module: m,
   827  		Providers: map[string]ResourceProviderFactory{
   828  			"aws": testProviderFuncFixed(p),
   829  		},
   830  		Variables: map[string]string{
   831  			"count": "3",
   832  		},
   833  	})
   834  
   835  	plan, err := ctx.Plan()
   836  	if err != nil {
   837  		t.Fatalf("err: %s", err)
   838  	}
   839  
   840  	actual := strings.TrimSpace(plan.String())
   841  	expected := strings.TrimSpace(testTerraformPlanCountVarStr)
   842  	if actual != expected {
   843  		t.Fatalf("bad:\n%s", actual)
   844  	}
   845  }
   846  
   847  func TestContext2Plan_countZero(t *testing.T) {
   848  	m := testModule(t, "plan-count-zero")
   849  	p := testProvider("aws")
   850  	p.DiffFn = testDiffFn
   851  	ctx := testContext2(t, &ContextOpts{
   852  		Module: m,
   853  		Providers: map[string]ResourceProviderFactory{
   854  			"aws": testProviderFuncFixed(p),
   855  		},
   856  	})
   857  
   858  	plan, err := ctx.Plan()
   859  	if err != nil {
   860  		t.Fatalf("err: %s", err)
   861  	}
   862  
   863  	actual := strings.TrimSpace(plan.String())
   864  	expected := strings.TrimSpace(testTerraformPlanCountZeroStr)
   865  	if actual != expected {
   866  		t.Fatalf("bad:\n%s", actual)
   867  	}
   868  }
   869  
   870  func TestContext2Plan_countOneIndex(t *testing.T) {
   871  	m := testModule(t, "plan-count-one-index")
   872  	p := testProvider("aws")
   873  	p.DiffFn = testDiffFn
   874  	ctx := testContext2(t, &ContextOpts{
   875  		Module: m,
   876  		Providers: map[string]ResourceProviderFactory{
   877  			"aws": testProviderFuncFixed(p),
   878  		},
   879  	})
   880  
   881  	plan, err := ctx.Plan()
   882  	if err != nil {
   883  		t.Fatalf("err: %s", err)
   884  	}
   885  
   886  	actual := strings.TrimSpace(plan.String())
   887  	expected := strings.TrimSpace(testTerraformPlanCountOneIndexStr)
   888  	if actual != expected {
   889  		t.Fatalf("bad:\n%s", actual)
   890  	}
   891  }
   892  
   893  func TestContext2Plan_countDecreaseToOne(t *testing.T) {
   894  	m := testModule(t, "plan-count-dec")
   895  	p := testProvider("aws")
   896  	p.DiffFn = testDiffFn
   897  	s := &State{
   898  		Modules: []*ModuleState{
   899  			&ModuleState{
   900  				Path: rootModulePath,
   901  				Resources: map[string]*ResourceState{
   902  					"aws_instance.foo.0": &ResourceState{
   903  						Type: "aws_instance",
   904  						Primary: &InstanceState{
   905  							ID: "bar",
   906  							Attributes: map[string]string{
   907  								"foo":  "foo",
   908  								"type": "aws_instance",
   909  							},
   910  						},
   911  					},
   912  					"aws_instance.foo.1": &ResourceState{
   913  						Type: "aws_instance",
   914  						Primary: &InstanceState{
   915  							ID: "bar",
   916  						},
   917  					},
   918  					"aws_instance.foo.2": &ResourceState{
   919  						Type: "aws_instance",
   920  						Primary: &InstanceState{
   921  							ID: "bar",
   922  						},
   923  					},
   924  				},
   925  			},
   926  		},
   927  	}
   928  	ctx := testContext2(t, &ContextOpts{
   929  		Module: m,
   930  		Providers: map[string]ResourceProviderFactory{
   931  			"aws": testProviderFuncFixed(p),
   932  		},
   933  		State: s,
   934  	})
   935  
   936  	plan, err := ctx.Plan()
   937  	if err != nil {
   938  		t.Fatalf("err: %s", err)
   939  	}
   940  
   941  	actual := strings.TrimSpace(plan.String())
   942  	expected := strings.TrimSpace(testTerraformPlanCountDecreaseStr)
   943  	if actual != expected {
   944  		t.Fatalf("bad:\n%s", actual)
   945  	}
   946  }
   947  
   948  func TestContext2Plan_countIncreaseFromNotSet(t *testing.T) {
   949  	m := testModule(t, "plan-count-inc")
   950  	p := testProvider("aws")
   951  	p.DiffFn = testDiffFn
   952  	s := &State{
   953  		Modules: []*ModuleState{
   954  			&ModuleState{
   955  				Path: rootModulePath,
   956  				Resources: map[string]*ResourceState{
   957  					"aws_instance.foo": &ResourceState{
   958  						Type: "aws_instance",
   959  						Primary: &InstanceState{
   960  							ID: "bar",
   961  							Attributes: map[string]string{
   962  								"foo":  "foo",
   963  								"type": "aws_instance",
   964  							},
   965  						},
   966  					},
   967  				},
   968  			},
   969  		},
   970  	}
   971  	ctx := testContext2(t, &ContextOpts{
   972  		Module: m,
   973  		Providers: map[string]ResourceProviderFactory{
   974  			"aws": testProviderFuncFixed(p),
   975  		},
   976  		State: s,
   977  	})
   978  
   979  	plan, err := ctx.Plan()
   980  	if err != nil {
   981  		t.Fatalf("err: %s", err)
   982  	}
   983  
   984  	actual := strings.TrimSpace(plan.String())
   985  	expected := strings.TrimSpace(testTerraformPlanCountIncreaseStr)
   986  	if actual != expected {
   987  		t.Fatalf("bad:\n%s", actual)
   988  	}
   989  }
   990  
   991  func TestContext2Plan_countIncreaseFromOne(t *testing.T) {
   992  	m := testModule(t, "plan-count-inc")
   993  	p := testProvider("aws")
   994  	p.DiffFn = testDiffFn
   995  	s := &State{
   996  		Modules: []*ModuleState{
   997  			&ModuleState{
   998  				Path: rootModulePath,
   999  				Resources: map[string]*ResourceState{
  1000  					"aws_instance.foo.0": &ResourceState{
  1001  						Type: "aws_instance",
  1002  						Primary: &InstanceState{
  1003  							ID: "bar",
  1004  							Attributes: map[string]string{
  1005  								"foo":  "foo",
  1006  								"type": "aws_instance",
  1007  							},
  1008  						},
  1009  					},
  1010  				},
  1011  			},
  1012  		},
  1013  	}
  1014  	ctx := testContext2(t, &ContextOpts{
  1015  		Module: m,
  1016  		Providers: map[string]ResourceProviderFactory{
  1017  			"aws": testProviderFuncFixed(p),
  1018  		},
  1019  		State: s,
  1020  	})
  1021  
  1022  	plan, err := ctx.Plan()
  1023  	if err != nil {
  1024  		t.Fatalf("err: %s", err)
  1025  	}
  1026  
  1027  	actual := strings.TrimSpace(plan.String())
  1028  	expected := strings.TrimSpace(testTerraformPlanCountIncreaseFromOneStr)
  1029  	if actual != expected {
  1030  		t.Fatalf("bad:\n%s", actual)
  1031  	}
  1032  }
  1033  
  1034  // https://github.com/PeoplePerHour/terraform/pull/11
  1035  //
  1036  // This tests a case where both a "resource" and "resource.0" are in
  1037  // the state file, which apparently is a reasonable backwards compatibility
  1038  // concern found in the above 3rd party repo.
  1039  func TestContext2Plan_countIncreaseFromOneCorrupted(t *testing.T) {
  1040  	m := testModule(t, "plan-count-inc")
  1041  	p := testProvider("aws")
  1042  	p.DiffFn = testDiffFn
  1043  	s := &State{
  1044  		Modules: []*ModuleState{
  1045  			&ModuleState{
  1046  				Path: rootModulePath,
  1047  				Resources: map[string]*ResourceState{
  1048  					"aws_instance.foo": &ResourceState{
  1049  						Type: "aws_instance",
  1050  						Primary: &InstanceState{
  1051  							ID: "bar",
  1052  							Attributes: map[string]string{
  1053  								"foo":  "foo",
  1054  								"type": "aws_instance",
  1055  							},
  1056  						},
  1057  					},
  1058  					"aws_instance.foo.0": &ResourceState{
  1059  						Type: "aws_instance",
  1060  						Primary: &InstanceState{
  1061  							ID: "bar",
  1062  							Attributes: map[string]string{
  1063  								"foo":  "foo",
  1064  								"type": "aws_instance",
  1065  							},
  1066  						},
  1067  					},
  1068  				},
  1069  			},
  1070  		},
  1071  	}
  1072  	ctx := testContext2(t, &ContextOpts{
  1073  		Module: m,
  1074  		Providers: map[string]ResourceProviderFactory{
  1075  			"aws": testProviderFuncFixed(p),
  1076  		},
  1077  		State: s,
  1078  	})
  1079  
  1080  	plan, err := ctx.Plan()
  1081  	if err != nil {
  1082  		t.Fatalf("err: %s", err)
  1083  	}
  1084  
  1085  	actual := strings.TrimSpace(plan.String())
  1086  	expected := strings.TrimSpace(testTerraformPlanCountIncreaseFromOneCorruptedStr)
  1087  	if actual != expected {
  1088  		t.Fatalf("bad:\n%s", actual)
  1089  	}
  1090  }
  1091  
  1092  func TestContext2Plan_destroy(t *testing.T) {
  1093  	m := testModule(t, "plan-destroy")
  1094  	p := testProvider("aws")
  1095  	p.DiffFn = testDiffFn
  1096  	s := &State{
  1097  		Modules: []*ModuleState{
  1098  			&ModuleState{
  1099  				Path: rootModulePath,
  1100  				Resources: map[string]*ResourceState{
  1101  					"aws_instance.one": &ResourceState{
  1102  						Type: "aws_instance",
  1103  						Primary: &InstanceState{
  1104  							ID: "bar",
  1105  						},
  1106  					},
  1107  					"aws_instance.two": &ResourceState{
  1108  						Type: "aws_instance",
  1109  						Primary: &InstanceState{
  1110  							ID: "baz",
  1111  						},
  1112  					},
  1113  				},
  1114  			},
  1115  		},
  1116  	}
  1117  	ctx := testContext2(t, &ContextOpts{
  1118  		Module: m,
  1119  		Providers: map[string]ResourceProviderFactory{
  1120  			"aws": testProviderFuncFixed(p),
  1121  		},
  1122  		State:   s,
  1123  		Destroy: true,
  1124  	})
  1125  
  1126  	plan, err := ctx.Plan()
  1127  	if err != nil {
  1128  		t.Fatalf("err: %s", err)
  1129  	}
  1130  
  1131  	if len(plan.Diff.RootModule().Resources) != 2 {
  1132  		t.Fatalf("bad: %#v", plan.Diff.RootModule().Resources)
  1133  	}
  1134  
  1135  	actual := strings.TrimSpace(plan.String())
  1136  	expected := strings.TrimSpace(testTerraformPlanDestroyStr)
  1137  	if actual != expected {
  1138  		t.Fatalf("bad:\n%s", actual)
  1139  	}
  1140  }
  1141  
  1142  func TestContext2Plan_moduleDestroy(t *testing.T) {
  1143  	m := testModule(t, "plan-module-destroy")
  1144  	p := testProvider("aws")
  1145  	p.DiffFn = testDiffFn
  1146  	s := &State{
  1147  		Modules: []*ModuleState{
  1148  			&ModuleState{
  1149  				Path: rootModulePath,
  1150  				Resources: map[string]*ResourceState{
  1151  					"aws_instance.foo": &ResourceState{
  1152  						Type: "aws_instance",
  1153  						Primary: &InstanceState{
  1154  							ID: "bar",
  1155  						},
  1156  					},
  1157  				},
  1158  			},
  1159  			&ModuleState{
  1160  				Path: []string{"root", "child"},
  1161  				Resources: map[string]*ResourceState{
  1162  					"aws_instance.foo": &ResourceState{
  1163  						Type: "aws_instance",
  1164  						Primary: &InstanceState{
  1165  							ID: "bar",
  1166  						},
  1167  					},
  1168  				},
  1169  			},
  1170  		},
  1171  	}
  1172  	ctx := testContext2(t, &ContextOpts{
  1173  		Module: m,
  1174  		Providers: map[string]ResourceProviderFactory{
  1175  			"aws": testProviderFuncFixed(p),
  1176  		},
  1177  		State:   s,
  1178  		Destroy: true,
  1179  	})
  1180  
  1181  	plan, err := ctx.Plan()
  1182  	if err != nil {
  1183  		t.Fatalf("err: %s", err)
  1184  	}
  1185  
  1186  	actual := strings.TrimSpace(plan.String())
  1187  	expected := strings.TrimSpace(testTerraformPlanModuleDestroyStr)
  1188  	if actual != expected {
  1189  		t.Fatalf("bad:\n%s", actual)
  1190  	}
  1191  }
  1192  
  1193  // GH-1835
  1194  func TestContext2Plan_moduleDestroyCycle(t *testing.T) {
  1195  	m := testModule(t, "plan-module-destroy-gh-1835")
  1196  	p := testProvider("aws")
  1197  	p.DiffFn = testDiffFn
  1198  	s := &State{
  1199  		Modules: []*ModuleState{
  1200  			&ModuleState{
  1201  				Path: []string{"root", "a_module"},
  1202  				Resources: map[string]*ResourceState{
  1203  					"aws_instance.a": &ResourceState{
  1204  						Type: "aws_instance",
  1205  						Primary: &InstanceState{
  1206  							ID: "a",
  1207  						},
  1208  					},
  1209  				},
  1210  			},
  1211  			&ModuleState{
  1212  				Path: []string{"root", "b_module"},
  1213  				Resources: map[string]*ResourceState{
  1214  					"aws_instance.b": &ResourceState{
  1215  						Type: "aws_instance",
  1216  						Primary: &InstanceState{
  1217  							ID: "b",
  1218  						},
  1219  					},
  1220  				},
  1221  			},
  1222  		},
  1223  	}
  1224  	ctx := testContext2(t, &ContextOpts{
  1225  		Module: m,
  1226  		Providers: map[string]ResourceProviderFactory{
  1227  			"aws": testProviderFuncFixed(p),
  1228  		},
  1229  		State:   s,
  1230  		Destroy: true,
  1231  	})
  1232  
  1233  	plan, err := ctx.Plan()
  1234  	if err != nil {
  1235  		t.Fatalf("err: %s", err)
  1236  	}
  1237  
  1238  	actual := strings.TrimSpace(plan.String())
  1239  	expected := strings.TrimSpace(testTerraformPlanModuleDestroyCycleStr)
  1240  	if actual != expected {
  1241  		t.Fatalf("bad:\n%s", actual)
  1242  	}
  1243  }
  1244  
  1245  func TestContext2Plan_moduleDestroyMultivar(t *testing.T) {
  1246  	m := testModule(t, "plan-module-destroy-multivar")
  1247  	p := testProvider("aws")
  1248  	p.DiffFn = testDiffFn
  1249  	s := &State{
  1250  		Modules: []*ModuleState{
  1251  			&ModuleState{
  1252  				Path:      rootModulePath,
  1253  				Resources: map[string]*ResourceState{},
  1254  			},
  1255  			&ModuleState{
  1256  				Path: []string{"root", "child"},
  1257  				Resources: map[string]*ResourceState{
  1258  					"aws_instance.foo.0": &ResourceState{
  1259  						Type: "aws_instance",
  1260  						Primary: &InstanceState{
  1261  							ID: "bar0",
  1262  						},
  1263  					},
  1264  					"aws_instance.foo.1": &ResourceState{
  1265  						Type: "aws_instance",
  1266  						Primary: &InstanceState{
  1267  							ID: "bar1",
  1268  						},
  1269  					},
  1270  				},
  1271  			},
  1272  		},
  1273  	}
  1274  	ctx := testContext2(t, &ContextOpts{
  1275  		Module: m,
  1276  		Providers: map[string]ResourceProviderFactory{
  1277  			"aws": testProviderFuncFixed(p),
  1278  		},
  1279  		State:   s,
  1280  		Destroy: true,
  1281  	})
  1282  
  1283  	plan, err := ctx.Plan()
  1284  	if err != nil {
  1285  		t.Fatalf("err: %s", err)
  1286  	}
  1287  
  1288  	actual := strings.TrimSpace(plan.String())
  1289  	expected := strings.TrimSpace(testTerraformPlanModuleDestroyMultivarStr)
  1290  	if actual != expected {
  1291  		t.Fatalf("bad:\n%s", actual)
  1292  	}
  1293  }
  1294  
  1295  func TestContext2Plan_pathVar(t *testing.T) {
  1296  	cwd, err := os.Getwd()
  1297  	if err != nil {
  1298  		t.Fatalf("err: %s", err)
  1299  	}
  1300  
  1301  	m := testModule(t, "plan-path-var")
  1302  	p := testProvider("aws")
  1303  	p.DiffFn = testDiffFn
  1304  	ctx := testContext2(t, &ContextOpts{
  1305  		Module: m,
  1306  		Providers: map[string]ResourceProviderFactory{
  1307  			"aws": testProviderFuncFixed(p),
  1308  		},
  1309  	})
  1310  
  1311  	plan, err := ctx.Plan()
  1312  	if err != nil {
  1313  		t.Fatalf("err: %s", err)
  1314  	}
  1315  
  1316  	actual := strings.TrimSpace(plan.String())
  1317  	expected := strings.TrimSpace(testTerraformPlanPathVarStr)
  1318  
  1319  	// Warning: this ordering REALLY matters for this test. The
  1320  	// order is: cwd, module, root.
  1321  	expected = fmt.Sprintf(
  1322  		expected,
  1323  		cwd,
  1324  		m.Config().Dir,
  1325  		m.Config().Dir)
  1326  
  1327  	if actual != expected {
  1328  		t.Fatalf("bad:\n%s\n\nexpected:\n\n%s", actual, expected)
  1329  	}
  1330  }
  1331  
  1332  func TestContext2Plan_diffVar(t *testing.T) {
  1333  	m := testModule(t, "plan-diffvar")
  1334  	p := testProvider("aws")
  1335  	s := &State{
  1336  		Modules: []*ModuleState{
  1337  			&ModuleState{
  1338  				Path: rootModulePath,
  1339  				Resources: map[string]*ResourceState{
  1340  					"aws_instance.foo": &ResourceState{
  1341  						Primary: &InstanceState{
  1342  							ID: "bar",
  1343  							Attributes: map[string]string{
  1344  								"num": "2",
  1345  							},
  1346  						},
  1347  					},
  1348  				},
  1349  			},
  1350  		},
  1351  	}
  1352  	ctx := testContext2(t, &ContextOpts{
  1353  		Module: m,
  1354  		Providers: map[string]ResourceProviderFactory{
  1355  			"aws": testProviderFuncFixed(p),
  1356  		},
  1357  		State: s,
  1358  	})
  1359  
  1360  	p.DiffFn = func(
  1361  		info *InstanceInfo,
  1362  		s *InstanceState,
  1363  		c *ResourceConfig) (*InstanceDiff, error) {
  1364  		if s.ID != "bar" {
  1365  			return testDiffFn(info, s, c)
  1366  		}
  1367  
  1368  		return &InstanceDiff{
  1369  			Attributes: map[string]*ResourceAttrDiff{
  1370  				"num": &ResourceAttrDiff{
  1371  					Old: "2",
  1372  					New: "3",
  1373  				},
  1374  			},
  1375  		}, nil
  1376  	}
  1377  
  1378  	plan, err := ctx.Plan()
  1379  	if err != nil {
  1380  		t.Fatalf("err: %s", err)
  1381  	}
  1382  
  1383  	actual := strings.TrimSpace(plan.String())
  1384  	expected := strings.TrimSpace(testTerraformPlanDiffVarStr)
  1385  	if actual != expected {
  1386  		t.Fatalf("actual:\n%s\n\nexpected:\n%s", actual, expected)
  1387  	}
  1388  }
  1389  
  1390  func TestContext2Plan_hook(t *testing.T) {
  1391  	m := testModule(t, "plan-good")
  1392  	h := new(MockHook)
  1393  	p := testProvider("aws")
  1394  	p.DiffFn = testDiffFn
  1395  	ctx := testContext2(t, &ContextOpts{
  1396  		Module: m,
  1397  		Hooks:  []Hook{h},
  1398  		Providers: map[string]ResourceProviderFactory{
  1399  			"aws": testProviderFuncFixed(p),
  1400  		},
  1401  	})
  1402  
  1403  	_, err := ctx.Plan()
  1404  	if err != nil {
  1405  		t.Fatalf("err: %s", err)
  1406  	}
  1407  
  1408  	if !h.PreDiffCalled {
  1409  		t.Fatal("should be called")
  1410  	}
  1411  	if !h.PostDiffCalled {
  1412  		t.Fatal("should be called")
  1413  	}
  1414  }
  1415  
  1416  func TestContext2Plan_orphan(t *testing.T) {
  1417  	m := testModule(t, "plan-orphan")
  1418  	p := testProvider("aws")
  1419  	p.DiffFn = testDiffFn
  1420  	s := &State{
  1421  		Modules: []*ModuleState{
  1422  			&ModuleState{
  1423  				Path: rootModulePath,
  1424  				Resources: map[string]*ResourceState{
  1425  					"aws_instance.baz": &ResourceState{
  1426  						Type: "aws_instance",
  1427  						Primary: &InstanceState{
  1428  							ID: "bar",
  1429  						},
  1430  					},
  1431  				},
  1432  			},
  1433  		},
  1434  	}
  1435  	ctx := testContext2(t, &ContextOpts{
  1436  		Module: m,
  1437  		Providers: map[string]ResourceProviderFactory{
  1438  			"aws": testProviderFuncFixed(p),
  1439  		},
  1440  		State: s,
  1441  	})
  1442  
  1443  	plan, err := ctx.Plan()
  1444  	if err != nil {
  1445  		t.Fatalf("err: %s", err)
  1446  	}
  1447  
  1448  	actual := strings.TrimSpace(plan.String())
  1449  	expected := strings.TrimSpace(testTerraformPlanOrphanStr)
  1450  	if actual != expected {
  1451  		t.Fatalf("bad:\n%s", actual)
  1452  	}
  1453  }
  1454  
  1455  func TestContext2Plan_state(t *testing.T) {
  1456  	m := testModule(t, "plan-good")
  1457  	p := testProvider("aws")
  1458  	p.DiffFn = testDiffFn
  1459  	s := &State{
  1460  		Modules: []*ModuleState{
  1461  			&ModuleState{
  1462  				Path: rootModulePath,
  1463  				Resources: map[string]*ResourceState{
  1464  					"aws_instance.foo": &ResourceState{
  1465  						Primary: &InstanceState{
  1466  							ID: "bar",
  1467  						},
  1468  					},
  1469  				},
  1470  			},
  1471  		},
  1472  	}
  1473  	ctx := testContext2(t, &ContextOpts{
  1474  		Module: m,
  1475  		Providers: map[string]ResourceProviderFactory{
  1476  			"aws": testProviderFuncFixed(p),
  1477  		},
  1478  		State: s,
  1479  	})
  1480  
  1481  	plan, err := ctx.Plan()
  1482  	if err != nil {
  1483  		t.Fatalf("err: %s", err)
  1484  	}
  1485  
  1486  	if len(plan.Diff.RootModule().Resources) < 2 {
  1487  		t.Fatalf("bad: %#v", plan.Diff.RootModule().Resources)
  1488  	}
  1489  
  1490  	actual := strings.TrimSpace(plan.String())
  1491  	expected := strings.TrimSpace(testTerraformPlanStateStr)
  1492  	if actual != expected {
  1493  		t.Fatalf("bad:\n%s\n\nexpected:\n\n%s", actual, expected)
  1494  	}
  1495  }
  1496  
  1497  func TestContext2Plan_taint(t *testing.T) {
  1498  	m := testModule(t, "plan-taint")
  1499  	p := testProvider("aws")
  1500  	p.DiffFn = testDiffFn
  1501  	s := &State{
  1502  		Modules: []*ModuleState{
  1503  			&ModuleState{
  1504  				Path: rootModulePath,
  1505  				Resources: map[string]*ResourceState{
  1506  					"aws_instance.foo": &ResourceState{
  1507  						Type: "aws_instance",
  1508  						Primary: &InstanceState{
  1509  							ID:         "bar",
  1510  							Attributes: map[string]string{"num": "2"},
  1511  						},
  1512  					},
  1513  					"aws_instance.bar": &ResourceState{
  1514  						Type: "aws_instance",
  1515  						Tainted: []*InstanceState{
  1516  							&InstanceState{
  1517  								ID: "baz",
  1518  							},
  1519  						},
  1520  					},
  1521  				},
  1522  			},
  1523  		},
  1524  	}
  1525  	ctx := testContext2(t, &ContextOpts{
  1526  		Module: m,
  1527  		Providers: map[string]ResourceProviderFactory{
  1528  			"aws": testProviderFuncFixed(p),
  1529  		},
  1530  		State: s,
  1531  	})
  1532  
  1533  	plan, err := ctx.Plan()
  1534  	if err != nil {
  1535  		t.Fatalf("err: %s", err)
  1536  	}
  1537  
  1538  	actual := strings.TrimSpace(plan.String())
  1539  	expected := strings.TrimSpace(testTerraformPlanTaintStr)
  1540  	if actual != expected {
  1541  		t.Fatalf("bad:\n%s", actual)
  1542  	}
  1543  }
  1544  
  1545  func TestContext2Plan_multiple_taint(t *testing.T) {
  1546  	m := testModule(t, "plan-taint")
  1547  	p := testProvider("aws")
  1548  	p.DiffFn = testDiffFn
  1549  	s := &State{
  1550  		Modules: []*ModuleState{
  1551  			&ModuleState{
  1552  				Path: rootModulePath,
  1553  				Resources: map[string]*ResourceState{
  1554  					"aws_instance.foo": &ResourceState{
  1555  						Type: "aws_instance",
  1556  						Primary: &InstanceState{
  1557  							ID:         "bar",
  1558  							Attributes: map[string]string{"num": "2"},
  1559  						},
  1560  					},
  1561  					"aws_instance.bar": &ResourceState{
  1562  						Type: "aws_instance",
  1563  						Tainted: []*InstanceState{
  1564  							&InstanceState{
  1565  								ID: "baz",
  1566  							},
  1567  							&InstanceState{
  1568  								ID: "zip",
  1569  							},
  1570  						},
  1571  					},
  1572  				},
  1573  			},
  1574  		},
  1575  	}
  1576  	ctx := testContext2(t, &ContextOpts{
  1577  		Module: m,
  1578  		Providers: map[string]ResourceProviderFactory{
  1579  			"aws": testProviderFuncFixed(p),
  1580  		},
  1581  		State: s,
  1582  	})
  1583  
  1584  	plan, err := ctx.Plan()
  1585  	if err != nil {
  1586  		t.Fatalf("err: %s", err)
  1587  	}
  1588  
  1589  	actual := strings.TrimSpace(plan.String())
  1590  	expected := strings.TrimSpace(testTerraformPlanMultipleTaintStr)
  1591  	if actual != expected {
  1592  		t.Fatalf("bad:\n%s", actual)
  1593  	}
  1594  }
  1595  
  1596  func TestContext2Plan_targeted(t *testing.T) {
  1597  	m := testModule(t, "plan-targeted")
  1598  	p := testProvider("aws")
  1599  	p.DiffFn = testDiffFn
  1600  	ctx := testContext2(t, &ContextOpts{
  1601  		Module: m,
  1602  		Providers: map[string]ResourceProviderFactory{
  1603  			"aws": testProviderFuncFixed(p),
  1604  		},
  1605  		Targets: []string{"aws_instance.foo"},
  1606  	})
  1607  
  1608  	plan, err := ctx.Plan()
  1609  	if err != nil {
  1610  		t.Fatalf("err: %s", err)
  1611  	}
  1612  
  1613  	actual := strings.TrimSpace(plan.String())
  1614  	expected := strings.TrimSpace(`
  1615  DIFF:
  1616  
  1617  CREATE: aws_instance.foo
  1618    num:  "" => "2"
  1619    type: "" => "aws_instance"
  1620  
  1621  STATE:
  1622  
  1623  <no state>
  1624  	`)
  1625  	if actual != expected {
  1626  		t.Fatalf("expected:\n%s\n\ngot:\n%s", expected, actual)
  1627  	}
  1628  }
  1629  
  1630  func TestContext2Plan_targetedOrphan(t *testing.T) {
  1631  	m := testModule(t, "plan-targeted-orphan")
  1632  	p := testProvider("aws")
  1633  	p.DiffFn = testDiffFn
  1634  	ctx := testContext2(t, &ContextOpts{
  1635  		Module: m,
  1636  		Providers: map[string]ResourceProviderFactory{
  1637  			"aws": testProviderFuncFixed(p),
  1638  		},
  1639  		State: &State{
  1640  			Modules: []*ModuleState{
  1641  				&ModuleState{
  1642  					Path: rootModulePath,
  1643  					Resources: map[string]*ResourceState{
  1644  						"aws_instance.orphan": &ResourceState{
  1645  							Type: "aws_instance",
  1646  							Primary: &InstanceState{
  1647  								ID: "i-789xyz",
  1648  							},
  1649  						},
  1650  					},
  1651  				},
  1652  			},
  1653  		},
  1654  		Destroy: true,
  1655  		Targets: []string{"aws_instance.orphan"},
  1656  	})
  1657  
  1658  	plan, err := ctx.Plan()
  1659  	if err != nil {
  1660  		t.Fatalf("err: %s", err)
  1661  	}
  1662  
  1663  	actual := strings.TrimSpace(plan.String())
  1664  	expected := strings.TrimSpace(`DIFF:
  1665  
  1666  DESTROY: aws_instance.orphan
  1667  
  1668  STATE:
  1669  
  1670  aws_instance.orphan:
  1671    ID = i-789xyz`)
  1672  	if actual != expected {
  1673  		t.Fatalf("expected:\n%s\n\ngot:\n%s", expected, actual)
  1674  	}
  1675  }
  1676  
  1677  func TestContext2Plan_provider(t *testing.T) {
  1678  	m := testModule(t, "plan-provider")
  1679  	p := testProvider("aws")
  1680  	p.DiffFn = testDiffFn
  1681  
  1682  	var value interface{}
  1683  	p.ConfigureFn = func(c *ResourceConfig) error {
  1684  		value, _ = c.Get("foo")
  1685  		return nil
  1686  	}
  1687  
  1688  	ctx := testContext2(t, &ContextOpts{
  1689  		Module: m,
  1690  		Providers: map[string]ResourceProviderFactory{
  1691  			"aws": testProviderFuncFixed(p),
  1692  		},
  1693  		Variables: map[string]string{
  1694  			"foo": "bar",
  1695  		},
  1696  	})
  1697  
  1698  	if _, err := ctx.Plan(); err != nil {
  1699  		t.Fatalf("err: %s", err)
  1700  	}
  1701  
  1702  	if value != "bar" {
  1703  		t.Fatalf("bad: %#v", value)
  1704  	}
  1705  }
  1706  
  1707  func TestContext2Plan_varListErr(t *testing.T) {
  1708  	m := testModule(t, "plan-var-list-err")
  1709  	p := testProvider("aws")
  1710  	ctx := testContext2(t, &ContextOpts{
  1711  		Module: m,
  1712  		Providers: map[string]ResourceProviderFactory{
  1713  			"aws": testProviderFuncFixed(p),
  1714  		},
  1715  	})
  1716  
  1717  	_, err := ctx.Plan()
  1718  	if err == nil {
  1719  		t.Fatal("should error")
  1720  	}
  1721  }
  1722  
  1723  func TestContext2Plan_ignoreChanges(t *testing.T) {
  1724  	m := testModule(t, "plan-ignore-changes")
  1725  	p := testProvider("aws")
  1726  	p.DiffFn = testDiffFn
  1727  	s := &State{
  1728  		Modules: []*ModuleState{
  1729  			&ModuleState{
  1730  				Path: rootModulePath,
  1731  				Resources: map[string]*ResourceState{
  1732  					"aws_instance.foo": &ResourceState{
  1733  						Primary: &InstanceState{
  1734  							ID:         "bar",
  1735  							Attributes: map[string]string{"ami": "ami-abcd1234"},
  1736  						},
  1737  					},
  1738  				},
  1739  			},
  1740  		},
  1741  	}
  1742  	ctx := testContext2(t, &ContextOpts{
  1743  		Module: m,
  1744  		Providers: map[string]ResourceProviderFactory{
  1745  			"aws": testProviderFuncFixed(p),
  1746  		},
  1747  		Variables: map[string]string{
  1748  			"foo": "ami-1234abcd",
  1749  		},
  1750  		State: s,
  1751  	})
  1752  
  1753  	plan, err := ctx.Plan()
  1754  	if err != nil {
  1755  		t.Fatalf("err: %s", err)
  1756  	}
  1757  
  1758  	if len(plan.Diff.RootModule().Resources) < 1 {
  1759  		t.Fatalf("bad: %#v", plan.Diff.RootModule().Resources)
  1760  	}
  1761  
  1762  	actual := strings.TrimSpace(plan.String())
  1763  	expected := strings.TrimSpace(testTerraformPlanIgnoreChangesStr)
  1764  	if actual != expected {
  1765  		t.Fatalf("bad:\n%s\n\nexpected\n\n%s", actual, expected)
  1766  	}
  1767  }