github.com/ves/terraform@v0.8.0-beta2/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_basic(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]interface{}{
    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]interface{}{
   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]interface{}{
   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_moduleVarWrongTypeBasic(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_countBad(t *testing.T) {
   809  	m := testModule(t, "plan-prevent-destroy-count-bad")
   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.0": &ResourceState{
   823  							Type: "aws_instance",
   824  							Primary: &InstanceState{
   825  								ID: "i-abc123",
   826  							},
   827  						},
   828  						"aws_instance.foo.1": &ResourceState{
   829  							Type: "aws_instance",
   830  							Primary: &InstanceState{
   831  								ID: "i-abc345",
   832  							},
   833  						},
   834  					},
   835  				},
   836  			},
   837  		},
   838  	})
   839  
   840  	plan, err := ctx.Plan()
   841  
   842  	expectedErr := "aws_instance.foo.1: the plan would destroy"
   843  	if !strings.Contains(fmt.Sprintf("%s", err), expectedErr) {
   844  		t.Fatalf("expected err would contain %q\nerr: %s\nplan: %s",
   845  			expectedErr, err, plan)
   846  	}
   847  }
   848  
   849  func TestContext2Plan_preventDestroy_countGood(t *testing.T) {
   850  	m := testModule(t, "plan-prevent-destroy-count-good")
   851  	p := testProvider("aws")
   852  	p.DiffFn = testDiffFn
   853  	ctx := testContext2(t, &ContextOpts{
   854  		Module: m,
   855  		Providers: map[string]ResourceProviderFactory{
   856  			"aws": testProviderFuncFixed(p),
   857  		},
   858  		State: &State{
   859  			Modules: []*ModuleState{
   860  				&ModuleState{
   861  					Path: rootModulePath,
   862  					Resources: map[string]*ResourceState{
   863  						"aws_instance.foo.0": &ResourceState{
   864  							Type: "aws_instance",
   865  							Primary: &InstanceState{
   866  								ID: "i-abc123",
   867  							},
   868  						},
   869  						"aws_instance.foo.1": &ResourceState{
   870  							Type: "aws_instance",
   871  							Primary: &InstanceState{
   872  								ID: "i-abc345",
   873  							},
   874  						},
   875  					},
   876  				},
   877  			},
   878  		},
   879  	})
   880  
   881  	plan, err := ctx.Plan()
   882  	if err != nil {
   883  		t.Fatalf("err: %s", err)
   884  	}
   885  	if plan.Diff.Empty() {
   886  		t.Fatalf("Expected non-empty plan, got %s", plan.String())
   887  	}
   888  }
   889  
   890  func TestContext2Plan_preventDestroy_countGoodNoChange(t *testing.T) {
   891  	m := testModule(t, "plan-prevent-destroy-count-good")
   892  	p := testProvider("aws")
   893  	p.DiffFn = testDiffFn
   894  	ctx := testContext2(t, &ContextOpts{
   895  		Module: m,
   896  		Providers: map[string]ResourceProviderFactory{
   897  			"aws": testProviderFuncFixed(p),
   898  		},
   899  		State: &State{
   900  			Modules: []*ModuleState{
   901  				&ModuleState{
   902  					Path: rootModulePath,
   903  					Resources: map[string]*ResourceState{
   904  						"aws_instance.foo.0": &ResourceState{
   905  							Type: "aws_instance",
   906  							Primary: &InstanceState{
   907  								ID: "i-abc123",
   908  								Attributes: map[string]string{
   909  									"current": "0",
   910  									"type":    "aws_instance",
   911  								},
   912  							},
   913  						},
   914  					},
   915  				},
   916  			},
   917  		},
   918  	})
   919  
   920  	plan, err := ctx.Plan()
   921  	if err != nil {
   922  		t.Fatalf("err: %s", err)
   923  	}
   924  	if !plan.Diff.Empty() {
   925  		t.Fatalf("Expected empty plan, got %s", plan.String())
   926  	}
   927  }
   928  
   929  func TestContext2Plan_preventDestroy_destroyPlan(t *testing.T) {
   930  	m := testModule(t, "plan-prevent-destroy-good")
   931  	p := testProvider("aws")
   932  	p.DiffFn = testDiffFn
   933  	ctx := testContext2(t, &ContextOpts{
   934  		Module: m,
   935  		Providers: map[string]ResourceProviderFactory{
   936  			"aws": testProviderFuncFixed(p),
   937  		},
   938  		State: &State{
   939  			Modules: []*ModuleState{
   940  				&ModuleState{
   941  					Path: rootModulePath,
   942  					Resources: map[string]*ResourceState{
   943  						"aws_instance.foo": &ResourceState{
   944  							Type: "aws_instance",
   945  							Primary: &InstanceState{
   946  								ID: "i-abc123",
   947  							},
   948  						},
   949  					},
   950  				},
   951  			},
   952  		},
   953  		Destroy: true,
   954  	})
   955  
   956  	plan, err := ctx.Plan()
   957  
   958  	expectedErr := "aws_instance.foo: the plan would destroy"
   959  	if !strings.Contains(fmt.Sprintf("%s", err), expectedErr) {
   960  		t.Fatalf("expected err would contain %q\nerr: %s\nplan: %s",
   961  			expectedErr, err, plan)
   962  	}
   963  }
   964  
   965  func TestContext2Plan_provisionerCycle(t *testing.T) {
   966  	m := testModule(t, "plan-provisioner-cycle")
   967  	p := testProvider("aws")
   968  	p.DiffFn = testDiffFn
   969  	pr := testProvisioner()
   970  	ctx := testContext2(t, &ContextOpts{
   971  		Module: m,
   972  		Providers: map[string]ResourceProviderFactory{
   973  			"aws": testProviderFuncFixed(p),
   974  		},
   975  		Provisioners: map[string]ResourceProvisionerFactory{
   976  			"local-exec": testProvisionerFuncFixed(pr),
   977  		},
   978  	})
   979  
   980  	_, err := ctx.Plan()
   981  	if err == nil {
   982  		t.Fatalf("should error")
   983  	}
   984  }
   985  
   986  func TestContext2Plan_computed(t *testing.T) {
   987  	m := testModule(t, "plan-computed")
   988  	p := testProvider("aws")
   989  	p.DiffFn = testDiffFn
   990  	ctx := testContext2(t, &ContextOpts{
   991  		Module: m,
   992  		Providers: map[string]ResourceProviderFactory{
   993  			"aws": testProviderFuncFixed(p),
   994  		},
   995  	})
   996  
   997  	plan, err := ctx.Plan()
   998  	if err != nil {
   999  		t.Fatalf("err: %s", err)
  1000  	}
  1001  
  1002  	actual := strings.TrimSpace(plan.String())
  1003  	expected := strings.TrimSpace(testTerraformPlanComputedStr)
  1004  	if actual != expected {
  1005  		t.Fatalf("bad:\n%s", actual)
  1006  	}
  1007  }
  1008  
  1009  func TestContext2Plan_computedDataResource(t *testing.T) {
  1010  	m := testModule(t, "plan-computed-data-resource")
  1011  	p := testProvider("aws")
  1012  	p.DiffFn = testDiffFn
  1013  	ctx := testContext2(t, &ContextOpts{
  1014  		Module: m,
  1015  		Providers: map[string]ResourceProviderFactory{
  1016  			"aws": testProviderFuncFixed(p),
  1017  		},
  1018  	})
  1019  
  1020  	plan, err := ctx.Plan()
  1021  	if err != nil {
  1022  		t.Fatalf("err: %s", err)
  1023  	}
  1024  
  1025  	if got := len(plan.Diff.Modules); got != 1 {
  1026  		t.Fatalf("got %d modules; want 1", got)
  1027  	}
  1028  
  1029  	moduleDiff := plan.Diff.Modules[0]
  1030  
  1031  	if _, ok := moduleDiff.Resources["aws_instance.foo"]; !ok {
  1032  		t.Fatalf("missing diff for aws_instance.foo")
  1033  	}
  1034  	iDiff, ok := moduleDiff.Resources["data.aws_vpc.bar"]
  1035  	if !ok {
  1036  		t.Fatalf("missing diff for data.aws_vpc.bar")
  1037  	}
  1038  
  1039  	expectedDiff := &InstanceDiff{
  1040  		Attributes: map[string]*ResourceAttrDiff{
  1041  			"id": {
  1042  				NewComputed: true,
  1043  				RequiresNew: true,
  1044  				Type:        DiffAttrOutput,
  1045  			},
  1046  		},
  1047  	}
  1048  	if same, _ := expectedDiff.Same(iDiff); !same {
  1049  		t.Fatalf(
  1050  			"incorrect diff for data.aws_vpc.bar\ngot:  %#v\nwant: %#v",
  1051  			iDiff, expectedDiff,
  1052  		)
  1053  	}
  1054  }
  1055  
  1056  func TestContext2Plan_computedDataCountResource(t *testing.T) {
  1057  	m := testModule(t, "plan-computed-data-count")
  1058  	p := testProvider("aws")
  1059  	p.DiffFn = testDiffFn
  1060  	ctx := testContext2(t, &ContextOpts{
  1061  		Module: m,
  1062  		Providers: map[string]ResourceProviderFactory{
  1063  			"aws": testProviderFuncFixed(p),
  1064  		},
  1065  	})
  1066  
  1067  	plan, err := ctx.Plan()
  1068  	if err != nil {
  1069  		t.Fatalf("err: %s", err)
  1070  	}
  1071  
  1072  	if got := len(plan.Diff.Modules); got != 1 {
  1073  		t.Fatalf("got %d modules; want 1", got)
  1074  	}
  1075  
  1076  	moduleDiff := plan.Diff.Modules[0]
  1077  
  1078  	// make sure we created 3 "bar"s
  1079  	for i := 0; i < 3; i++ {
  1080  		resource := fmt.Sprintf("data.aws_vpc.bar.%d", i)
  1081  		if _, ok := moduleDiff.Resources[resource]; !ok {
  1082  			t.Fatalf("missing diff for %s", resource)
  1083  		}
  1084  	}
  1085  }
  1086  
  1087  // Higher level test at TestResource_dataSourceListPlanPanic
  1088  func TestContext2Plan_dataSourceTypeMismatch(t *testing.T) {
  1089  	m := testModule(t, "plan-data-source-type-mismatch")
  1090  	p := testProvider("aws")
  1091  	p.ValidateResourceFn = func(t string, c *ResourceConfig) (ws []string, es []error) {
  1092  		// Emulate the type checking behavior of helper/schema based validation
  1093  		if t == "aws_instance" {
  1094  			ami, _ := c.Get("ami")
  1095  			switch a := ami.(type) {
  1096  			case string:
  1097  				// ok
  1098  			default:
  1099  				es = append(es, fmt.Errorf("Expected ami to be string, got %T", a))
  1100  			}
  1101  		}
  1102  		return
  1103  	}
  1104  	p.DiffFn = func(
  1105  		info *InstanceInfo,
  1106  		state *InstanceState,
  1107  		c *ResourceConfig) (*InstanceDiff, error) {
  1108  		if info.Type == "aws_instance" {
  1109  			// If we get to the diff, we should be able to assume types
  1110  			ami, _ := c.Get("ami")
  1111  			_ = ami.(string)
  1112  		}
  1113  		return nil, nil
  1114  	}
  1115  	ctx := testContext2(t, &ContextOpts{
  1116  		Module: m,
  1117  		// Pretend like we ran a Refresh and the AZs data source was populated.
  1118  		State: &State{
  1119  			Modules: []*ModuleState{
  1120  				&ModuleState{
  1121  					Path: rootModulePath,
  1122  					Resources: map[string]*ResourceState{
  1123  						"data.aws_availability_zones.azs": &ResourceState{
  1124  							Type: "aws_availability_zones",
  1125  							Primary: &InstanceState{
  1126  								ID: "i-abc123",
  1127  								Attributes: map[string]string{
  1128  									"names.#": "2",
  1129  									"names.0": "us-east-1a",
  1130  									"names.1": "us-east-1b",
  1131  								},
  1132  							},
  1133  						},
  1134  					},
  1135  				},
  1136  			},
  1137  		},
  1138  		Providers: map[string]ResourceProviderFactory{
  1139  			"aws": testProviderFuncFixed(p),
  1140  		},
  1141  	})
  1142  
  1143  	_, err := ctx.Plan()
  1144  
  1145  	if err == nil {
  1146  		t.Fatalf("Expected err, got none!")
  1147  	}
  1148  	expected := "Expected ami to be string"
  1149  	if !strings.Contains(err.Error(), expected) {
  1150  		t.Fatalf("expected:\n\n%s\n\nto contain:\n\n%s", err, expected)
  1151  	}
  1152  }
  1153  
  1154  func TestContext2Plan_dataResourceBecomesComputed(t *testing.T) {
  1155  	m := testModule(t, "plan-data-resource-becomes-computed")
  1156  	p := testProvider("aws")
  1157  
  1158  	p.DiffFn = func(info *InstanceInfo, state *InstanceState, config *ResourceConfig) (*InstanceDiff, error) {
  1159  		if info.Type != "aws_instance" {
  1160  			t.Fatalf("don't know how to diff %s", info.Id)
  1161  			return nil, nil
  1162  		}
  1163  
  1164  		return &InstanceDiff{
  1165  			Attributes: map[string]*ResourceAttrDiff{
  1166  				"computed": &ResourceAttrDiff{
  1167  					Old:         "",
  1168  					New:         "",
  1169  					NewComputed: true,
  1170  				},
  1171  			},
  1172  		}, nil
  1173  	}
  1174  	p.ReadDataDiffReturn = &InstanceDiff{
  1175  		Attributes: map[string]*ResourceAttrDiff{
  1176  			"foo": &ResourceAttrDiff{
  1177  				Old:         "",
  1178  				New:         "",
  1179  				NewComputed: true,
  1180  			},
  1181  		},
  1182  	}
  1183  
  1184  	ctx := testContext2(t, &ContextOpts{
  1185  		Module: m,
  1186  		Providers: map[string]ResourceProviderFactory{
  1187  			"aws": testProviderFuncFixed(p),
  1188  		},
  1189  		State: &State{
  1190  			Modules: []*ModuleState{
  1191  				&ModuleState{
  1192  					Path: rootModulePath,
  1193  					Resources: map[string]*ResourceState{
  1194  						"data.aws_data_resource.foo": &ResourceState{
  1195  							Type: "aws_data_resource",
  1196  							Primary: &InstanceState{
  1197  								ID: "i-abc123",
  1198  								Attributes: map[string]string{
  1199  									"id":    "i-abc123",
  1200  									"value": "baz",
  1201  								},
  1202  							},
  1203  						},
  1204  					},
  1205  				},
  1206  			},
  1207  		},
  1208  	})
  1209  
  1210  	plan, err := ctx.Plan()
  1211  	if err != nil {
  1212  		t.Fatalf("err: %s", err)
  1213  	}
  1214  
  1215  	if got := len(plan.Diff.Modules); got != 1 {
  1216  		t.Fatalf("got %d modules; want 1", got)
  1217  	}
  1218  
  1219  	if !p.ReadDataDiffCalled {
  1220  		t.Fatal("ReadDataDiff wasn't called, but should've been")
  1221  	}
  1222  	if got, want := p.ReadDataDiffInfo.Id, "data.aws_data_resource.foo"; got != want {
  1223  		t.Fatalf("ReadDataDiff info id is %s; want %s", got, want)
  1224  	}
  1225  
  1226  	moduleDiff := plan.Diff.Modules[0]
  1227  
  1228  	iDiff, ok := moduleDiff.Resources["data.aws_data_resource.foo"]
  1229  	if !ok {
  1230  		t.Fatalf("missing diff for data.aws_data_resource.foo")
  1231  	}
  1232  
  1233  	// This is added by the diff but we want to verify that we got
  1234  	// the same diff as above minus the dynamic stuff.
  1235  	delete(iDiff.Attributes, "id")
  1236  
  1237  	if same, _ := p.ReadDataDiffReturn.Same(iDiff); !same {
  1238  		t.Fatalf(
  1239  			"incorrect diff for data.data_resource.foo\ngot:  %#v\nwant: %#v",
  1240  			iDiff, p.ReadDataDiffReturn,
  1241  		)
  1242  	}
  1243  }
  1244  
  1245  func TestContext2Plan_computedList(t *testing.T) {
  1246  	m := testModule(t, "plan-computed-list")
  1247  	p := testProvider("aws")
  1248  	p.DiffFn = testDiffFn
  1249  	ctx := testContext2(t, &ContextOpts{
  1250  		Module: m,
  1251  		Providers: map[string]ResourceProviderFactory{
  1252  			"aws": testProviderFuncFixed(p),
  1253  		},
  1254  	})
  1255  
  1256  	plan, err := ctx.Plan()
  1257  	if err != nil {
  1258  		t.Fatalf("err: %s", err)
  1259  	}
  1260  
  1261  	actual := strings.TrimSpace(plan.String())
  1262  	expected := strings.TrimSpace(testTerraformPlanComputedListStr)
  1263  	if actual != expected {
  1264  		t.Fatalf("bad:\n%s", actual)
  1265  	}
  1266  }
  1267  
  1268  func TestContext2Plan_count(t *testing.T) {
  1269  	m := testModule(t, "plan-count")
  1270  	p := testProvider("aws")
  1271  	p.DiffFn = testDiffFn
  1272  	ctx := testContext2(t, &ContextOpts{
  1273  		Module: m,
  1274  		Providers: map[string]ResourceProviderFactory{
  1275  			"aws": testProviderFuncFixed(p),
  1276  		},
  1277  	})
  1278  
  1279  	plan, err := ctx.Plan()
  1280  	if err != nil {
  1281  		t.Fatalf("err: %s", err)
  1282  	}
  1283  
  1284  	if len(plan.Diff.RootModule().Resources) < 6 {
  1285  		t.Fatalf("bad: %#v", plan.Diff.RootModule().Resources)
  1286  	}
  1287  
  1288  	actual := strings.TrimSpace(plan.String())
  1289  	expected := strings.TrimSpace(testTerraformPlanCountStr)
  1290  	if actual != expected {
  1291  		t.Fatalf("bad:\n%s", actual)
  1292  	}
  1293  }
  1294  
  1295  func TestContext2Plan_countComputed(t *testing.T) {
  1296  	m := testModule(t, "plan-count-computed")
  1297  	p := testProvider("aws")
  1298  	p.DiffFn = testDiffFn
  1299  	ctx := testContext2(t, &ContextOpts{
  1300  		Module: m,
  1301  		Providers: map[string]ResourceProviderFactory{
  1302  			"aws": testProviderFuncFixed(p),
  1303  		},
  1304  	})
  1305  
  1306  	_, err := ctx.Plan()
  1307  	if err == nil {
  1308  		t.Fatal("should error")
  1309  	}
  1310  }
  1311  
  1312  func TestContext2Plan_countComputedModule(t *testing.T) {
  1313  	m := testModule(t, "plan-count-computed-module")
  1314  	p := testProvider("aws")
  1315  	p.DiffFn = testDiffFn
  1316  	ctx := testContext2(t, &ContextOpts{
  1317  		Module: m,
  1318  		Providers: map[string]ResourceProviderFactory{
  1319  			"aws": testProviderFuncFixed(p),
  1320  		},
  1321  	})
  1322  
  1323  	_, err := ctx.Plan()
  1324  
  1325  	expectedErr := "aws_instance.bar: value of 'count'"
  1326  	if !strings.Contains(fmt.Sprintf("%s", err), expectedErr) {
  1327  		t.Fatalf("expected err would contain %q\nerr: %s\n",
  1328  			expectedErr, err)
  1329  	}
  1330  }
  1331  
  1332  func TestContext2Plan_countIndex(t *testing.T) {
  1333  	m := testModule(t, "plan-count-index")
  1334  	p := testProvider("aws")
  1335  	p.DiffFn = testDiffFn
  1336  	ctx := testContext2(t, &ContextOpts{
  1337  		Module: m,
  1338  		Providers: map[string]ResourceProviderFactory{
  1339  			"aws": testProviderFuncFixed(p),
  1340  		},
  1341  	})
  1342  
  1343  	plan, err := ctx.Plan()
  1344  	if err != nil {
  1345  		t.Fatalf("err: %s", err)
  1346  	}
  1347  
  1348  	actual := strings.TrimSpace(plan.String())
  1349  	expected := strings.TrimSpace(testTerraformPlanCountIndexStr)
  1350  	if actual != expected {
  1351  		t.Fatalf("bad:\n%s", actual)
  1352  	}
  1353  }
  1354  
  1355  func TestContext2Plan_countIndexZero(t *testing.T) {
  1356  	m := testModule(t, "plan-count-index-zero")
  1357  	p := testProvider("aws")
  1358  	p.DiffFn = testDiffFn
  1359  	ctx := testContext2(t, &ContextOpts{
  1360  		Module: m,
  1361  		Providers: map[string]ResourceProviderFactory{
  1362  			"aws": testProviderFuncFixed(p),
  1363  		},
  1364  	})
  1365  
  1366  	plan, err := ctx.Plan()
  1367  	if err != nil {
  1368  		t.Fatalf("err: %s", err)
  1369  	}
  1370  
  1371  	actual := strings.TrimSpace(plan.String())
  1372  	expected := strings.TrimSpace(testTerraformPlanCountIndexZeroStr)
  1373  	if actual != expected {
  1374  		t.Fatalf("bad:\n%s", actual)
  1375  	}
  1376  }
  1377  
  1378  func TestContext2Plan_countVar(t *testing.T) {
  1379  	m := testModule(t, "plan-count-var")
  1380  	p := testProvider("aws")
  1381  	p.DiffFn = testDiffFn
  1382  	ctx := testContext2(t, &ContextOpts{
  1383  		Module: m,
  1384  		Providers: map[string]ResourceProviderFactory{
  1385  			"aws": testProviderFuncFixed(p),
  1386  		},
  1387  		Variables: map[string]interface{}{
  1388  			"count": "3",
  1389  		},
  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(testTerraformPlanCountVarStr)
  1399  	if actual != expected {
  1400  		t.Fatalf("bad:\n%s", actual)
  1401  	}
  1402  }
  1403  
  1404  func TestContext2Plan_countZero(t *testing.T) {
  1405  	m := testModule(t, "plan-count-zero")
  1406  	p := testProvider("aws")
  1407  	p.DiffFn = testDiffFn
  1408  	ctx := testContext2(t, &ContextOpts{
  1409  		Module: m,
  1410  		Providers: map[string]ResourceProviderFactory{
  1411  			"aws": testProviderFuncFixed(p),
  1412  		},
  1413  	})
  1414  
  1415  	plan, err := ctx.Plan()
  1416  	if err != nil {
  1417  		t.Fatalf("err: %s", err)
  1418  	}
  1419  
  1420  	actual := strings.TrimSpace(plan.String())
  1421  	expected := strings.TrimSpace(testTerraformPlanCountZeroStr)
  1422  	if actual != expected {
  1423  		t.Logf("expected:\n%s", expected)
  1424  		t.Fatalf("bad:\n%s", actual)
  1425  	}
  1426  }
  1427  
  1428  func TestContext2Plan_countOneIndex(t *testing.T) {
  1429  	m := testModule(t, "plan-count-one-index")
  1430  	p := testProvider("aws")
  1431  	p.DiffFn = testDiffFn
  1432  	ctx := testContext2(t, &ContextOpts{
  1433  		Module: m,
  1434  		Providers: map[string]ResourceProviderFactory{
  1435  			"aws": testProviderFuncFixed(p),
  1436  		},
  1437  	})
  1438  
  1439  	plan, err := ctx.Plan()
  1440  	if err != nil {
  1441  		t.Fatalf("err: %s", err)
  1442  	}
  1443  
  1444  	actual := strings.TrimSpace(plan.String())
  1445  	expected := strings.TrimSpace(testTerraformPlanCountOneIndexStr)
  1446  	if actual != expected {
  1447  		t.Fatalf("bad:\n%s", actual)
  1448  	}
  1449  }
  1450  
  1451  func TestContext2Plan_countDecreaseToOne(t *testing.T) {
  1452  	m := testModule(t, "plan-count-dec")
  1453  	p := testProvider("aws")
  1454  	p.DiffFn = testDiffFn
  1455  	s := &State{
  1456  		Modules: []*ModuleState{
  1457  			&ModuleState{
  1458  				Path: rootModulePath,
  1459  				Resources: map[string]*ResourceState{
  1460  					"aws_instance.foo.0": &ResourceState{
  1461  						Type: "aws_instance",
  1462  						Primary: &InstanceState{
  1463  							ID: "bar",
  1464  							Attributes: map[string]string{
  1465  								"foo":  "foo",
  1466  								"type": "aws_instance",
  1467  							},
  1468  						},
  1469  					},
  1470  					"aws_instance.foo.1": &ResourceState{
  1471  						Type: "aws_instance",
  1472  						Primary: &InstanceState{
  1473  							ID: "bar",
  1474  						},
  1475  					},
  1476  					"aws_instance.foo.2": &ResourceState{
  1477  						Type: "aws_instance",
  1478  						Primary: &InstanceState{
  1479  							ID: "bar",
  1480  						},
  1481  					},
  1482  				},
  1483  			},
  1484  		},
  1485  	}
  1486  	ctx := testContext2(t, &ContextOpts{
  1487  		Module: m,
  1488  		Providers: map[string]ResourceProviderFactory{
  1489  			"aws": testProviderFuncFixed(p),
  1490  		},
  1491  		State: s,
  1492  	})
  1493  
  1494  	plan, err := ctx.Plan()
  1495  	if err != nil {
  1496  		t.Fatalf("err: %s", err)
  1497  	}
  1498  
  1499  	actual := strings.TrimSpace(plan.String())
  1500  	expected := strings.TrimSpace(testTerraformPlanCountDecreaseStr)
  1501  	if actual != expected {
  1502  		t.Fatalf("bad:\n%s", actual)
  1503  	}
  1504  }
  1505  
  1506  func TestContext2Plan_countIncreaseFromNotSet(t *testing.T) {
  1507  	m := testModule(t, "plan-count-inc")
  1508  	p := testProvider("aws")
  1509  	p.DiffFn = testDiffFn
  1510  	s := &State{
  1511  		Modules: []*ModuleState{
  1512  			&ModuleState{
  1513  				Path: rootModulePath,
  1514  				Resources: map[string]*ResourceState{
  1515  					"aws_instance.foo": &ResourceState{
  1516  						Type: "aws_instance",
  1517  						Primary: &InstanceState{
  1518  							ID: "bar",
  1519  							Attributes: map[string]string{
  1520  								"foo":  "foo",
  1521  								"type": "aws_instance",
  1522  							},
  1523  						},
  1524  					},
  1525  				},
  1526  			},
  1527  		},
  1528  	}
  1529  	ctx := testContext2(t, &ContextOpts{
  1530  		Module: m,
  1531  		Providers: map[string]ResourceProviderFactory{
  1532  			"aws": testProviderFuncFixed(p),
  1533  		},
  1534  		State: s,
  1535  	})
  1536  
  1537  	plan, err := ctx.Plan()
  1538  	if err != nil {
  1539  		t.Fatalf("err: %s", err)
  1540  	}
  1541  
  1542  	actual := strings.TrimSpace(plan.String())
  1543  	expected := strings.TrimSpace(testTerraformPlanCountIncreaseStr)
  1544  	if actual != expected {
  1545  		t.Fatalf("bad:\n%s", actual)
  1546  	}
  1547  }
  1548  
  1549  func TestContext2Plan_countIncreaseFromOne(t *testing.T) {
  1550  	m := testModule(t, "plan-count-inc")
  1551  	p := testProvider("aws")
  1552  	p.DiffFn = testDiffFn
  1553  	s := &State{
  1554  		Modules: []*ModuleState{
  1555  			&ModuleState{
  1556  				Path: rootModulePath,
  1557  				Resources: map[string]*ResourceState{
  1558  					"aws_instance.foo.0": &ResourceState{
  1559  						Type: "aws_instance",
  1560  						Primary: &InstanceState{
  1561  							ID: "bar",
  1562  							Attributes: map[string]string{
  1563  								"foo":  "foo",
  1564  								"type": "aws_instance",
  1565  							},
  1566  						},
  1567  					},
  1568  				},
  1569  			},
  1570  		},
  1571  	}
  1572  	ctx := testContext2(t, &ContextOpts{
  1573  		Module: m,
  1574  		Providers: map[string]ResourceProviderFactory{
  1575  			"aws": testProviderFuncFixed(p),
  1576  		},
  1577  		State: s,
  1578  	})
  1579  
  1580  	plan, err := ctx.Plan()
  1581  	if err != nil {
  1582  		t.Fatalf("err: %s", err)
  1583  	}
  1584  
  1585  	actual := strings.TrimSpace(plan.String())
  1586  	expected := strings.TrimSpace(testTerraformPlanCountIncreaseFromOneStr)
  1587  	if actual != expected {
  1588  		t.Fatalf("bad:\n%s", actual)
  1589  	}
  1590  }
  1591  
  1592  // https://github.com/PeoplePerHour/terraform/pull/11
  1593  //
  1594  // This tests a case where both a "resource" and "resource.0" are in
  1595  // the state file, which apparently is a reasonable backwards compatibility
  1596  // concern found in the above 3rd party repo.
  1597  func TestContext2Plan_countIncreaseFromOneCorrupted(t *testing.T) {
  1598  	m := testModule(t, "plan-count-inc")
  1599  	p := testProvider("aws")
  1600  	p.DiffFn = testDiffFn
  1601  	s := &State{
  1602  		Modules: []*ModuleState{
  1603  			&ModuleState{
  1604  				Path: rootModulePath,
  1605  				Resources: map[string]*ResourceState{
  1606  					"aws_instance.foo": &ResourceState{
  1607  						Type: "aws_instance",
  1608  						Primary: &InstanceState{
  1609  							ID: "bar",
  1610  							Attributes: map[string]string{
  1611  								"foo":  "foo",
  1612  								"type": "aws_instance",
  1613  							},
  1614  						},
  1615  					},
  1616  					"aws_instance.foo.0": &ResourceState{
  1617  						Type: "aws_instance",
  1618  						Primary: &InstanceState{
  1619  							ID: "bar",
  1620  							Attributes: map[string]string{
  1621  								"foo":  "foo",
  1622  								"type": "aws_instance",
  1623  							},
  1624  						},
  1625  					},
  1626  				},
  1627  			},
  1628  		},
  1629  	}
  1630  	ctx := testContext2(t, &ContextOpts{
  1631  		Module: m,
  1632  		Providers: map[string]ResourceProviderFactory{
  1633  			"aws": testProviderFuncFixed(p),
  1634  		},
  1635  		State: s,
  1636  	})
  1637  
  1638  	plan, err := ctx.Plan()
  1639  	if err != nil {
  1640  		t.Fatalf("err: %s", err)
  1641  	}
  1642  
  1643  	actual := strings.TrimSpace(plan.String())
  1644  	expected := strings.TrimSpace(testTerraformPlanCountIncreaseFromOneCorruptedStr)
  1645  	if actual != expected {
  1646  		t.Fatalf("bad:\n%s", actual)
  1647  	}
  1648  }
  1649  
  1650  func TestContext2Plan_destroy(t *testing.T) {
  1651  	m := testModule(t, "plan-destroy")
  1652  	p := testProvider("aws")
  1653  	p.DiffFn = testDiffFn
  1654  	s := &State{
  1655  		Modules: []*ModuleState{
  1656  			&ModuleState{
  1657  				Path: rootModulePath,
  1658  				Resources: map[string]*ResourceState{
  1659  					"aws_instance.one": &ResourceState{
  1660  						Type: "aws_instance",
  1661  						Primary: &InstanceState{
  1662  							ID: "bar",
  1663  						},
  1664  					},
  1665  					"aws_instance.two": &ResourceState{
  1666  						Type: "aws_instance",
  1667  						Primary: &InstanceState{
  1668  							ID: "baz",
  1669  						},
  1670  					},
  1671  				},
  1672  			},
  1673  		},
  1674  	}
  1675  	ctx := testContext2(t, &ContextOpts{
  1676  		Module: m,
  1677  		Providers: map[string]ResourceProviderFactory{
  1678  			"aws": testProviderFuncFixed(p),
  1679  		},
  1680  		State:   s,
  1681  		Destroy: true,
  1682  	})
  1683  
  1684  	plan, err := ctx.Plan()
  1685  	if err != nil {
  1686  		t.Fatalf("err: %s", err)
  1687  	}
  1688  
  1689  	if len(plan.Diff.RootModule().Resources) != 2 {
  1690  		t.Fatalf("bad: %#v", plan.Diff.RootModule().Resources)
  1691  	}
  1692  
  1693  	actual := strings.TrimSpace(plan.String())
  1694  	expected := strings.TrimSpace(testTerraformPlanDestroyStr)
  1695  	if actual != expected {
  1696  		t.Fatalf("bad:\n%s", actual)
  1697  	}
  1698  }
  1699  
  1700  func TestContext2Plan_moduleDestroy(t *testing.T) {
  1701  	m := testModule(t, "plan-module-destroy")
  1702  	p := testProvider("aws")
  1703  	p.DiffFn = testDiffFn
  1704  	s := &State{
  1705  		Modules: []*ModuleState{
  1706  			&ModuleState{
  1707  				Path: rootModulePath,
  1708  				Resources: map[string]*ResourceState{
  1709  					"aws_instance.foo": &ResourceState{
  1710  						Type: "aws_instance",
  1711  						Primary: &InstanceState{
  1712  							ID: "bar",
  1713  						},
  1714  					},
  1715  				},
  1716  			},
  1717  			&ModuleState{
  1718  				Path: []string{"root", "child"},
  1719  				Resources: map[string]*ResourceState{
  1720  					"aws_instance.foo": &ResourceState{
  1721  						Type: "aws_instance",
  1722  						Primary: &InstanceState{
  1723  							ID: "bar",
  1724  						},
  1725  					},
  1726  				},
  1727  			},
  1728  		},
  1729  	}
  1730  	ctx := testContext2(t, &ContextOpts{
  1731  		Module: m,
  1732  		Providers: map[string]ResourceProviderFactory{
  1733  			"aws": testProviderFuncFixed(p),
  1734  		},
  1735  		State:   s,
  1736  		Destroy: true,
  1737  	})
  1738  
  1739  	plan, err := ctx.Plan()
  1740  	if err != nil {
  1741  		t.Fatalf("err: %s", err)
  1742  	}
  1743  
  1744  	actual := strings.TrimSpace(plan.String())
  1745  	expected := strings.TrimSpace(testTerraformPlanModuleDestroyStr)
  1746  	if actual != expected {
  1747  		t.Fatalf("bad:\n%s\n\nexpected:\n\n%s", actual, expected)
  1748  	}
  1749  }
  1750  
  1751  // GH-1835
  1752  func TestContext2Plan_moduleDestroyCycle(t *testing.T) {
  1753  	m := testModule(t, "plan-module-destroy-gh-1835")
  1754  	p := testProvider("aws")
  1755  	p.DiffFn = testDiffFn
  1756  	s := &State{
  1757  		Modules: []*ModuleState{
  1758  			&ModuleState{
  1759  				Path: []string{"root", "a_module"},
  1760  				Resources: map[string]*ResourceState{
  1761  					"aws_instance.a": &ResourceState{
  1762  						Type: "aws_instance",
  1763  						Primary: &InstanceState{
  1764  							ID: "a",
  1765  						},
  1766  					},
  1767  				},
  1768  			},
  1769  			&ModuleState{
  1770  				Path: []string{"root", "b_module"},
  1771  				Resources: map[string]*ResourceState{
  1772  					"aws_instance.b": &ResourceState{
  1773  						Type: "aws_instance",
  1774  						Primary: &InstanceState{
  1775  							ID: "b",
  1776  						},
  1777  					},
  1778  				},
  1779  			},
  1780  		},
  1781  	}
  1782  	ctx := testContext2(t, &ContextOpts{
  1783  		Module: m,
  1784  		Providers: map[string]ResourceProviderFactory{
  1785  			"aws": testProviderFuncFixed(p),
  1786  		},
  1787  		State:   s,
  1788  		Destroy: true,
  1789  	})
  1790  
  1791  	plan, err := ctx.Plan()
  1792  	if err != nil {
  1793  		t.Fatalf("err: %s", err)
  1794  	}
  1795  
  1796  	actual := strings.TrimSpace(plan.String())
  1797  	expected := strings.TrimSpace(testTerraformPlanModuleDestroyCycleStr)
  1798  	if actual != expected {
  1799  		t.Fatalf("bad:\n%s\n\nexpected:\n\n%s", actual, expected)
  1800  	}
  1801  }
  1802  
  1803  func TestContext2Plan_moduleDestroyMultivar(t *testing.T) {
  1804  	m := testModule(t, "plan-module-destroy-multivar")
  1805  	p := testProvider("aws")
  1806  	p.DiffFn = testDiffFn
  1807  	s := &State{
  1808  		Modules: []*ModuleState{
  1809  			&ModuleState{
  1810  				Path:      rootModulePath,
  1811  				Resources: map[string]*ResourceState{},
  1812  			},
  1813  			&ModuleState{
  1814  				Path: []string{"root", "child"},
  1815  				Resources: map[string]*ResourceState{
  1816  					"aws_instance.foo.0": &ResourceState{
  1817  						Type: "aws_instance",
  1818  						Primary: &InstanceState{
  1819  							ID: "bar0",
  1820  						},
  1821  					},
  1822  					"aws_instance.foo.1": &ResourceState{
  1823  						Type: "aws_instance",
  1824  						Primary: &InstanceState{
  1825  							ID: "bar1",
  1826  						},
  1827  					},
  1828  				},
  1829  			},
  1830  		},
  1831  	}
  1832  	ctx := testContext2(t, &ContextOpts{
  1833  		Module: m,
  1834  		Providers: map[string]ResourceProviderFactory{
  1835  			"aws": testProviderFuncFixed(p),
  1836  		},
  1837  		State:   s,
  1838  		Destroy: true,
  1839  	})
  1840  
  1841  	plan, err := ctx.Plan()
  1842  	if err != nil {
  1843  		t.Fatalf("err: %s", err)
  1844  	}
  1845  
  1846  	actual := strings.TrimSpace(plan.String())
  1847  	expected := strings.TrimSpace(testTerraformPlanModuleDestroyMultivarStr)
  1848  	if actual != expected {
  1849  		t.Fatalf("bad:\n%s\n\nexpected:\n\n%s", actual, expected)
  1850  	}
  1851  }
  1852  
  1853  func TestContext2Plan_pathVar(t *testing.T) {
  1854  	cwd, err := os.Getwd()
  1855  	if err != nil {
  1856  		t.Fatalf("err: %s", err)
  1857  	}
  1858  
  1859  	m := testModule(t, "plan-path-var")
  1860  	p := testProvider("aws")
  1861  	p.DiffFn = testDiffFn
  1862  	ctx := testContext2(t, &ContextOpts{
  1863  		Module: m,
  1864  		Providers: map[string]ResourceProviderFactory{
  1865  			"aws": testProviderFuncFixed(p),
  1866  		},
  1867  	})
  1868  
  1869  	plan, err := ctx.Plan()
  1870  	if err != nil {
  1871  		t.Fatalf("err: %s", err)
  1872  	}
  1873  
  1874  	actual := strings.TrimSpace(plan.String())
  1875  	expected := strings.TrimSpace(testTerraformPlanPathVarStr)
  1876  
  1877  	// Warning: this ordering REALLY matters for this test. The
  1878  	// order is: cwd, module, root.
  1879  	expected = fmt.Sprintf(
  1880  		expected,
  1881  		cwd,
  1882  		m.Config().Dir,
  1883  		m.Config().Dir)
  1884  
  1885  	if actual != expected {
  1886  		t.Fatalf("bad:\n%s\n\nexpected:\n\n%s", actual, expected)
  1887  	}
  1888  }
  1889  
  1890  func TestContext2Plan_diffVar(t *testing.T) {
  1891  	m := testModule(t, "plan-diffvar")
  1892  	p := testProvider("aws")
  1893  	s := &State{
  1894  		Modules: []*ModuleState{
  1895  			&ModuleState{
  1896  				Path: rootModulePath,
  1897  				Resources: map[string]*ResourceState{
  1898  					"aws_instance.foo": &ResourceState{
  1899  						Primary: &InstanceState{
  1900  							ID: "bar",
  1901  							Attributes: map[string]string{
  1902  								"num": "2",
  1903  							},
  1904  						},
  1905  					},
  1906  				},
  1907  			},
  1908  		},
  1909  	}
  1910  	ctx := testContext2(t, &ContextOpts{
  1911  		Module: m,
  1912  		Providers: map[string]ResourceProviderFactory{
  1913  			"aws": testProviderFuncFixed(p),
  1914  		},
  1915  		State: s,
  1916  	})
  1917  
  1918  	p.DiffFn = func(
  1919  		info *InstanceInfo,
  1920  		s *InstanceState,
  1921  		c *ResourceConfig) (*InstanceDiff, error) {
  1922  		if s.ID != "bar" {
  1923  			return testDiffFn(info, s, c)
  1924  		}
  1925  
  1926  		return &InstanceDiff{
  1927  			Attributes: map[string]*ResourceAttrDiff{
  1928  				"num": &ResourceAttrDiff{
  1929  					Old: "2",
  1930  					New: "3",
  1931  				},
  1932  			},
  1933  		}, nil
  1934  	}
  1935  
  1936  	plan, err := ctx.Plan()
  1937  	if err != nil {
  1938  		t.Fatalf("err: %s", err)
  1939  	}
  1940  
  1941  	actual := strings.TrimSpace(plan.String())
  1942  	expected := strings.TrimSpace(testTerraformPlanDiffVarStr)
  1943  	if actual != expected {
  1944  		t.Fatalf("actual:\n%s\n\nexpected:\n%s", actual, expected)
  1945  	}
  1946  }
  1947  
  1948  func TestContext2Plan_hook(t *testing.T) {
  1949  	m := testModule(t, "plan-good")
  1950  	h := new(MockHook)
  1951  	p := testProvider("aws")
  1952  	p.DiffFn = testDiffFn
  1953  	ctx := testContext2(t, &ContextOpts{
  1954  		Module: m,
  1955  		Hooks:  []Hook{h},
  1956  		Providers: map[string]ResourceProviderFactory{
  1957  			"aws": testProviderFuncFixed(p),
  1958  		},
  1959  	})
  1960  
  1961  	_, err := ctx.Plan()
  1962  	if err != nil {
  1963  		t.Fatalf("err: %s", err)
  1964  	}
  1965  
  1966  	if !h.PreDiffCalled {
  1967  		t.Fatal("should be called")
  1968  	}
  1969  	if !h.PostDiffCalled {
  1970  		t.Fatal("should be called")
  1971  	}
  1972  }
  1973  
  1974  func TestContext2Plan_orphan(t *testing.T) {
  1975  	m := testModule(t, "plan-orphan")
  1976  	p := testProvider("aws")
  1977  	p.DiffFn = testDiffFn
  1978  	s := &State{
  1979  		Modules: []*ModuleState{
  1980  			&ModuleState{
  1981  				Path: rootModulePath,
  1982  				Resources: map[string]*ResourceState{
  1983  					"aws_instance.baz": &ResourceState{
  1984  						Type: "aws_instance",
  1985  						Primary: &InstanceState{
  1986  							ID: "bar",
  1987  						},
  1988  					},
  1989  				},
  1990  			},
  1991  		},
  1992  	}
  1993  	ctx := testContext2(t, &ContextOpts{
  1994  		Module: m,
  1995  		Providers: map[string]ResourceProviderFactory{
  1996  			"aws": testProviderFuncFixed(p),
  1997  		},
  1998  		State: s,
  1999  	})
  2000  
  2001  	plan, err := ctx.Plan()
  2002  	if err != nil {
  2003  		t.Fatalf("err: %s", err)
  2004  	}
  2005  
  2006  	actual := strings.TrimSpace(plan.String())
  2007  	expected := strings.TrimSpace(testTerraformPlanOrphanStr)
  2008  	if actual != expected {
  2009  		t.Fatalf("bad:\n%s", actual)
  2010  	}
  2011  }
  2012  
  2013  // This tests that configurations with UUIDs don't produce errors.
  2014  // For shadows, this would produce errors since a UUID changes every time.
  2015  func TestContext2Plan_shadowUuid(t *testing.T) {
  2016  	m := testModule(t, "plan-shadow-uuid")
  2017  	p := testProvider("aws")
  2018  	p.DiffFn = testDiffFn
  2019  	ctx := testContext2(t, &ContextOpts{
  2020  		Module: m,
  2021  		Providers: map[string]ResourceProviderFactory{
  2022  			"aws": testProviderFuncFixed(p),
  2023  		},
  2024  	})
  2025  
  2026  	_, err := ctx.Plan()
  2027  	if err != nil {
  2028  		t.Fatalf("err: %s", err)
  2029  	}
  2030  }
  2031  
  2032  func TestContext2Plan_state(t *testing.T) {
  2033  	m := testModule(t, "plan-good")
  2034  	p := testProvider("aws")
  2035  	p.DiffFn = testDiffFn
  2036  	s := &State{
  2037  		Modules: []*ModuleState{
  2038  			&ModuleState{
  2039  				Path: rootModulePath,
  2040  				Resources: map[string]*ResourceState{
  2041  					"aws_instance.foo": &ResourceState{
  2042  						Primary: &InstanceState{
  2043  							ID: "bar",
  2044  						},
  2045  					},
  2046  				},
  2047  			},
  2048  		},
  2049  	}
  2050  	ctx := testContext2(t, &ContextOpts{
  2051  		Module: m,
  2052  		Providers: map[string]ResourceProviderFactory{
  2053  			"aws": testProviderFuncFixed(p),
  2054  		},
  2055  		State: s,
  2056  	})
  2057  
  2058  	plan, err := ctx.Plan()
  2059  	if err != nil {
  2060  		t.Fatalf("err: %s", err)
  2061  	}
  2062  
  2063  	if len(plan.Diff.RootModule().Resources) < 2 {
  2064  		t.Fatalf("bad: %#v", plan.Diff.RootModule().Resources)
  2065  	}
  2066  
  2067  	actual := strings.TrimSpace(plan.String())
  2068  	expected := strings.TrimSpace(testTerraformPlanStateStr)
  2069  	if actual != expected {
  2070  		t.Fatalf("bad:\n%s\n\nexpected:\n\n%s", actual, expected)
  2071  	}
  2072  }
  2073  
  2074  func TestContext2Plan_taint(t *testing.T) {
  2075  	m := testModule(t, "plan-taint")
  2076  	p := testProvider("aws")
  2077  	p.DiffFn = testDiffFn
  2078  	s := &State{
  2079  		Modules: []*ModuleState{
  2080  			&ModuleState{
  2081  				Path: rootModulePath,
  2082  				Resources: map[string]*ResourceState{
  2083  					"aws_instance.foo": &ResourceState{
  2084  						Type: "aws_instance",
  2085  						Primary: &InstanceState{
  2086  							ID:         "bar",
  2087  							Attributes: map[string]string{"num": "2"},
  2088  						},
  2089  					},
  2090  					"aws_instance.bar": &ResourceState{
  2091  						Type: "aws_instance",
  2092  						Primary: &InstanceState{
  2093  							ID:      "baz",
  2094  							Tainted: true,
  2095  						},
  2096  					},
  2097  				},
  2098  			},
  2099  		},
  2100  	}
  2101  	ctx := testContext2(t, &ContextOpts{
  2102  		Module: m,
  2103  		Providers: map[string]ResourceProviderFactory{
  2104  			"aws": testProviderFuncFixed(p),
  2105  		},
  2106  		State: s,
  2107  	})
  2108  
  2109  	plan, err := ctx.Plan()
  2110  	if err != nil {
  2111  		t.Fatalf("err: %s", err)
  2112  	}
  2113  
  2114  	actual := strings.TrimSpace(plan.String())
  2115  	expected := strings.TrimSpace(testTerraformPlanTaintStr)
  2116  	if actual != expected {
  2117  		t.Fatalf("bad:\n%s", actual)
  2118  	}
  2119  }
  2120  
  2121  func TestContext2Apply_taintIgnoreChanges(t *testing.T) {
  2122  	m := testModule(t, "plan-taint-ignore-changes")
  2123  	p := testProvider("aws")
  2124  	p.ApplyFn = testApplyFn
  2125  	p.DiffFn = testDiffFn
  2126  	s := &State{
  2127  		Modules: []*ModuleState{
  2128  			&ModuleState{
  2129  				Path: rootModulePath,
  2130  				Resources: map[string]*ResourceState{
  2131  					"aws_instance.foo": &ResourceState{
  2132  						Type: "aws_instance",
  2133  						Primary: &InstanceState{
  2134  							ID: "foo",
  2135  							Attributes: map[string]string{
  2136  								"vars": "foo",
  2137  								"type": "aws_instance",
  2138  							},
  2139  							Tainted: true,
  2140  						},
  2141  					},
  2142  				},
  2143  			},
  2144  		},
  2145  	}
  2146  	ctx := testContext2(t, &ContextOpts{
  2147  		Module: m,
  2148  		Providers: map[string]ResourceProviderFactory{
  2149  			"aws": testProviderFuncFixed(p),
  2150  		},
  2151  		State: s,
  2152  	})
  2153  
  2154  	plan, err := ctx.Plan()
  2155  	if err != nil {
  2156  		t.Fatalf("err: %s", err)
  2157  	}
  2158  
  2159  	actual := strings.TrimSpace(plan.String())
  2160  	expected := strings.TrimSpace(testTerraformPlanTaintIgnoreChangesStr)
  2161  	if actual != expected {
  2162  		t.Fatalf("bad:\n%s", actual)
  2163  	}
  2164  }
  2165  
  2166  // Fails about 50% of the time before the fix for GH-4982, covers the fix.
  2167  func TestContext2Plan_taintDestroyInterpolatedCountRace(t *testing.T) {
  2168  	m := testModule(t, "plan-taint-interpolated-count")
  2169  	p := testProvider("aws")
  2170  	p.DiffFn = testDiffFn
  2171  	s := &State{
  2172  		Modules: []*ModuleState{
  2173  			&ModuleState{
  2174  				Path: rootModulePath,
  2175  				Resources: map[string]*ResourceState{
  2176  					"aws_instance.foo.0": &ResourceState{
  2177  						Type: "aws_instance",
  2178  						Primary: &InstanceState{
  2179  							ID:      "bar",
  2180  							Tainted: true,
  2181  						},
  2182  					},
  2183  					"aws_instance.foo.1": &ResourceState{
  2184  						Type:    "aws_instance",
  2185  						Primary: &InstanceState{ID: "bar"},
  2186  					},
  2187  					"aws_instance.foo.2": &ResourceState{
  2188  						Type:    "aws_instance",
  2189  						Primary: &InstanceState{ID: "bar"},
  2190  					},
  2191  				},
  2192  			},
  2193  		},
  2194  	}
  2195  	ctx := testContext2(t, &ContextOpts{
  2196  		Module: m,
  2197  		Providers: map[string]ResourceProviderFactory{
  2198  			"aws": testProviderFuncFixed(p),
  2199  		},
  2200  		State: s,
  2201  	})
  2202  
  2203  	for i := 0; i < 100; i++ {
  2204  		plan, err := ctx.Plan()
  2205  		if err != nil {
  2206  			t.Fatalf("err: %s", err)
  2207  		}
  2208  
  2209  		actual := strings.TrimSpace(plan.String())
  2210  		expected := strings.TrimSpace(`
  2211  DIFF:
  2212  
  2213  DESTROY/CREATE: aws_instance.foo.0
  2214    type: "" => "aws_instance"
  2215  
  2216  STATE:
  2217  
  2218  aws_instance.foo.0: (tainted)
  2219    ID = bar
  2220  aws_instance.foo.1:
  2221    ID = bar
  2222  aws_instance.foo.2:
  2223    ID = bar
  2224  		`)
  2225  		if actual != expected {
  2226  			t.Fatalf("[%d] bad:\n%s\nexpected:\n%s\n", i, actual, expected)
  2227  		}
  2228  	}
  2229  }
  2230  
  2231  func TestContext2Plan_targeted(t *testing.T) {
  2232  	m := testModule(t, "plan-targeted")
  2233  	p := testProvider("aws")
  2234  	p.DiffFn = testDiffFn
  2235  	ctx := testContext2(t, &ContextOpts{
  2236  		Module: m,
  2237  		Providers: map[string]ResourceProviderFactory{
  2238  			"aws": testProviderFuncFixed(p),
  2239  		},
  2240  		Targets: []string{"aws_instance.foo"},
  2241  	})
  2242  
  2243  	plan, err := ctx.Plan()
  2244  	if err != nil {
  2245  		t.Fatalf("err: %s", err)
  2246  	}
  2247  
  2248  	actual := strings.TrimSpace(plan.String())
  2249  	expected := strings.TrimSpace(`
  2250  DIFF:
  2251  
  2252  CREATE: aws_instance.foo
  2253    num:  "" => "2"
  2254    type: "" => "aws_instance"
  2255  
  2256  STATE:
  2257  
  2258  <no state>
  2259  	`)
  2260  	if actual != expected {
  2261  		t.Fatalf("expected:\n%s\n\ngot:\n%s", expected, actual)
  2262  	}
  2263  }
  2264  
  2265  func TestContext2Plan_targetedOrphan(t *testing.T) {
  2266  	m := testModule(t, "plan-targeted-orphan")
  2267  	p := testProvider("aws")
  2268  	p.DiffFn = testDiffFn
  2269  	ctx := testContext2(t, &ContextOpts{
  2270  		Module: m,
  2271  		Providers: map[string]ResourceProviderFactory{
  2272  			"aws": testProviderFuncFixed(p),
  2273  		},
  2274  		State: &State{
  2275  			Modules: []*ModuleState{
  2276  				&ModuleState{
  2277  					Path: rootModulePath,
  2278  					Resources: map[string]*ResourceState{
  2279  						"aws_instance.orphan": &ResourceState{
  2280  							Type: "aws_instance",
  2281  							Primary: &InstanceState{
  2282  								ID: "i-789xyz",
  2283  							},
  2284  						},
  2285  						"aws_instance.nottargeted": &ResourceState{
  2286  							Type: "aws_instance",
  2287  							Primary: &InstanceState{
  2288  								ID: "i-abc123",
  2289  							},
  2290  						},
  2291  					},
  2292  				},
  2293  			},
  2294  		},
  2295  		Destroy: true,
  2296  		Targets: []string{"aws_instance.orphan"},
  2297  	})
  2298  
  2299  	plan, err := ctx.Plan()
  2300  	if err != nil {
  2301  		t.Fatalf("err: %s", err)
  2302  	}
  2303  
  2304  	actual := strings.TrimSpace(plan.String())
  2305  	expected := strings.TrimSpace(`DIFF:
  2306  
  2307  DESTROY: aws_instance.orphan
  2308  
  2309  STATE:
  2310  
  2311  aws_instance.nottargeted:
  2312    ID = i-abc123
  2313  aws_instance.orphan:
  2314    ID = i-789xyz
  2315  `)
  2316  	if actual != expected {
  2317  		t.Fatalf("expected:\n%s\n\ngot:\n%s", expected, actual)
  2318  	}
  2319  }
  2320  
  2321  // https://github.com/hashicorp/terraform/issues/2538
  2322  func TestContext2Plan_targetedModuleOrphan(t *testing.T) {
  2323  	m := testModule(t, "plan-targeted-module-orphan")
  2324  	p := testProvider("aws")
  2325  	p.DiffFn = testDiffFn
  2326  	ctx := testContext2(t, &ContextOpts{
  2327  		Module: m,
  2328  		Providers: map[string]ResourceProviderFactory{
  2329  			"aws": testProviderFuncFixed(p),
  2330  		},
  2331  		State: &State{
  2332  			Modules: []*ModuleState{
  2333  				&ModuleState{
  2334  					Path: []string{"root", "child"},
  2335  					Resources: map[string]*ResourceState{
  2336  						"aws_instance.orphan": &ResourceState{
  2337  							Type: "aws_instance",
  2338  							Primary: &InstanceState{
  2339  								ID: "i-789xyz",
  2340  							},
  2341  						},
  2342  						"aws_instance.nottargeted": &ResourceState{
  2343  							Type: "aws_instance",
  2344  							Primary: &InstanceState{
  2345  								ID: "i-abc123",
  2346  							},
  2347  						},
  2348  					},
  2349  				},
  2350  			},
  2351  		},
  2352  		Destroy: true,
  2353  		Targets: []string{"module.child.aws_instance.orphan"},
  2354  	})
  2355  
  2356  	plan, err := ctx.Plan()
  2357  	if err != nil {
  2358  		t.Fatalf("err: %s", err)
  2359  	}
  2360  
  2361  	actual := strings.TrimSpace(plan.String())
  2362  	expected := strings.TrimSpace(`DIFF:
  2363  
  2364  module.child:
  2365    DESTROY: aws_instance.orphan
  2366  
  2367  STATE:
  2368  
  2369  module.child:
  2370    aws_instance.nottargeted:
  2371      ID = i-abc123
  2372    aws_instance.orphan:
  2373      ID = i-789xyz
  2374  `)
  2375  	if actual != expected {
  2376  		t.Fatalf("expected:\n%s\n\ngot:\n%s", expected, actual)
  2377  	}
  2378  }
  2379  
  2380  func TestContext2Plan_targetedModuleUntargetedVariable(t *testing.T) {
  2381  	m := testModule(t, "plan-targeted-module-untargeted-variable")
  2382  	p := testProvider("aws")
  2383  	p.DiffFn = testDiffFn
  2384  	ctx := testContext2(t, &ContextOpts{
  2385  		Module: m,
  2386  		Providers: map[string]ResourceProviderFactory{
  2387  			"aws": testProviderFuncFixed(p),
  2388  		},
  2389  		Targets: []string{"aws_instance.blue", "module.blue_mod"},
  2390  	})
  2391  
  2392  	plan, err := ctx.Plan()
  2393  	if err != nil {
  2394  		t.Fatalf("err: %s", err)
  2395  	}
  2396  
  2397  	actual := strings.TrimSpace(plan.String())
  2398  	expected := strings.TrimSpace(`
  2399  DIFF:
  2400  
  2401  CREATE: aws_instance.blue
  2402  
  2403  module.blue_mod:
  2404    CREATE: aws_instance.mod
  2405      type:  "" => "aws_instance"
  2406      value: "" => "<computed>"
  2407  
  2408  STATE:
  2409  
  2410  <no state>
  2411  `)
  2412  	if actual != expected {
  2413  		t.Fatalf("expected:\n%s\n\ngot:\n%s", expected, actual)
  2414  	}
  2415  }
  2416  
  2417  // https://github.com/hashicorp/terraform/issues/4515
  2418  func TestContext2Plan_targetedOverTen(t *testing.T) {
  2419  	m := testModule(t, "plan-targeted-over-ten")
  2420  	p := testProvider("aws")
  2421  	p.DiffFn = testDiffFn
  2422  
  2423  	resources := make(map[string]*ResourceState)
  2424  	var expectedState []string
  2425  	for i := 0; i < 13; i++ {
  2426  		key := fmt.Sprintf("aws_instance.foo.%d", i)
  2427  		id := fmt.Sprintf("i-abc%d", i)
  2428  		resources[key] = &ResourceState{
  2429  			Type:    "aws_instance",
  2430  			Primary: &InstanceState{ID: id},
  2431  		}
  2432  		expectedState = append(expectedState,
  2433  			fmt.Sprintf("%s:\n  ID = %s\n", key, id))
  2434  	}
  2435  	ctx := testContext2(t, &ContextOpts{
  2436  		Module: m,
  2437  		Providers: map[string]ResourceProviderFactory{
  2438  			"aws": testProviderFuncFixed(p),
  2439  		},
  2440  		State: &State{
  2441  			Modules: []*ModuleState{
  2442  				&ModuleState{
  2443  					Path:      rootModulePath,
  2444  					Resources: resources,
  2445  				},
  2446  			},
  2447  		},
  2448  		Targets: []string{"aws_instance.foo[1]"},
  2449  	})
  2450  
  2451  	plan, err := ctx.Plan()
  2452  	if err != nil {
  2453  		t.Fatalf("err: %s", err)
  2454  	}
  2455  
  2456  	actual := strings.TrimSpace(plan.String())
  2457  	sort.Strings(expectedState)
  2458  	expected := strings.TrimSpace(`
  2459  DIFF:
  2460  
  2461  
  2462  
  2463  STATE:
  2464  
  2465  aws_instance.foo.0:
  2466    ID = i-abc0
  2467  aws_instance.foo.1:
  2468    ID = i-abc1
  2469  aws_instance.foo.10:
  2470    ID = i-abc10
  2471  aws_instance.foo.11:
  2472    ID = i-abc11
  2473  aws_instance.foo.12:
  2474    ID = i-abc12
  2475  aws_instance.foo.2:
  2476    ID = i-abc2
  2477  aws_instance.foo.3:
  2478    ID = i-abc3
  2479  aws_instance.foo.4:
  2480    ID = i-abc4
  2481  aws_instance.foo.5:
  2482    ID = i-abc5
  2483  aws_instance.foo.6:
  2484    ID = i-abc6
  2485  aws_instance.foo.7:
  2486    ID = i-abc7
  2487  aws_instance.foo.8:
  2488    ID = i-abc8
  2489  aws_instance.foo.9:
  2490    ID = i-abc9
  2491  	`)
  2492  	if actual != expected {
  2493  		t.Fatalf("expected:\n%s\n\ngot:\n%s", expected, actual)
  2494  	}
  2495  }
  2496  
  2497  func TestContext2Plan_provider(t *testing.T) {
  2498  	m := testModule(t, "plan-provider")
  2499  	p := testProvider("aws")
  2500  	p.DiffFn = testDiffFn
  2501  
  2502  	var value interface{}
  2503  	p.ConfigureFn = func(c *ResourceConfig) error {
  2504  		value, _ = c.Get("foo")
  2505  		return nil
  2506  	}
  2507  
  2508  	ctx := testContext2(t, &ContextOpts{
  2509  		Module: m,
  2510  		Providers: map[string]ResourceProviderFactory{
  2511  			"aws": testProviderFuncFixed(p),
  2512  		},
  2513  		Variables: map[string]interface{}{
  2514  			"foo": "bar",
  2515  		},
  2516  	})
  2517  
  2518  	if _, err := ctx.Plan(); err != nil {
  2519  		t.Fatalf("err: %s", err)
  2520  	}
  2521  
  2522  	if value != "bar" {
  2523  		t.Fatalf("bad: %#v", value)
  2524  	}
  2525  }
  2526  
  2527  func TestContext2Plan_varListErr(t *testing.T) {
  2528  	m := testModule(t, "plan-var-list-err")
  2529  	p := testProvider("aws")
  2530  	ctx := testContext2(t, &ContextOpts{
  2531  		Module: m,
  2532  		Providers: map[string]ResourceProviderFactory{
  2533  			"aws": testProviderFuncFixed(p),
  2534  		},
  2535  	})
  2536  
  2537  	_, err := ctx.Plan()
  2538  
  2539  	if err == nil {
  2540  		t.Fatal("should error")
  2541  	}
  2542  }
  2543  
  2544  func TestContext2Plan_ignoreChanges(t *testing.T) {
  2545  	m := testModule(t, "plan-ignore-changes")
  2546  	p := testProvider("aws")
  2547  	p.DiffFn = testDiffFn
  2548  	s := &State{
  2549  		Modules: []*ModuleState{
  2550  			&ModuleState{
  2551  				Path: rootModulePath,
  2552  				Resources: map[string]*ResourceState{
  2553  					"aws_instance.foo": &ResourceState{
  2554  						Primary: &InstanceState{
  2555  							ID:         "bar",
  2556  							Attributes: map[string]string{"ami": "ami-abcd1234"},
  2557  						},
  2558  					},
  2559  				},
  2560  			},
  2561  		},
  2562  	}
  2563  	ctx := testContext2(t, &ContextOpts{
  2564  		Module: m,
  2565  		Providers: map[string]ResourceProviderFactory{
  2566  			"aws": testProviderFuncFixed(p),
  2567  		},
  2568  		Variables: map[string]interface{}{
  2569  			"foo": "ami-1234abcd",
  2570  		},
  2571  		State: s,
  2572  	})
  2573  
  2574  	plan, err := ctx.Plan()
  2575  	if err != nil {
  2576  		t.Fatalf("err: %s", err)
  2577  	}
  2578  
  2579  	if len(plan.Diff.RootModule().Resources) < 1 {
  2580  		t.Fatalf("bad: %#v", plan.Diff.RootModule().Resources)
  2581  	}
  2582  
  2583  	actual := strings.TrimSpace(plan.String())
  2584  	expected := strings.TrimSpace(testTerraformPlanIgnoreChangesStr)
  2585  	if actual != expected {
  2586  		t.Fatalf("bad:\n%s\n\nexpected\n\n%s", actual, expected)
  2587  	}
  2588  }
  2589  
  2590  func TestContext2Plan_ignoreChangesWildcard(t *testing.T) {
  2591  	m := testModule(t, "plan-ignore-changes-wildcard")
  2592  	p := testProvider("aws")
  2593  	p.DiffFn = testDiffFn
  2594  	s := &State{
  2595  		Modules: []*ModuleState{
  2596  			&ModuleState{
  2597  				Path: rootModulePath,
  2598  				Resources: map[string]*ResourceState{
  2599  					"aws_instance.foo": &ResourceState{
  2600  						Primary: &InstanceState{
  2601  							ID: "bar",
  2602  							Attributes: map[string]string{
  2603  								"ami":           "ami-abcd1234",
  2604  								"instance_type": "t2.micro",
  2605  							},
  2606  						},
  2607  					},
  2608  				},
  2609  			},
  2610  		},
  2611  	}
  2612  	ctx := testContext2(t, &ContextOpts{
  2613  		Module: m,
  2614  		Providers: map[string]ResourceProviderFactory{
  2615  			"aws": testProviderFuncFixed(p),
  2616  		},
  2617  		Variables: map[string]interface{}{
  2618  			"foo": "ami-1234abcd",
  2619  			"bar": "t2.small",
  2620  		},
  2621  		State: s,
  2622  	})
  2623  
  2624  	plan, err := ctx.Plan()
  2625  	if err != nil {
  2626  		t.Fatalf("err: %s", err)
  2627  	}
  2628  
  2629  	if len(plan.Diff.RootModule().Resources) > 0 {
  2630  		t.Fatalf("bad: %#v", plan.Diff.RootModule().Resources)
  2631  	}
  2632  
  2633  	actual := strings.TrimSpace(plan.String())
  2634  	expected := strings.TrimSpace(testTerraformPlanIgnoreChangesWildcardStr)
  2635  	if actual != expected {
  2636  		t.Fatalf("bad:\n%s\n\nexpected\n\n%s", actual, expected)
  2637  	}
  2638  }
  2639  
  2640  func TestContext2Plan_moduleMapLiteral(t *testing.T) {
  2641  	m := testModule(t, "plan-module-map-literal")
  2642  	p := testProvider("aws")
  2643  	p.ApplyFn = testApplyFn
  2644  	p.DiffFn = func(i *InstanceInfo, s *InstanceState, c *ResourceConfig) (*InstanceDiff, error) {
  2645  		// Here we verify that both the populated and empty map literals made it
  2646  		// through to the resource attributes
  2647  		val, _ := c.Get("tags")
  2648  		m, ok := val.(map[string]interface{})
  2649  		if !ok {
  2650  			t.Fatalf("Tags attr not map: %#v", val)
  2651  		}
  2652  		if m["foo"] != "bar" {
  2653  			t.Fatalf("Bad value in tags attr: %#v", m)
  2654  		}
  2655  		{
  2656  			val, _ := c.Get("meta")
  2657  			m, ok := val.(map[string]interface{})
  2658  			if !ok {
  2659  				t.Fatalf("Meta attr not map: %#v", val)
  2660  			}
  2661  			if len(m) != 0 {
  2662  				t.Fatalf("Meta attr not empty: %#v", val)
  2663  			}
  2664  		}
  2665  		return nil, nil
  2666  	}
  2667  	ctx := testContext2(t, &ContextOpts{
  2668  		Module: m,
  2669  		Providers: map[string]ResourceProviderFactory{
  2670  			"aws": testProviderFuncFixed(p),
  2671  		},
  2672  	})
  2673  
  2674  	if _, err := ctx.Plan(); err != nil {
  2675  		t.Fatalf("err: %s", err)
  2676  	}
  2677  }
  2678  
  2679  func TestContext2Plan_computedValueInMap(t *testing.T) {
  2680  	m := testModule(t, "plan-computed-value-in-map")
  2681  	p := testProvider("aws")
  2682  	p.DiffFn = func(info *InstanceInfo, state *InstanceState, c *ResourceConfig) (*InstanceDiff, error) {
  2683  		switch info.Type {
  2684  		case "aws_computed_source":
  2685  			return &InstanceDiff{
  2686  				Attributes: map[string]*ResourceAttrDiff{
  2687  					"computed_read_only": &ResourceAttrDiff{
  2688  						NewComputed: true,
  2689  					},
  2690  				},
  2691  			}, nil
  2692  		}
  2693  
  2694  		return testDiffFn(info, state, c)
  2695  	}
  2696  	ctx := testContext2(t, &ContextOpts{
  2697  		Module: m,
  2698  		Providers: map[string]ResourceProviderFactory{
  2699  			"aws": testProviderFuncFixed(p),
  2700  		},
  2701  	})
  2702  
  2703  	if _, err := ctx.Plan(); err != nil {
  2704  		t.Fatalf("err: %s", err)
  2705  	}
  2706  
  2707  	plan, err := ctx.Plan()
  2708  	if err != nil {
  2709  		t.Fatalf("err: %s", err)
  2710  	}
  2711  
  2712  	actual := strings.TrimSpace(plan.String())
  2713  	expected := strings.TrimSpace(testTerraformPlanComputedValueInMap)
  2714  	if actual != expected {
  2715  		t.Fatalf("bad:\n%s\n\nexpected\n\n%s", actual, expected)
  2716  	}
  2717  }
  2718  
  2719  func TestContext2Plan_moduleVariableFromSplat(t *testing.T) {
  2720  	m := testModule(t, "plan-module-variable-from-splat")
  2721  	p := testProvider("aws")
  2722  	p.DiffFn = testDiffFn
  2723  	ctx := testContext2(t, &ContextOpts{
  2724  		Module: m,
  2725  		Providers: map[string]ResourceProviderFactory{
  2726  			"aws": testProviderFuncFixed(p),
  2727  		},
  2728  	})
  2729  
  2730  	if _, err := ctx.Plan(); err != nil {
  2731  		t.Fatalf("err: %s", err)
  2732  	}
  2733  
  2734  	plan, err := ctx.Plan()
  2735  	if err != nil {
  2736  		t.Fatalf("err: %s", err)
  2737  	}
  2738  
  2739  	actual := strings.TrimSpace(plan.String())
  2740  	expected := strings.TrimSpace(testTerraformPlanModuleVariableFromSplat)
  2741  	if actual != expected {
  2742  		t.Fatalf("bad:\n%s\n\nexpected\n\n%s", actual, expected)
  2743  	}
  2744  }
  2745  
  2746  func TestContext2Plan_createBeforeDestroy_depends_datasource(t *testing.T) {
  2747  	m := testModule(t, "plan-cdb-depends-datasource")
  2748  	p := testProvider("aws")
  2749  	p.DiffFn = testDiffFn
  2750  	ctx := testContext2(t, &ContextOpts{
  2751  		Module: m,
  2752  		Providers: map[string]ResourceProviderFactory{
  2753  			"aws": testProviderFuncFixed(p),
  2754  		},
  2755  	})
  2756  
  2757  	plan, err := ctx.Plan()
  2758  	if err != nil {
  2759  		t.Fatalf("err: %s", err)
  2760  	}
  2761  
  2762  	if got := len(plan.Diff.Modules); got != 1 {
  2763  		t.Fatalf("got %d modules; want 1", got)
  2764  	}
  2765  
  2766  	moduleDiff := plan.Diff.Modules[0]
  2767  
  2768  	if _, ok := moduleDiff.Resources["aws_instance.foo.0"]; !ok {
  2769  		t.Fatalf("missing diff for aws_instance.foo.0")
  2770  	}
  2771  	if _, ok := moduleDiff.Resources["aws_instance.foo.1"]; !ok {
  2772  		t.Fatalf("missing diff for aws_instance.foo.1")
  2773  	}
  2774  	if _, ok := moduleDiff.Resources["data.aws_vpc.bar.0"]; !ok {
  2775  		t.Fatalf("missing diff for data.aws_vpc.bar.0")
  2776  	}
  2777  	if _, ok := moduleDiff.Resources["data.aws_vpc.bar.1"]; !ok {
  2778  		t.Fatalf("missing diff for data.aws_vpc.bar.1")
  2779  	}
  2780  }