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