github.com/danrjohnson/terraform@v0.7.0-rc2.0.20160627135212-d0fc1fa086ff/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_escapedVar(t *testing.T) {
   108  	m := testModule(t, "plan-escaped-var")
   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(testTerraformPlanEscapedVarStr)
   125  	if actual != expected {
   126  		t.Fatalf("bad:\n%s", actual)
   127  	}
   128  }
   129  
   130  func TestContext2Plan_minimal(t *testing.T) {
   131  	m := testModule(t, "plan-empty")
   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(testTerraformPlanEmptyStr)
   148  	if actual != expected {
   149  		t.Fatalf("bad:\n%s", actual)
   150  	}
   151  }
   152  
   153  func TestContext2Plan_modules(t *testing.T) {
   154  	m := testModule(t, "plan-modules")
   155  	p := testProvider("aws")
   156  	p.DiffFn = testDiffFn
   157  	ctx := testContext2(t, &ContextOpts{
   158  		Module: m,
   159  		Providers: map[string]ResourceProviderFactory{
   160  			"aws": testProviderFuncFixed(p),
   161  		},
   162  	})
   163  
   164  	plan, err := ctx.Plan()
   165  	if err != nil {
   166  		t.Fatalf("err: %s", err)
   167  	}
   168  
   169  	actual := strings.TrimSpace(plan.String())
   170  	expected := strings.TrimSpace(testTerraformPlanModulesStr)
   171  	if actual != expected {
   172  		t.Fatalf("bad:\n%s", actual)
   173  	}
   174  }
   175  
   176  // GH-1475
   177  func TestContext2Plan_moduleCycle(t *testing.T) {
   178  	m := testModule(t, "plan-module-cycle")
   179  	p := testProvider("aws")
   180  	p.DiffFn = testDiffFn
   181  	ctx := testContext2(t, &ContextOpts{
   182  		Module: m,
   183  		Providers: map[string]ResourceProviderFactory{
   184  			"aws": testProviderFuncFixed(p),
   185  		},
   186  	})
   187  
   188  	plan, err := ctx.Plan()
   189  	if err != nil {
   190  		t.Fatalf("err: %s", err)
   191  	}
   192  
   193  	actual := strings.TrimSpace(plan.String())
   194  	expected := strings.TrimSpace(testTerraformPlanModuleCycleStr)
   195  	if actual != expected {
   196  		t.Fatalf("bad:\n%s", actual)
   197  	}
   198  }
   199  
   200  func TestContext2Plan_moduleDeadlock(t *testing.T) {
   201  	testCheckDeadlock(t, func() {
   202  		m := testModule(t, "plan-module-deadlock")
   203  		p := testProvider("aws")
   204  		p.DiffFn = testDiffFn
   205  
   206  		ctx := testContext2(t, &ContextOpts{
   207  			Module: m,
   208  			Providers: map[string]ResourceProviderFactory{
   209  				"aws": testProviderFuncFixed(p),
   210  			},
   211  		})
   212  
   213  		plan, err := ctx.Plan()
   214  		if err != nil {
   215  			t.Fatalf("err: %s", err)
   216  		}
   217  
   218  		actual := strings.TrimSpace(plan.String())
   219  		expected := strings.TrimSpace(`
   220  DIFF:
   221  
   222  module.child:
   223    CREATE: aws_instance.foo.0
   224    CREATE: aws_instance.foo.1
   225    CREATE: aws_instance.foo.2
   226  
   227  STATE:
   228  
   229  <no state>
   230  		`)
   231  		if actual != expected {
   232  			t.Fatalf("expected:\n%sgot:\n%s", expected, actual)
   233  		}
   234  	})
   235  }
   236  
   237  func TestContext2Plan_moduleInput(t *testing.T) {
   238  	m := testModule(t, "plan-module-input")
   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(testTerraformPlanModuleInputStr)
   255  	if actual != expected {
   256  		t.Fatalf("bad:\n%s", actual)
   257  	}
   258  }
   259  
   260  func TestContext2Plan_moduleInputComputed(t *testing.T) {
   261  	m := testModule(t, "plan-module-input-computed")
   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  	})
   270  
   271  	plan, err := ctx.Plan()
   272  	if err != nil {
   273  		t.Fatalf("err: %s", err)
   274  	}
   275  
   276  	actual := strings.TrimSpace(plan.String())
   277  	expected := strings.TrimSpace(testTerraformPlanModuleInputComputedStr)
   278  	if actual != expected {
   279  		t.Fatalf("bad:\n%s", actual)
   280  	}
   281  }
   282  
   283  func TestContext2Plan_moduleInputFromVar(t *testing.T) {
   284  	m := testModule(t, "plan-module-input-var")
   285  	p := testProvider("aws")
   286  	p.DiffFn = testDiffFn
   287  	ctx := testContext2(t, &ContextOpts{
   288  		Module: m,
   289  		Providers: map[string]ResourceProviderFactory{
   290  			"aws": testProviderFuncFixed(p),
   291  		},
   292  		Variables: map[string]string{
   293  			"foo": "52",
   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(testTerraformPlanModuleInputVarStr)
   304  	if actual != expected {
   305  		t.Fatalf("bad:\n%s", actual)
   306  	}
   307  }
   308  
   309  func TestContext2Plan_moduleMultiVar(t *testing.T) {
   310  	m := testModule(t, "plan-module-multi-var")
   311  	p := testProvider("aws")
   312  	p.DiffFn = testDiffFn
   313  	ctx := testContext2(t, &ContextOpts{
   314  		Module: m,
   315  		Providers: map[string]ResourceProviderFactory{
   316  			"aws": testProviderFuncFixed(p),
   317  		},
   318  	})
   319  
   320  	plan, err := ctx.Plan()
   321  	if err != nil {
   322  		t.Fatalf("err: %s", err)
   323  	}
   324  
   325  	actual := strings.TrimSpace(plan.String())
   326  	expected := strings.TrimSpace(testTerraformPlanModuleMultiVarStr)
   327  	if actual != expected {
   328  		t.Fatalf("bad:\n%s", actual)
   329  	}
   330  }
   331  
   332  func TestContext2Plan_moduleOrphans(t *testing.T) {
   333  	m := testModule(t, "plan-modules-remove")
   334  	p := testProvider("aws")
   335  	p.DiffFn = testDiffFn
   336  	s := &State{
   337  		Modules: []*ModuleState{
   338  			&ModuleState{
   339  				Path: []string{"root", "child"},
   340  				Resources: map[string]*ResourceState{
   341  					"aws_instance.foo": &ResourceState{
   342  						Type: "aws_instance",
   343  						Primary: &InstanceState{
   344  							ID: "baz",
   345  						},
   346  					},
   347  				},
   348  			},
   349  		},
   350  	}
   351  	ctx := testContext2(t, &ContextOpts{
   352  		Module: m,
   353  		Providers: map[string]ResourceProviderFactory{
   354  			"aws": testProviderFuncFixed(p),
   355  		},
   356  		State: s,
   357  	})
   358  
   359  	plan, err := ctx.Plan()
   360  	if err != nil {
   361  		t.Fatalf("err: %s", err)
   362  	}
   363  
   364  	actual := strings.TrimSpace(plan.String())
   365  	expected := strings.TrimSpace(testTerraformPlanModuleOrphansStr)
   366  	if actual != expected {
   367  		t.Fatalf("bad:\n%s", actual)
   368  	}
   369  }
   370  
   371  // https://github.com/hashicorp/terraform/issues/3114
   372  func TestContext2Plan_moduleOrphansWithProvisioner(t *testing.T) {
   373  	m := testModule(t, "plan-modules-remove-provisioners")
   374  	p := testProvider("aws")
   375  	pr := testProvisioner()
   376  	p.DiffFn = testDiffFn
   377  	s := &State{
   378  		Modules: []*ModuleState{
   379  			&ModuleState{
   380  				Path: []string{"root"},
   381  				Resources: map[string]*ResourceState{
   382  					"aws_instance.top": &ResourceState{
   383  						Type: "aws_instance",
   384  						Primary: &InstanceState{
   385  							ID: "top",
   386  						},
   387  					},
   388  				},
   389  			},
   390  			&ModuleState{
   391  				Path: []string{"root", "parent", "childone"},
   392  				Resources: map[string]*ResourceState{
   393  					"aws_instance.foo": &ResourceState{
   394  						Type: "aws_instance",
   395  						Primary: &InstanceState{
   396  							ID: "baz",
   397  						},
   398  					},
   399  				},
   400  			},
   401  			&ModuleState{
   402  				Path: []string{"root", "parent", "childtwo"},
   403  				Resources: map[string]*ResourceState{
   404  					"aws_instance.foo": &ResourceState{
   405  						Type: "aws_instance",
   406  						Primary: &InstanceState{
   407  							ID: "baz",
   408  						},
   409  					},
   410  				},
   411  			},
   412  		},
   413  	}
   414  	ctx := testContext2(t, &ContextOpts{
   415  		Module: m,
   416  		Providers: map[string]ResourceProviderFactory{
   417  			"aws": testProviderFuncFixed(p),
   418  		},
   419  		Provisioners: map[string]ResourceProvisionerFactory{
   420  			"shell": testProvisionerFuncFixed(pr),
   421  		},
   422  		State: s,
   423  	})
   424  
   425  	plan, err := ctx.Plan()
   426  	if err != nil {
   427  		t.Fatalf("err: %s", err)
   428  	}
   429  
   430  	actual := strings.TrimSpace(plan.String())
   431  	expected := strings.TrimSpace(`
   432  DIFF:
   433  
   434  module.parent.childone:
   435    DESTROY: aws_instance.foo
   436  module.parent.childtwo:
   437    DESTROY: aws_instance.foo
   438  
   439  STATE:
   440  
   441  aws_instance.top:
   442    ID = top
   443  
   444  module.parent.childone:
   445    aws_instance.foo:
   446      ID = baz
   447  module.parent.childtwo:
   448    aws_instance.foo:
   449      ID = baz
   450  	`)
   451  	if actual != expected {
   452  		t.Fatalf("bad:\n%s", actual)
   453  	}
   454  }
   455  
   456  func TestContext2Plan_moduleProviderInherit(t *testing.T) {
   457  	var l sync.Mutex
   458  	var calls []string
   459  
   460  	m := testModule(t, "plan-module-provider-inherit")
   461  	ctx := testContext2(t, &ContextOpts{
   462  		Module: m,
   463  		Providers: map[string]ResourceProviderFactory{
   464  			"aws": func() (ResourceProvider, error) {
   465  				l.Lock()
   466  				defer l.Unlock()
   467  
   468  				p := testProvider("aws")
   469  				p.ConfigureFn = func(c *ResourceConfig) error {
   470  					if v, ok := c.Get("from"); !ok || v.(string) != "root" {
   471  						return fmt.Errorf("bad")
   472  					}
   473  
   474  					return nil
   475  				}
   476  				p.DiffFn = func(
   477  					info *InstanceInfo,
   478  					state *InstanceState,
   479  					c *ResourceConfig) (*InstanceDiff, error) {
   480  					v, _ := c.Get("from")
   481  					calls = append(calls, v.(string))
   482  					return testDiffFn(info, state, c)
   483  				}
   484  				return p, nil
   485  			},
   486  		},
   487  	})
   488  
   489  	_, err := ctx.Plan()
   490  	if err != nil {
   491  		t.Fatalf("err: %s", err)
   492  	}
   493  
   494  	actual := calls
   495  	sort.Strings(actual)
   496  	expected := []string{"child", "root"}
   497  	if !reflect.DeepEqual(actual, expected) {
   498  		t.Fatalf("bad: %#v", actual)
   499  	}
   500  }
   501  
   502  func TestContext2Plan_moduleProviderDefaults(t *testing.T) {
   503  	var l sync.Mutex
   504  	var calls []string
   505  	toCount := 0
   506  
   507  	m := testModule(t, "plan-module-provider-defaults")
   508  	ctx := testContext2(t, &ContextOpts{
   509  		Module: m,
   510  		Providers: map[string]ResourceProviderFactory{
   511  			"aws": func() (ResourceProvider, error) {
   512  				l.Lock()
   513  				defer l.Unlock()
   514  
   515  				p := testProvider("aws")
   516  				p.ConfigureFn = func(c *ResourceConfig) error {
   517  					if v, ok := c.Get("from"); !ok || v.(string) != "root" {
   518  						return fmt.Errorf("bad")
   519  					}
   520  					if v, ok := c.Get("to"); ok && v.(string) == "child" {
   521  						toCount++
   522  					}
   523  
   524  					return nil
   525  				}
   526  				p.DiffFn = func(
   527  					info *InstanceInfo,
   528  					state *InstanceState,
   529  					c *ResourceConfig) (*InstanceDiff, error) {
   530  					v, _ := c.Get("from")
   531  					calls = append(calls, v.(string))
   532  					return testDiffFn(info, state, c)
   533  				}
   534  				return p, nil
   535  			},
   536  		},
   537  	})
   538  
   539  	_, err := ctx.Plan()
   540  	if err != nil {
   541  		t.Fatalf("err: %s", err)
   542  	}
   543  
   544  	if toCount != 1 {
   545  		t.Fatalf(
   546  			"provider in child didn't set proper config\n\n"+
   547  				"toCount: %d", toCount)
   548  	}
   549  
   550  	actual := calls
   551  	sort.Strings(actual)
   552  	expected := []string{"child", "root"}
   553  	if !reflect.DeepEqual(actual, expected) {
   554  		t.Fatalf("bad: %#v", actual)
   555  	}
   556  }
   557  
   558  func TestContext2Plan_moduleProviderDefaultsVar(t *testing.T) {
   559  	var l sync.Mutex
   560  	var calls []string
   561  
   562  	m := testModule(t, "plan-module-provider-defaults-var")
   563  	ctx := testContext2(t, &ContextOpts{
   564  		Module: m,
   565  		Providers: map[string]ResourceProviderFactory{
   566  			"aws": func() (ResourceProvider, error) {
   567  				l.Lock()
   568  				defer l.Unlock()
   569  
   570  				p := testProvider("aws")
   571  				p.ConfigureFn = func(c *ResourceConfig) error {
   572  					var buf bytes.Buffer
   573  					if v, ok := c.Get("from"); ok {
   574  						buf.WriteString(v.(string) + "\n")
   575  					}
   576  					if v, ok := c.Get("to"); ok {
   577  						buf.WriteString(v.(string) + "\n")
   578  					}
   579  
   580  					calls = append(calls, buf.String())
   581  					return nil
   582  				}
   583  				p.DiffFn = testDiffFn
   584  				return p, nil
   585  			},
   586  		},
   587  		Variables: map[string]string{
   588  			"foo": "root",
   589  		},
   590  	})
   591  
   592  	_, err := ctx.Plan()
   593  	if err != nil {
   594  		t.Fatalf("err: %s", err)
   595  	}
   596  
   597  	expected := []string{
   598  		"root\n",
   599  		"root\nchild\n",
   600  	}
   601  	if !reflect.DeepEqual(calls, expected) {
   602  		t.Fatalf("BAD: %#v", calls)
   603  	}
   604  }
   605  
   606  func TestContext2Plan_moduleVar(t *testing.T) {
   607  	m := testModule(t, "plan-module-var")
   608  	p := testProvider("aws")
   609  	p.DiffFn = testDiffFn
   610  	ctx := testContext2(t, &ContextOpts{
   611  		Module: m,
   612  		Providers: map[string]ResourceProviderFactory{
   613  			"aws": testProviderFuncFixed(p),
   614  		},
   615  	})
   616  
   617  	plan, err := ctx.Plan()
   618  	if err != nil {
   619  		t.Fatalf("err: %s", err)
   620  	}
   621  
   622  	actual := strings.TrimSpace(plan.String())
   623  	expected := strings.TrimSpace(testTerraformPlanModuleVarStr)
   624  	if actual != expected {
   625  		t.Fatalf("bad:\n%s", actual)
   626  	}
   627  }
   628  
   629  func TestContext2Plan_moduleVarWrongType(t *testing.T) {
   630  	m := testModule(t, "plan-module-wrong-var-type")
   631  	p := testProvider("aws")
   632  	p.DiffFn = testDiffFn
   633  	ctx := testContext2(t, &ContextOpts{
   634  		Module: m,
   635  		Providers: map[string]ResourceProviderFactory{
   636  			"aws": testProviderFuncFixed(p),
   637  		},
   638  	})
   639  
   640  	_, err := ctx.Plan()
   641  	if err == nil {
   642  		t.Fatalf("should error")
   643  	}
   644  }
   645  
   646  func TestContext2Plan_moduleVarWrongTypeNested(t *testing.T) {
   647  	m := testModule(t, "plan-module-wrong-var-type-nested")
   648  	p := testProvider("aws")
   649  	p.DiffFn = testDiffFn
   650  	ctx := testContext2(t, &ContextOpts{
   651  		Module: m,
   652  		Providers: map[string]ResourceProviderFactory{
   653  			"aws": testProviderFuncFixed(p),
   654  		},
   655  	})
   656  
   657  	_, err := ctx.Plan()
   658  	if err == nil {
   659  		t.Fatalf("should error")
   660  	}
   661  }
   662  
   663  func TestContext2Plan_moduleVarWithDefaultValue(t *testing.T) {
   664  	m := testModule(t, "plan-module-var-with-default-value")
   665  	p := testProvider("null")
   666  	p.DiffFn = testDiffFn
   667  	ctx := testContext2(t, &ContextOpts{
   668  		Module: m,
   669  		Providers: map[string]ResourceProviderFactory{
   670  			"null": testProviderFuncFixed(p),
   671  		},
   672  	})
   673  
   674  	_, err := ctx.Plan()
   675  	if err != nil {
   676  		t.Fatalf("bad: %s", err)
   677  	}
   678  }
   679  
   680  func TestContext2Plan_moduleVarComputed(t *testing.T) {
   681  	m := testModule(t, "plan-module-var-computed")
   682  	p := testProvider("aws")
   683  	p.DiffFn = testDiffFn
   684  	ctx := testContext2(t, &ContextOpts{
   685  		Module: m,
   686  		Providers: map[string]ResourceProviderFactory{
   687  			"aws": testProviderFuncFixed(p),
   688  		},
   689  	})
   690  
   691  	plan, err := ctx.Plan()
   692  	if err != nil {
   693  		t.Fatalf("err: %s", err)
   694  	}
   695  
   696  	actual := strings.TrimSpace(plan.String())
   697  	expected := strings.TrimSpace(testTerraformPlanModuleVarComputedStr)
   698  	if actual != expected {
   699  		t.Fatalf("bad:\n%s", actual)
   700  	}
   701  }
   702  
   703  func TestContext2Plan_nil(t *testing.T) {
   704  	m := testModule(t, "plan-nil")
   705  	p := testProvider("aws")
   706  	p.DiffFn = testDiffFn
   707  	ctx := testContext2(t, &ContextOpts{
   708  		Module: m,
   709  		Providers: map[string]ResourceProviderFactory{
   710  			"aws": testProviderFuncFixed(p),
   711  		},
   712  		State: &State{
   713  			Modules: []*ModuleState{
   714  				&ModuleState{
   715  					Path: rootModulePath,
   716  					Resources: map[string]*ResourceState{
   717  						"aws_instance.foo": &ResourceState{
   718  							Type: "aws_instance",
   719  							Primary: &InstanceState{
   720  								ID: "bar",
   721  							},
   722  						},
   723  					},
   724  				},
   725  			},
   726  		},
   727  	})
   728  
   729  	plan, err := ctx.Plan()
   730  	if err != nil {
   731  		t.Fatalf("err: %s", err)
   732  	}
   733  	if len(plan.Diff.RootModule().Resources) != 0 {
   734  		t.Fatalf("bad: %#v", plan.Diff.RootModule().Resources)
   735  	}
   736  }
   737  
   738  func TestContext2Plan_preventDestroy_bad(t *testing.T) {
   739  	m := testModule(t, "plan-prevent-destroy-bad")
   740  	p := testProvider("aws")
   741  	p.DiffFn = testDiffFn
   742  	ctx := testContext2(t, &ContextOpts{
   743  		Module: m,
   744  		Providers: map[string]ResourceProviderFactory{
   745  			"aws": testProviderFuncFixed(p),
   746  		},
   747  		State: &State{
   748  			Modules: []*ModuleState{
   749  				&ModuleState{
   750  					Path: rootModulePath,
   751  					Resources: map[string]*ResourceState{
   752  						"aws_instance.foo": &ResourceState{
   753  							Type: "aws_instance",
   754  							Primary: &InstanceState{
   755  								ID: "i-abc123",
   756  							},
   757  						},
   758  					},
   759  				},
   760  			},
   761  		},
   762  	})
   763  
   764  	plan, err := ctx.Plan()
   765  
   766  	expectedErr := "aws_instance.foo: the plan would destroy"
   767  	if !strings.Contains(fmt.Sprintf("%s", err), expectedErr) {
   768  		t.Fatalf("expected err would contain %q\nerr: %s\nplan: %s",
   769  			expectedErr, err, plan)
   770  	}
   771  }
   772  
   773  func TestContext2Plan_preventDestroy_good(t *testing.T) {
   774  	m := testModule(t, "plan-prevent-destroy-good")
   775  	p := testProvider("aws")
   776  	p.DiffFn = testDiffFn
   777  	ctx := testContext2(t, &ContextOpts{
   778  		Module: m,
   779  		Providers: map[string]ResourceProviderFactory{
   780  			"aws": testProviderFuncFixed(p),
   781  		},
   782  		State: &State{
   783  			Modules: []*ModuleState{
   784  				&ModuleState{
   785  					Path: rootModulePath,
   786  					Resources: map[string]*ResourceState{
   787  						"aws_instance.foo": &ResourceState{
   788  							Type: "aws_instance",
   789  							Primary: &InstanceState{
   790  								ID: "i-abc123",
   791  							},
   792  						},
   793  					},
   794  				},
   795  			},
   796  		},
   797  	})
   798  
   799  	plan, err := ctx.Plan()
   800  	if err != nil {
   801  		t.Fatalf("err: %s", err)
   802  	}
   803  	if !plan.Diff.Empty() {
   804  		t.Fatalf("Expected empty plan, got %s", plan.String())
   805  	}
   806  }
   807  
   808  func TestContext2Plan_preventDestroy_destroyPlan(t *testing.T) {
   809  	m := testModule(t, "plan-prevent-destroy-good")
   810  	p := testProvider("aws")
   811  	p.DiffFn = testDiffFn
   812  	ctx := testContext2(t, &ContextOpts{
   813  		Module: m,
   814  		Providers: map[string]ResourceProviderFactory{
   815  			"aws": testProviderFuncFixed(p),
   816  		},
   817  		State: &State{
   818  			Modules: []*ModuleState{
   819  				&ModuleState{
   820  					Path: rootModulePath,
   821  					Resources: map[string]*ResourceState{
   822  						"aws_instance.foo": &ResourceState{
   823  							Type: "aws_instance",
   824  							Primary: &InstanceState{
   825  								ID: "i-abc123",
   826  							},
   827  						},
   828  					},
   829  				},
   830  			},
   831  		},
   832  		Destroy: true,
   833  	})
   834  
   835  	plan, err := ctx.Plan()
   836  
   837  	expectedErr := "aws_instance.foo: the plan would destroy"
   838  	if !strings.Contains(fmt.Sprintf("%s", err), expectedErr) {
   839  		t.Fatalf("expected err would contain %q\nerr: %s\nplan: %s",
   840  			expectedErr, err, plan)
   841  	}
   842  }
   843  
   844  func TestContext2Plan_computed(t *testing.T) {
   845  	m := testModule(t, "plan-computed")
   846  	p := testProvider("aws")
   847  	p.DiffFn = testDiffFn
   848  	ctx := testContext2(t, &ContextOpts{
   849  		Module: m,
   850  		Providers: map[string]ResourceProviderFactory{
   851  			"aws": testProviderFuncFixed(p),
   852  		},
   853  	})
   854  
   855  	plan, err := ctx.Plan()
   856  	if err != nil {
   857  		t.Fatalf("err: %s", err)
   858  	}
   859  
   860  	actual := strings.TrimSpace(plan.String())
   861  	expected := strings.TrimSpace(testTerraformPlanComputedStr)
   862  	if actual != expected {
   863  		t.Fatalf("bad:\n%s", actual)
   864  	}
   865  }
   866  
   867  func TestContext2Plan_computedDataResource(t *testing.T) {
   868  	m := testModule(t, "plan-computed-data-resource")
   869  	p := testProvider("aws")
   870  	p.DiffFn = testDiffFn
   871  	ctx := testContext2(t, &ContextOpts{
   872  		Module: m,
   873  		Providers: map[string]ResourceProviderFactory{
   874  			"aws": testProviderFuncFixed(p),
   875  		},
   876  	})
   877  
   878  	plan, err := ctx.Plan()
   879  	if err != nil {
   880  		t.Fatalf("err: %s", err)
   881  	}
   882  
   883  	if got := len(plan.Diff.Modules); got != 1 {
   884  		t.Fatalf("got %d modules; want 1", got)
   885  	}
   886  
   887  	moduleDiff := plan.Diff.Modules[0]
   888  
   889  	if _, ok := moduleDiff.Resources["aws_instance.foo"]; !ok {
   890  		t.Fatalf("missing diff for aws_instance.foo")
   891  	}
   892  	iDiff, ok := moduleDiff.Resources["data.aws_vpc.bar"]
   893  	if !ok {
   894  		t.Fatalf("missing diff for data.aws_vpc.bar")
   895  	}
   896  
   897  	expectedDiff := &InstanceDiff{
   898  		Attributes: map[string]*ResourceAttrDiff{
   899  			"id": {
   900  				NewComputed: true,
   901  				RequiresNew: true,
   902  				Type:        DiffAttrOutput,
   903  			},
   904  		},
   905  	}
   906  	if same, _ := expectedDiff.Same(iDiff); !same {
   907  		t.Fatalf(
   908  			"incorrect diff for data.aws_vpc.bar\ngot:  %#v\nwant: %#v",
   909  			iDiff, expectedDiff,
   910  		)
   911  	}
   912  }
   913  
   914  func TestContext2Plan_dataResourceBecomesComputed(t *testing.T) {
   915  	m := testModule(t, "plan-data-resource-becomes-computed")
   916  	p := testProvider("aws")
   917  
   918  	p.DiffFn = func(info *InstanceInfo, state *InstanceState, config *ResourceConfig) (*InstanceDiff, error) {
   919  		if info.Type != "aws_instance" {
   920  			t.Fatalf("don't know how to diff %s", info.Id)
   921  			return nil, nil
   922  		}
   923  
   924  		return &InstanceDiff{
   925  			Attributes: map[string]*ResourceAttrDiff{
   926  				"computed": &ResourceAttrDiff{
   927  					Old:         "",
   928  					New:         "",
   929  					NewComputed: true,
   930  				},
   931  			},
   932  		}, nil
   933  	}
   934  	p.ReadDataDiffReturn = &InstanceDiff{
   935  		Attributes: map[string]*ResourceAttrDiff{
   936  			"foo": &ResourceAttrDiff{
   937  				Old:         "",
   938  				New:         "",
   939  				NewComputed: true,
   940  			},
   941  		},
   942  	}
   943  
   944  	ctx := testContext2(t, &ContextOpts{
   945  		Module: m,
   946  		Providers: map[string]ResourceProviderFactory{
   947  			"aws": testProviderFuncFixed(p),
   948  		},
   949  		State: &State{
   950  			Modules: []*ModuleState{
   951  				&ModuleState{
   952  					Path: rootModulePath,
   953  					Resources: map[string]*ResourceState{
   954  						"data.aws_data_resource.foo": &ResourceState{
   955  							Type: "aws_data_resource",
   956  							Primary: &InstanceState{
   957  								ID: "i-abc123",
   958  								Attributes: map[string]string{
   959  									"id":    "i-abc123",
   960  									"value": "baz",
   961  								},
   962  							},
   963  						},
   964  					},
   965  				},
   966  			},
   967  		},
   968  	})
   969  
   970  	plan, err := ctx.Plan()
   971  	if err != nil {
   972  		t.Fatalf("err: %s", err)
   973  	}
   974  
   975  	if got := len(plan.Diff.Modules); got != 1 {
   976  		t.Fatalf("got %d modules; want 1", got)
   977  	}
   978  
   979  	if !p.ReadDataDiffCalled {
   980  		t.Fatal("ReadDataDiff wasn't called, but should've been")
   981  	}
   982  	if got, want := p.ReadDataDiffInfo.Id, "data.aws_data_resource.foo"; got != want {
   983  		t.Fatalf("ReadDataDiff info id is %s; want %s", got, want)
   984  	}
   985  
   986  	moduleDiff := plan.Diff.Modules[0]
   987  
   988  	iDiff, ok := moduleDiff.Resources["data.aws_data_resource.foo"]
   989  	if !ok {
   990  		t.Fatalf("missing diff for data.aws_data_resource.foo")
   991  	}
   992  
   993  	if same, _ := p.ReadDataDiffReturn.Same(iDiff); !same {
   994  		t.Fatalf(
   995  			"incorrect diff for data.data_resource.foo\ngot:  %#v\nwant: %#v",
   996  			iDiff, p.ReadDataDiffReturn,
   997  		)
   998  	}
   999  }
  1000  
  1001  func TestContext2Plan_computedList(t *testing.T) {
  1002  	m := testModule(t, "plan-computed-list")
  1003  	p := testProvider("aws")
  1004  	p.DiffFn = testDiffFn
  1005  	ctx := testContext2(t, &ContextOpts{
  1006  		Module: m,
  1007  		Providers: map[string]ResourceProviderFactory{
  1008  			"aws": testProviderFuncFixed(p),
  1009  		},
  1010  	})
  1011  
  1012  	plan, err := ctx.Plan()
  1013  	if err != nil {
  1014  		t.Fatalf("err: %s", err)
  1015  	}
  1016  
  1017  	actual := strings.TrimSpace(plan.String())
  1018  	expected := strings.TrimSpace(testTerraformPlanComputedListStr)
  1019  	if actual != expected {
  1020  		t.Fatalf("bad:\n%s", actual)
  1021  	}
  1022  }
  1023  
  1024  func TestContext2Plan_count(t *testing.T) {
  1025  	m := testModule(t, "plan-count")
  1026  	p := testProvider("aws")
  1027  	p.DiffFn = testDiffFn
  1028  	ctx := testContext2(t, &ContextOpts{
  1029  		Module: m,
  1030  		Providers: map[string]ResourceProviderFactory{
  1031  			"aws": testProviderFuncFixed(p),
  1032  		},
  1033  	})
  1034  
  1035  	plan, err := ctx.Plan()
  1036  	if err != nil {
  1037  		t.Fatalf("err: %s", err)
  1038  	}
  1039  
  1040  	if len(plan.Diff.RootModule().Resources) < 6 {
  1041  		t.Fatalf("bad: %#v", plan.Diff.RootModule().Resources)
  1042  	}
  1043  
  1044  	actual := strings.TrimSpace(plan.String())
  1045  	expected := strings.TrimSpace(testTerraformPlanCountStr)
  1046  	if actual != expected {
  1047  		t.Fatalf("bad:\n%s", actual)
  1048  	}
  1049  }
  1050  
  1051  func TestContext2Plan_countComputed(t *testing.T) {
  1052  	m := testModule(t, "plan-count-computed")
  1053  	p := testProvider("aws")
  1054  	p.DiffFn = testDiffFn
  1055  	ctx := testContext2(t, &ContextOpts{
  1056  		Module: m,
  1057  		Providers: map[string]ResourceProviderFactory{
  1058  			"aws": testProviderFuncFixed(p),
  1059  		},
  1060  	})
  1061  
  1062  	_, err := ctx.Plan()
  1063  	if err == nil {
  1064  		t.Fatal("should error")
  1065  	}
  1066  }
  1067  
  1068  func TestContext2Plan_countIndex(t *testing.T) {
  1069  	m := testModule(t, "plan-count-index")
  1070  	p := testProvider("aws")
  1071  	p.DiffFn = testDiffFn
  1072  	ctx := testContext2(t, &ContextOpts{
  1073  		Module: m,
  1074  		Providers: map[string]ResourceProviderFactory{
  1075  			"aws": testProviderFuncFixed(p),
  1076  		},
  1077  	})
  1078  
  1079  	plan, err := ctx.Plan()
  1080  	if err != nil {
  1081  		t.Fatalf("err: %s", err)
  1082  	}
  1083  
  1084  	actual := strings.TrimSpace(plan.String())
  1085  	expected := strings.TrimSpace(testTerraformPlanCountIndexStr)
  1086  	if actual != expected {
  1087  		t.Fatalf("bad:\n%s", actual)
  1088  	}
  1089  }
  1090  
  1091  func TestContext2Plan_countIndexZero(t *testing.T) {
  1092  	m := testModule(t, "plan-count-index-zero")
  1093  	p := testProvider("aws")
  1094  	p.DiffFn = testDiffFn
  1095  	ctx := testContext2(t, &ContextOpts{
  1096  		Module: m,
  1097  		Providers: map[string]ResourceProviderFactory{
  1098  			"aws": testProviderFuncFixed(p),
  1099  		},
  1100  	})
  1101  
  1102  	plan, err := ctx.Plan()
  1103  	if err != nil {
  1104  		t.Fatalf("err: %s", err)
  1105  	}
  1106  
  1107  	actual := strings.TrimSpace(plan.String())
  1108  	expected := strings.TrimSpace(testTerraformPlanCountIndexZeroStr)
  1109  	if actual != expected {
  1110  		t.Fatalf("bad:\n%s", actual)
  1111  	}
  1112  }
  1113  
  1114  func TestContext2Plan_countVar(t *testing.T) {
  1115  	m := testModule(t, "plan-count-var")
  1116  	p := testProvider("aws")
  1117  	p.DiffFn = testDiffFn
  1118  	ctx := testContext2(t, &ContextOpts{
  1119  		Module: m,
  1120  		Providers: map[string]ResourceProviderFactory{
  1121  			"aws": testProviderFuncFixed(p),
  1122  		},
  1123  		Variables: map[string]string{
  1124  			"count": "3",
  1125  		},
  1126  	})
  1127  
  1128  	plan, err := ctx.Plan()
  1129  	if err != nil {
  1130  		t.Fatalf("err: %s", err)
  1131  	}
  1132  
  1133  	actual := strings.TrimSpace(plan.String())
  1134  	expected := strings.TrimSpace(testTerraformPlanCountVarStr)
  1135  	if actual != expected {
  1136  		t.Fatalf("bad:\n%s", actual)
  1137  	}
  1138  }
  1139  
  1140  func TestContext2Plan_countZero(t *testing.T) {
  1141  	m := testModule(t, "plan-count-zero")
  1142  	p := testProvider("aws")
  1143  	p.DiffFn = testDiffFn
  1144  	ctx := testContext2(t, &ContextOpts{
  1145  		Module: m,
  1146  		Providers: map[string]ResourceProviderFactory{
  1147  			"aws": testProviderFuncFixed(p),
  1148  		},
  1149  	})
  1150  
  1151  	plan, err := ctx.Plan()
  1152  	if err != nil {
  1153  		t.Fatalf("err: %s", err)
  1154  	}
  1155  
  1156  	actual := strings.TrimSpace(plan.String())
  1157  	expected := strings.TrimSpace(testTerraformPlanCountZeroStr)
  1158  	if actual != expected {
  1159  		t.Fatalf("bad:\n%s", actual)
  1160  	}
  1161  }
  1162  
  1163  func TestContext2Plan_countOneIndex(t *testing.T) {
  1164  	m := testModule(t, "plan-count-one-index")
  1165  	p := testProvider("aws")
  1166  	p.DiffFn = testDiffFn
  1167  	ctx := testContext2(t, &ContextOpts{
  1168  		Module: m,
  1169  		Providers: map[string]ResourceProviderFactory{
  1170  			"aws": testProviderFuncFixed(p),
  1171  		},
  1172  	})
  1173  
  1174  	plan, err := ctx.Plan()
  1175  	if err != nil {
  1176  		t.Fatalf("err: %s", err)
  1177  	}
  1178  
  1179  	actual := strings.TrimSpace(plan.String())
  1180  	expected := strings.TrimSpace(testTerraformPlanCountOneIndexStr)
  1181  	if actual != expected {
  1182  		t.Fatalf("bad:\n%s", actual)
  1183  	}
  1184  }
  1185  
  1186  func TestContext2Plan_countDecreaseToOne(t *testing.T) {
  1187  	m := testModule(t, "plan-count-dec")
  1188  	p := testProvider("aws")
  1189  	p.DiffFn = testDiffFn
  1190  	s := &State{
  1191  		Modules: []*ModuleState{
  1192  			&ModuleState{
  1193  				Path: rootModulePath,
  1194  				Resources: map[string]*ResourceState{
  1195  					"aws_instance.foo.0": &ResourceState{
  1196  						Type: "aws_instance",
  1197  						Primary: &InstanceState{
  1198  							ID: "bar",
  1199  							Attributes: map[string]string{
  1200  								"foo":  "foo",
  1201  								"type": "aws_instance",
  1202  							},
  1203  						},
  1204  					},
  1205  					"aws_instance.foo.1": &ResourceState{
  1206  						Type: "aws_instance",
  1207  						Primary: &InstanceState{
  1208  							ID: "bar",
  1209  						},
  1210  					},
  1211  					"aws_instance.foo.2": &ResourceState{
  1212  						Type: "aws_instance",
  1213  						Primary: &InstanceState{
  1214  							ID: "bar",
  1215  						},
  1216  					},
  1217  				},
  1218  			},
  1219  		},
  1220  	}
  1221  	ctx := testContext2(t, &ContextOpts{
  1222  		Module: m,
  1223  		Providers: map[string]ResourceProviderFactory{
  1224  			"aws": testProviderFuncFixed(p),
  1225  		},
  1226  		State: s,
  1227  	})
  1228  
  1229  	plan, err := ctx.Plan()
  1230  	if err != nil {
  1231  		t.Fatalf("err: %s", err)
  1232  	}
  1233  
  1234  	actual := strings.TrimSpace(plan.String())
  1235  	expected := strings.TrimSpace(testTerraformPlanCountDecreaseStr)
  1236  	if actual != expected {
  1237  		t.Fatalf("bad:\n%s", actual)
  1238  	}
  1239  }
  1240  
  1241  func TestContext2Plan_countIncreaseFromNotSet(t *testing.T) {
  1242  	m := testModule(t, "plan-count-inc")
  1243  	p := testProvider("aws")
  1244  	p.DiffFn = testDiffFn
  1245  	s := &State{
  1246  		Modules: []*ModuleState{
  1247  			&ModuleState{
  1248  				Path: rootModulePath,
  1249  				Resources: map[string]*ResourceState{
  1250  					"aws_instance.foo": &ResourceState{
  1251  						Type: "aws_instance",
  1252  						Primary: &InstanceState{
  1253  							ID: "bar",
  1254  							Attributes: map[string]string{
  1255  								"foo":  "foo",
  1256  								"type": "aws_instance",
  1257  							},
  1258  						},
  1259  					},
  1260  				},
  1261  			},
  1262  		},
  1263  	}
  1264  	ctx := testContext2(t, &ContextOpts{
  1265  		Module: m,
  1266  		Providers: map[string]ResourceProviderFactory{
  1267  			"aws": testProviderFuncFixed(p),
  1268  		},
  1269  		State: s,
  1270  	})
  1271  
  1272  	plan, err := ctx.Plan()
  1273  	if err != nil {
  1274  		t.Fatalf("err: %s", err)
  1275  	}
  1276  
  1277  	actual := strings.TrimSpace(plan.String())
  1278  	expected := strings.TrimSpace(testTerraformPlanCountIncreaseStr)
  1279  	if actual != expected {
  1280  		t.Fatalf("bad:\n%s", actual)
  1281  	}
  1282  }
  1283  
  1284  func TestContext2Plan_countIncreaseFromOne(t *testing.T) {
  1285  	m := testModule(t, "plan-count-inc")
  1286  	p := testProvider("aws")
  1287  	p.DiffFn = testDiffFn
  1288  	s := &State{
  1289  		Modules: []*ModuleState{
  1290  			&ModuleState{
  1291  				Path: rootModulePath,
  1292  				Resources: map[string]*ResourceState{
  1293  					"aws_instance.foo.0": &ResourceState{
  1294  						Type: "aws_instance",
  1295  						Primary: &InstanceState{
  1296  							ID: "bar",
  1297  							Attributes: map[string]string{
  1298  								"foo":  "foo",
  1299  								"type": "aws_instance",
  1300  							},
  1301  						},
  1302  					},
  1303  				},
  1304  			},
  1305  		},
  1306  	}
  1307  	ctx := testContext2(t, &ContextOpts{
  1308  		Module: m,
  1309  		Providers: map[string]ResourceProviderFactory{
  1310  			"aws": testProviderFuncFixed(p),
  1311  		},
  1312  		State: s,
  1313  	})
  1314  
  1315  	plan, err := ctx.Plan()
  1316  	if err != nil {
  1317  		t.Fatalf("err: %s", err)
  1318  	}
  1319  
  1320  	actual := strings.TrimSpace(plan.String())
  1321  	expected := strings.TrimSpace(testTerraformPlanCountIncreaseFromOneStr)
  1322  	if actual != expected {
  1323  		t.Fatalf("bad:\n%s", actual)
  1324  	}
  1325  }
  1326  
  1327  // https://github.com/PeoplePerHour/terraform/pull/11
  1328  //
  1329  // This tests a case where both a "resource" and "resource.0" are in
  1330  // the state file, which apparently is a reasonable backwards compatibility
  1331  // concern found in the above 3rd party repo.
  1332  func TestContext2Plan_countIncreaseFromOneCorrupted(t *testing.T) {
  1333  	m := testModule(t, "plan-count-inc")
  1334  	p := testProvider("aws")
  1335  	p.DiffFn = testDiffFn
  1336  	s := &State{
  1337  		Modules: []*ModuleState{
  1338  			&ModuleState{
  1339  				Path: rootModulePath,
  1340  				Resources: map[string]*ResourceState{
  1341  					"aws_instance.foo": &ResourceState{
  1342  						Type: "aws_instance",
  1343  						Primary: &InstanceState{
  1344  							ID: "bar",
  1345  							Attributes: map[string]string{
  1346  								"foo":  "foo",
  1347  								"type": "aws_instance",
  1348  							},
  1349  						},
  1350  					},
  1351  					"aws_instance.foo.0": &ResourceState{
  1352  						Type: "aws_instance",
  1353  						Primary: &InstanceState{
  1354  							ID: "bar",
  1355  							Attributes: map[string]string{
  1356  								"foo":  "foo",
  1357  								"type": "aws_instance",
  1358  							},
  1359  						},
  1360  					},
  1361  				},
  1362  			},
  1363  		},
  1364  	}
  1365  	ctx := testContext2(t, &ContextOpts{
  1366  		Module: m,
  1367  		Providers: map[string]ResourceProviderFactory{
  1368  			"aws": testProviderFuncFixed(p),
  1369  		},
  1370  		State: s,
  1371  	})
  1372  
  1373  	plan, err := ctx.Plan()
  1374  	if err != nil {
  1375  		t.Fatalf("err: %s", err)
  1376  	}
  1377  
  1378  	actual := strings.TrimSpace(plan.String())
  1379  	expected := strings.TrimSpace(testTerraformPlanCountIncreaseFromOneCorruptedStr)
  1380  	if actual != expected {
  1381  		t.Fatalf("bad:\n%s", actual)
  1382  	}
  1383  }
  1384  
  1385  func TestContext2Plan_destroy(t *testing.T) {
  1386  	m := testModule(t, "plan-destroy")
  1387  	p := testProvider("aws")
  1388  	p.DiffFn = testDiffFn
  1389  	s := &State{
  1390  		Modules: []*ModuleState{
  1391  			&ModuleState{
  1392  				Path: rootModulePath,
  1393  				Resources: map[string]*ResourceState{
  1394  					"aws_instance.one": &ResourceState{
  1395  						Type: "aws_instance",
  1396  						Primary: &InstanceState{
  1397  							ID: "bar",
  1398  						},
  1399  					},
  1400  					"aws_instance.two": &ResourceState{
  1401  						Type: "aws_instance",
  1402  						Primary: &InstanceState{
  1403  							ID: "baz",
  1404  						},
  1405  					},
  1406  				},
  1407  			},
  1408  		},
  1409  	}
  1410  	ctx := testContext2(t, &ContextOpts{
  1411  		Module: m,
  1412  		Providers: map[string]ResourceProviderFactory{
  1413  			"aws": testProviderFuncFixed(p),
  1414  		},
  1415  		State:   s,
  1416  		Destroy: true,
  1417  	})
  1418  
  1419  	plan, err := ctx.Plan()
  1420  	if err != nil {
  1421  		t.Fatalf("err: %s", err)
  1422  	}
  1423  
  1424  	if len(plan.Diff.RootModule().Resources) != 2 {
  1425  		t.Fatalf("bad: %#v", plan.Diff.RootModule().Resources)
  1426  	}
  1427  
  1428  	actual := strings.TrimSpace(plan.String())
  1429  	expected := strings.TrimSpace(testTerraformPlanDestroyStr)
  1430  	if actual != expected {
  1431  		t.Fatalf("bad:\n%s", actual)
  1432  	}
  1433  }
  1434  
  1435  func TestContext2Plan_moduleDestroy(t *testing.T) {
  1436  	m := testModule(t, "plan-module-destroy")
  1437  	p := testProvider("aws")
  1438  	p.DiffFn = testDiffFn
  1439  	s := &State{
  1440  		Modules: []*ModuleState{
  1441  			&ModuleState{
  1442  				Path: rootModulePath,
  1443  				Resources: map[string]*ResourceState{
  1444  					"aws_instance.foo": &ResourceState{
  1445  						Type: "aws_instance",
  1446  						Primary: &InstanceState{
  1447  							ID: "bar",
  1448  						},
  1449  					},
  1450  				},
  1451  			},
  1452  			&ModuleState{
  1453  				Path: []string{"root", "child"},
  1454  				Resources: map[string]*ResourceState{
  1455  					"aws_instance.foo": &ResourceState{
  1456  						Type: "aws_instance",
  1457  						Primary: &InstanceState{
  1458  							ID: "bar",
  1459  						},
  1460  					},
  1461  				},
  1462  			},
  1463  		},
  1464  	}
  1465  	ctx := testContext2(t, &ContextOpts{
  1466  		Module: m,
  1467  		Providers: map[string]ResourceProviderFactory{
  1468  			"aws": testProviderFuncFixed(p),
  1469  		},
  1470  		State:   s,
  1471  		Destroy: true,
  1472  	})
  1473  
  1474  	plan, err := ctx.Plan()
  1475  	if err != nil {
  1476  		t.Fatalf("err: %s", err)
  1477  	}
  1478  
  1479  	actual := strings.TrimSpace(plan.String())
  1480  	expected := strings.TrimSpace(testTerraformPlanModuleDestroyStr)
  1481  	if actual != expected {
  1482  		t.Fatalf("bad:\n%s", actual)
  1483  	}
  1484  }
  1485  
  1486  // GH-1835
  1487  func TestContext2Plan_moduleDestroyCycle(t *testing.T) {
  1488  	m := testModule(t, "plan-module-destroy-gh-1835")
  1489  	p := testProvider("aws")
  1490  	p.DiffFn = testDiffFn
  1491  	s := &State{
  1492  		Modules: []*ModuleState{
  1493  			&ModuleState{
  1494  				Path: []string{"root", "a_module"},
  1495  				Resources: map[string]*ResourceState{
  1496  					"aws_instance.a": &ResourceState{
  1497  						Type: "aws_instance",
  1498  						Primary: &InstanceState{
  1499  							ID: "a",
  1500  						},
  1501  					},
  1502  				},
  1503  			},
  1504  			&ModuleState{
  1505  				Path: []string{"root", "b_module"},
  1506  				Resources: map[string]*ResourceState{
  1507  					"aws_instance.b": &ResourceState{
  1508  						Type: "aws_instance",
  1509  						Primary: &InstanceState{
  1510  							ID: "b",
  1511  						},
  1512  					},
  1513  				},
  1514  			},
  1515  		},
  1516  	}
  1517  	ctx := testContext2(t, &ContextOpts{
  1518  		Module: m,
  1519  		Providers: map[string]ResourceProviderFactory{
  1520  			"aws": testProviderFuncFixed(p),
  1521  		},
  1522  		State:   s,
  1523  		Destroy: true,
  1524  	})
  1525  
  1526  	plan, err := ctx.Plan()
  1527  	if err != nil {
  1528  		t.Fatalf("err: %s", err)
  1529  	}
  1530  
  1531  	actual := strings.TrimSpace(plan.String())
  1532  	expected := strings.TrimSpace(testTerraformPlanModuleDestroyCycleStr)
  1533  	if actual != expected {
  1534  		t.Fatalf("bad:\n%s", actual)
  1535  	}
  1536  }
  1537  
  1538  func TestContext2Plan_moduleDestroyMultivar(t *testing.T) {
  1539  	m := testModule(t, "plan-module-destroy-multivar")
  1540  	p := testProvider("aws")
  1541  	p.DiffFn = testDiffFn
  1542  	s := &State{
  1543  		Modules: []*ModuleState{
  1544  			&ModuleState{
  1545  				Path:      rootModulePath,
  1546  				Resources: map[string]*ResourceState{},
  1547  			},
  1548  			&ModuleState{
  1549  				Path: []string{"root", "child"},
  1550  				Resources: map[string]*ResourceState{
  1551  					"aws_instance.foo.0": &ResourceState{
  1552  						Type: "aws_instance",
  1553  						Primary: &InstanceState{
  1554  							ID: "bar0",
  1555  						},
  1556  					},
  1557  					"aws_instance.foo.1": &ResourceState{
  1558  						Type: "aws_instance",
  1559  						Primary: &InstanceState{
  1560  							ID: "bar1",
  1561  						},
  1562  					},
  1563  				},
  1564  			},
  1565  		},
  1566  	}
  1567  	ctx := testContext2(t, &ContextOpts{
  1568  		Module: m,
  1569  		Providers: map[string]ResourceProviderFactory{
  1570  			"aws": testProviderFuncFixed(p),
  1571  		},
  1572  		State:   s,
  1573  		Destroy: true,
  1574  	})
  1575  
  1576  	plan, err := ctx.Plan()
  1577  	if err != nil {
  1578  		t.Fatalf("err: %s", err)
  1579  	}
  1580  
  1581  	actual := strings.TrimSpace(plan.String())
  1582  	expected := strings.TrimSpace(testTerraformPlanModuleDestroyMultivarStr)
  1583  	if actual != expected {
  1584  		t.Fatalf("bad:\n%s", actual)
  1585  	}
  1586  }
  1587  
  1588  func TestContext2Plan_pathVar(t *testing.T) {
  1589  	cwd, err := os.Getwd()
  1590  	if err != nil {
  1591  		t.Fatalf("err: %s", err)
  1592  	}
  1593  
  1594  	m := testModule(t, "plan-path-var")
  1595  	p := testProvider("aws")
  1596  	p.DiffFn = testDiffFn
  1597  	ctx := testContext2(t, &ContextOpts{
  1598  		Module: m,
  1599  		Providers: map[string]ResourceProviderFactory{
  1600  			"aws": testProviderFuncFixed(p),
  1601  		},
  1602  	})
  1603  
  1604  	plan, err := ctx.Plan()
  1605  	if err != nil {
  1606  		t.Fatalf("err: %s", err)
  1607  	}
  1608  
  1609  	actual := strings.TrimSpace(plan.String())
  1610  	expected := strings.TrimSpace(testTerraformPlanPathVarStr)
  1611  
  1612  	// Warning: this ordering REALLY matters for this test. The
  1613  	// order is: cwd, module, root.
  1614  	expected = fmt.Sprintf(
  1615  		expected,
  1616  		cwd,
  1617  		m.Config().Dir,
  1618  		m.Config().Dir)
  1619  
  1620  	if actual != expected {
  1621  		t.Fatalf("bad:\n%s\n\nexpected:\n\n%s", actual, expected)
  1622  	}
  1623  }
  1624  
  1625  func TestContext2Plan_diffVar(t *testing.T) {
  1626  	m := testModule(t, "plan-diffvar")
  1627  	p := testProvider("aws")
  1628  	s := &State{
  1629  		Modules: []*ModuleState{
  1630  			&ModuleState{
  1631  				Path: rootModulePath,
  1632  				Resources: map[string]*ResourceState{
  1633  					"aws_instance.foo": &ResourceState{
  1634  						Primary: &InstanceState{
  1635  							ID: "bar",
  1636  							Attributes: map[string]string{
  1637  								"num": "2",
  1638  							},
  1639  						},
  1640  					},
  1641  				},
  1642  			},
  1643  		},
  1644  	}
  1645  	ctx := testContext2(t, &ContextOpts{
  1646  		Module: m,
  1647  		Providers: map[string]ResourceProviderFactory{
  1648  			"aws": testProviderFuncFixed(p),
  1649  		},
  1650  		State: s,
  1651  	})
  1652  
  1653  	p.DiffFn = func(
  1654  		info *InstanceInfo,
  1655  		s *InstanceState,
  1656  		c *ResourceConfig) (*InstanceDiff, error) {
  1657  		if s.ID != "bar" {
  1658  			return testDiffFn(info, s, c)
  1659  		}
  1660  
  1661  		return &InstanceDiff{
  1662  			Attributes: map[string]*ResourceAttrDiff{
  1663  				"num": &ResourceAttrDiff{
  1664  					Old: "2",
  1665  					New: "3",
  1666  				},
  1667  			},
  1668  		}, nil
  1669  	}
  1670  
  1671  	plan, err := ctx.Plan()
  1672  	if err != nil {
  1673  		t.Fatalf("err: %s", err)
  1674  	}
  1675  
  1676  	actual := strings.TrimSpace(plan.String())
  1677  	expected := strings.TrimSpace(testTerraformPlanDiffVarStr)
  1678  	if actual != expected {
  1679  		t.Fatalf("actual:\n%s\n\nexpected:\n%s", actual, expected)
  1680  	}
  1681  }
  1682  
  1683  func TestContext2Plan_hook(t *testing.T) {
  1684  	m := testModule(t, "plan-good")
  1685  	h := new(MockHook)
  1686  	p := testProvider("aws")
  1687  	p.DiffFn = testDiffFn
  1688  	ctx := testContext2(t, &ContextOpts{
  1689  		Module: m,
  1690  		Hooks:  []Hook{h},
  1691  		Providers: map[string]ResourceProviderFactory{
  1692  			"aws": testProviderFuncFixed(p),
  1693  		},
  1694  	})
  1695  
  1696  	_, err := ctx.Plan()
  1697  	if err != nil {
  1698  		t.Fatalf("err: %s", err)
  1699  	}
  1700  
  1701  	if !h.PreDiffCalled {
  1702  		t.Fatal("should be called")
  1703  	}
  1704  	if !h.PostDiffCalled {
  1705  		t.Fatal("should be called")
  1706  	}
  1707  }
  1708  
  1709  func TestContext2Plan_orphan(t *testing.T) {
  1710  	m := testModule(t, "plan-orphan")
  1711  	p := testProvider("aws")
  1712  	p.DiffFn = testDiffFn
  1713  	s := &State{
  1714  		Modules: []*ModuleState{
  1715  			&ModuleState{
  1716  				Path: rootModulePath,
  1717  				Resources: map[string]*ResourceState{
  1718  					"aws_instance.baz": &ResourceState{
  1719  						Type: "aws_instance",
  1720  						Primary: &InstanceState{
  1721  							ID: "bar",
  1722  						},
  1723  					},
  1724  				},
  1725  			},
  1726  		},
  1727  	}
  1728  	ctx := testContext2(t, &ContextOpts{
  1729  		Module: m,
  1730  		Providers: map[string]ResourceProviderFactory{
  1731  			"aws": testProviderFuncFixed(p),
  1732  		},
  1733  		State: s,
  1734  	})
  1735  
  1736  	plan, err := ctx.Plan()
  1737  	if err != nil {
  1738  		t.Fatalf("err: %s", err)
  1739  	}
  1740  
  1741  	actual := strings.TrimSpace(plan.String())
  1742  	expected := strings.TrimSpace(testTerraformPlanOrphanStr)
  1743  	if actual != expected {
  1744  		t.Fatalf("bad:\n%s", actual)
  1745  	}
  1746  }
  1747  
  1748  func TestContext2Plan_state(t *testing.T) {
  1749  	m := testModule(t, "plan-good")
  1750  	p := testProvider("aws")
  1751  	p.DiffFn = testDiffFn
  1752  	s := &State{
  1753  		Modules: []*ModuleState{
  1754  			&ModuleState{
  1755  				Path: rootModulePath,
  1756  				Resources: map[string]*ResourceState{
  1757  					"aws_instance.foo": &ResourceState{
  1758  						Primary: &InstanceState{
  1759  							ID: "bar",
  1760  						},
  1761  					},
  1762  				},
  1763  			},
  1764  		},
  1765  	}
  1766  	ctx := testContext2(t, &ContextOpts{
  1767  		Module: m,
  1768  		Providers: map[string]ResourceProviderFactory{
  1769  			"aws": testProviderFuncFixed(p),
  1770  		},
  1771  		State: s,
  1772  	})
  1773  
  1774  	plan, err := ctx.Plan()
  1775  	if err != nil {
  1776  		t.Fatalf("err: %s", err)
  1777  	}
  1778  
  1779  	if len(plan.Diff.RootModule().Resources) < 2 {
  1780  		t.Fatalf("bad: %#v", plan.Diff.RootModule().Resources)
  1781  	}
  1782  
  1783  	actual := strings.TrimSpace(plan.String())
  1784  	expected := strings.TrimSpace(testTerraformPlanStateStr)
  1785  	if actual != expected {
  1786  		t.Fatalf("bad:\n%s\n\nexpected:\n\n%s", actual, expected)
  1787  	}
  1788  }
  1789  
  1790  func TestContext2Plan_taint(t *testing.T) {
  1791  	m := testModule(t, "plan-taint")
  1792  	p := testProvider("aws")
  1793  	p.DiffFn = testDiffFn
  1794  	s := &State{
  1795  		Modules: []*ModuleState{
  1796  			&ModuleState{
  1797  				Path: rootModulePath,
  1798  				Resources: map[string]*ResourceState{
  1799  					"aws_instance.foo": &ResourceState{
  1800  						Type: "aws_instance",
  1801  						Primary: &InstanceState{
  1802  							ID:         "bar",
  1803  							Attributes: map[string]string{"num": "2"},
  1804  						},
  1805  					},
  1806  					"aws_instance.bar": &ResourceState{
  1807  						Type: "aws_instance",
  1808  						Primary: &InstanceState{
  1809  							ID:      "baz",
  1810  							Tainted: true,
  1811  						},
  1812  					},
  1813  				},
  1814  			},
  1815  		},
  1816  	}
  1817  	ctx := testContext2(t, &ContextOpts{
  1818  		Module: m,
  1819  		Providers: map[string]ResourceProviderFactory{
  1820  			"aws": testProviderFuncFixed(p),
  1821  		},
  1822  		State: s,
  1823  	})
  1824  
  1825  	plan, err := ctx.Plan()
  1826  	if err != nil {
  1827  		t.Fatalf("err: %s", err)
  1828  	}
  1829  
  1830  	actual := strings.TrimSpace(plan.String())
  1831  	expected := strings.TrimSpace(testTerraformPlanTaintStr)
  1832  	if actual != expected {
  1833  		t.Fatalf("bad:\n%s", actual)
  1834  	}
  1835  }
  1836  
  1837  // Fails about 50% of the time before the fix for GH-4982, covers the fix.
  1838  func TestContext2Plan_taintDestroyInterpolatedCountRace(t *testing.T) {
  1839  	m := testModule(t, "plan-taint-interpolated-count")
  1840  	p := testProvider("aws")
  1841  	p.DiffFn = testDiffFn
  1842  	s := &State{
  1843  		Modules: []*ModuleState{
  1844  			&ModuleState{
  1845  				Path: rootModulePath,
  1846  				Resources: map[string]*ResourceState{
  1847  					"aws_instance.foo.0": &ResourceState{
  1848  						Type: "aws_instance",
  1849  						Primary: &InstanceState{
  1850  							ID:      "bar",
  1851  							Tainted: true,
  1852  						},
  1853  					},
  1854  					"aws_instance.foo.1": &ResourceState{
  1855  						Type:    "aws_instance",
  1856  						Primary: &InstanceState{ID: "bar"},
  1857  					},
  1858  					"aws_instance.foo.2": &ResourceState{
  1859  						Type:    "aws_instance",
  1860  						Primary: &InstanceState{ID: "bar"},
  1861  					},
  1862  				},
  1863  			},
  1864  		},
  1865  	}
  1866  	ctx := testContext2(t, &ContextOpts{
  1867  		Module: m,
  1868  		Providers: map[string]ResourceProviderFactory{
  1869  			"aws": testProviderFuncFixed(p),
  1870  		},
  1871  		State: s,
  1872  	})
  1873  
  1874  	for i := 0; i < 100; i++ {
  1875  		plan, err := ctx.Plan()
  1876  		if err != nil {
  1877  			t.Fatalf("err: %s", err)
  1878  		}
  1879  
  1880  		actual := strings.TrimSpace(plan.String())
  1881  		expected := strings.TrimSpace(`
  1882  DIFF:
  1883  
  1884  DESTROY/CREATE: aws_instance.foo.0
  1885  
  1886  STATE:
  1887  
  1888  aws_instance.foo.0: (tainted)
  1889    ID = bar
  1890  aws_instance.foo.1:
  1891    ID = bar
  1892  aws_instance.foo.2:
  1893    ID = bar
  1894  		`)
  1895  		if actual != expected {
  1896  			t.Fatalf("bad:\n%s", actual)
  1897  		}
  1898  	}
  1899  }
  1900  
  1901  func TestContext2Plan_targeted(t *testing.T) {
  1902  	m := testModule(t, "plan-targeted")
  1903  	p := testProvider("aws")
  1904  	p.DiffFn = testDiffFn
  1905  	ctx := testContext2(t, &ContextOpts{
  1906  		Module: m,
  1907  		Providers: map[string]ResourceProviderFactory{
  1908  			"aws": testProviderFuncFixed(p),
  1909  		},
  1910  		Targets: []string{"aws_instance.foo"},
  1911  	})
  1912  
  1913  	plan, err := ctx.Plan()
  1914  	if err != nil {
  1915  		t.Fatalf("err: %s", err)
  1916  	}
  1917  
  1918  	actual := strings.TrimSpace(plan.String())
  1919  	expected := strings.TrimSpace(`
  1920  DIFF:
  1921  
  1922  CREATE: aws_instance.foo
  1923    num:  "" => "2"
  1924    type: "" => "aws_instance"
  1925  
  1926  STATE:
  1927  
  1928  <no state>
  1929  	`)
  1930  	if actual != expected {
  1931  		t.Fatalf("expected:\n%s\n\ngot:\n%s", expected, actual)
  1932  	}
  1933  }
  1934  
  1935  func TestContext2Plan_targetedOrphan(t *testing.T) {
  1936  	m := testModule(t, "plan-targeted-orphan")
  1937  	p := testProvider("aws")
  1938  	p.DiffFn = testDiffFn
  1939  	ctx := testContext2(t, &ContextOpts{
  1940  		Module: m,
  1941  		Providers: map[string]ResourceProviderFactory{
  1942  			"aws": testProviderFuncFixed(p),
  1943  		},
  1944  		State: &State{
  1945  			Modules: []*ModuleState{
  1946  				&ModuleState{
  1947  					Path: rootModulePath,
  1948  					Resources: map[string]*ResourceState{
  1949  						"aws_instance.orphan": &ResourceState{
  1950  							Type: "aws_instance",
  1951  							Primary: &InstanceState{
  1952  								ID: "i-789xyz",
  1953  							},
  1954  						},
  1955  						"aws_instance.nottargeted": &ResourceState{
  1956  							Type: "aws_instance",
  1957  							Primary: &InstanceState{
  1958  								ID: "i-abc123",
  1959  							},
  1960  						},
  1961  					},
  1962  				},
  1963  			},
  1964  		},
  1965  		Destroy: true,
  1966  		Targets: []string{"aws_instance.orphan"},
  1967  	})
  1968  
  1969  	plan, err := ctx.Plan()
  1970  	if err != nil {
  1971  		t.Fatalf("err: %s", err)
  1972  	}
  1973  
  1974  	actual := strings.TrimSpace(plan.String())
  1975  	expected := strings.TrimSpace(`DIFF:
  1976  
  1977  DESTROY: aws_instance.orphan
  1978  
  1979  STATE:
  1980  
  1981  aws_instance.nottargeted:
  1982    ID = i-abc123
  1983  aws_instance.orphan:
  1984    ID = i-789xyz
  1985  `)
  1986  	if actual != expected {
  1987  		t.Fatalf("expected:\n%s\n\ngot:\n%s", expected, actual)
  1988  	}
  1989  }
  1990  
  1991  // https://github.com/hashicorp/terraform/issues/2538
  1992  func TestContext2Plan_targetedModuleOrphan(t *testing.T) {
  1993  	m := testModule(t, "plan-targeted-module-orphan")
  1994  	p := testProvider("aws")
  1995  	p.DiffFn = testDiffFn
  1996  	ctx := testContext2(t, &ContextOpts{
  1997  		Module: m,
  1998  		Providers: map[string]ResourceProviderFactory{
  1999  			"aws": testProviderFuncFixed(p),
  2000  		},
  2001  		State: &State{
  2002  			Modules: []*ModuleState{
  2003  				&ModuleState{
  2004  					Path: []string{"root", "child"},
  2005  					Resources: map[string]*ResourceState{
  2006  						"aws_instance.orphan": &ResourceState{
  2007  							Type: "aws_instance",
  2008  							Primary: &InstanceState{
  2009  								ID: "i-789xyz",
  2010  							},
  2011  						},
  2012  						"aws_instance.nottargeted": &ResourceState{
  2013  							Type: "aws_instance",
  2014  							Primary: &InstanceState{
  2015  								ID: "i-abc123",
  2016  							},
  2017  						},
  2018  					},
  2019  				},
  2020  			},
  2021  		},
  2022  		Destroy: true,
  2023  		Targets: []string{"module.child.aws_instance.orphan"},
  2024  	})
  2025  
  2026  	plan, err := ctx.Plan()
  2027  	if err != nil {
  2028  		t.Fatalf("err: %s", err)
  2029  	}
  2030  
  2031  	actual := strings.TrimSpace(plan.String())
  2032  	expected := strings.TrimSpace(`DIFF:
  2033  
  2034  module.child:
  2035    DESTROY: aws_instance.orphan
  2036  
  2037  STATE:
  2038  
  2039  module.child:
  2040    aws_instance.nottargeted:
  2041      ID = i-abc123
  2042    aws_instance.orphan:
  2043      ID = i-789xyz
  2044  `)
  2045  	if actual != expected {
  2046  		t.Fatalf("expected:\n%s\n\ngot:\n%s", expected, actual)
  2047  	}
  2048  }
  2049  
  2050  // https://github.com/hashicorp/terraform/issues/4515
  2051  func TestContext2Plan_targetedOverTen(t *testing.T) {
  2052  	m := testModule(t, "plan-targeted-over-ten")
  2053  	p := testProvider("aws")
  2054  	p.DiffFn = testDiffFn
  2055  
  2056  	resources := make(map[string]*ResourceState)
  2057  	var expectedState []string
  2058  	for i := 0; i < 13; i++ {
  2059  		key := fmt.Sprintf("aws_instance.foo.%d", i)
  2060  		id := fmt.Sprintf("i-abc%d", i)
  2061  		resources[key] = &ResourceState{
  2062  			Type:    "aws_instance",
  2063  			Primary: &InstanceState{ID: id},
  2064  		}
  2065  		expectedState = append(expectedState,
  2066  			fmt.Sprintf("%s:\n  ID = %s\n", key, id))
  2067  	}
  2068  	ctx := testContext2(t, &ContextOpts{
  2069  		Module: m,
  2070  		Providers: map[string]ResourceProviderFactory{
  2071  			"aws": testProviderFuncFixed(p),
  2072  		},
  2073  		State: &State{
  2074  			Modules: []*ModuleState{
  2075  				&ModuleState{
  2076  					Path:      rootModulePath,
  2077  					Resources: resources,
  2078  				},
  2079  			},
  2080  		},
  2081  		Targets: []string{"aws_instance.foo[1]"},
  2082  	})
  2083  
  2084  	plan, err := ctx.Plan()
  2085  	if err != nil {
  2086  		t.Fatalf("err: %s", err)
  2087  	}
  2088  
  2089  	actual := strings.TrimSpace(plan.String())
  2090  	sort.Strings(expectedState)
  2091  	expected := strings.TrimSpace(`
  2092  DIFF:
  2093  
  2094  
  2095  
  2096  STATE:
  2097  
  2098  aws_instance.foo.0:
  2099    ID = i-abc0
  2100  aws_instance.foo.1:
  2101    ID = i-abc1
  2102  aws_instance.foo.10:
  2103    ID = i-abc10
  2104  aws_instance.foo.11:
  2105    ID = i-abc11
  2106  aws_instance.foo.12:
  2107    ID = i-abc12
  2108  aws_instance.foo.2:
  2109    ID = i-abc2
  2110  aws_instance.foo.3:
  2111    ID = i-abc3
  2112  aws_instance.foo.4:
  2113    ID = i-abc4
  2114  aws_instance.foo.5:
  2115    ID = i-abc5
  2116  aws_instance.foo.6:
  2117    ID = i-abc6
  2118  aws_instance.foo.7:
  2119    ID = i-abc7
  2120  aws_instance.foo.8:
  2121    ID = i-abc8
  2122  aws_instance.foo.9:
  2123    ID = i-abc9
  2124  	`)
  2125  	if actual != expected {
  2126  		t.Fatalf("expected:\n%s\n\ngot:\n%s", expected, actual)
  2127  	}
  2128  }
  2129  
  2130  func TestContext2Plan_provider(t *testing.T) {
  2131  	m := testModule(t, "plan-provider")
  2132  	p := testProvider("aws")
  2133  	p.DiffFn = testDiffFn
  2134  
  2135  	var value interface{}
  2136  	p.ConfigureFn = func(c *ResourceConfig) error {
  2137  		value, _ = c.Get("foo")
  2138  		return nil
  2139  	}
  2140  
  2141  	ctx := testContext2(t, &ContextOpts{
  2142  		Module: m,
  2143  		Providers: map[string]ResourceProviderFactory{
  2144  			"aws": testProviderFuncFixed(p),
  2145  		},
  2146  		Variables: map[string]string{
  2147  			"foo": "bar",
  2148  		},
  2149  	})
  2150  
  2151  	if _, err := ctx.Plan(); err != nil {
  2152  		t.Fatalf("err: %s", err)
  2153  	}
  2154  
  2155  	if value != "bar" {
  2156  		t.Fatalf("bad: %#v", value)
  2157  	}
  2158  }
  2159  
  2160  func TestContext2Plan_varListErr(t *testing.T) {
  2161  	m := testModule(t, "plan-var-list-err")
  2162  	p := testProvider("aws")
  2163  	ctx := testContext2(t, &ContextOpts{
  2164  		Module: m,
  2165  		Providers: map[string]ResourceProviderFactory{
  2166  			"aws": testProviderFuncFixed(p),
  2167  		},
  2168  	})
  2169  
  2170  	_, err := ctx.Plan()
  2171  
  2172  	if err == nil {
  2173  		t.Fatal("should error")
  2174  	}
  2175  }
  2176  
  2177  func TestContext2Plan_ignoreChanges(t *testing.T) {
  2178  	m := testModule(t, "plan-ignore-changes")
  2179  	p := testProvider("aws")
  2180  	p.DiffFn = testDiffFn
  2181  	s := &State{
  2182  		Modules: []*ModuleState{
  2183  			&ModuleState{
  2184  				Path: rootModulePath,
  2185  				Resources: map[string]*ResourceState{
  2186  					"aws_instance.foo": &ResourceState{
  2187  						Primary: &InstanceState{
  2188  							ID:         "bar",
  2189  							Attributes: map[string]string{"ami": "ami-abcd1234"},
  2190  						},
  2191  					},
  2192  				},
  2193  			},
  2194  		},
  2195  	}
  2196  	ctx := testContext2(t, &ContextOpts{
  2197  		Module: m,
  2198  		Providers: map[string]ResourceProviderFactory{
  2199  			"aws": testProviderFuncFixed(p),
  2200  		},
  2201  		Variables: map[string]string{
  2202  			"foo": "ami-1234abcd",
  2203  		},
  2204  		State: s,
  2205  	})
  2206  
  2207  	plan, err := ctx.Plan()
  2208  	if err != nil {
  2209  		t.Fatalf("err: %s", err)
  2210  	}
  2211  
  2212  	if len(plan.Diff.RootModule().Resources) < 1 {
  2213  		t.Fatalf("bad: %#v", plan.Diff.RootModule().Resources)
  2214  	}
  2215  
  2216  	actual := strings.TrimSpace(plan.String())
  2217  	expected := strings.TrimSpace(testTerraformPlanIgnoreChangesStr)
  2218  	if actual != expected {
  2219  		t.Fatalf("bad:\n%s\n\nexpected\n\n%s", actual, expected)
  2220  	}
  2221  }