github.com/pgray/terraform@v0.5.4-0.20170822184730-b6a464c5214d/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  		ProviderResolver: ResourceProviderResolverFixed(
    21  			map[string]ResourceProviderFactory{
    22  				"aws": testProviderFuncFixed(p),
    23  			},
    24  		),
    25  		ProviderSHA256s: map[string][]byte{
    26  			"aws": []byte("placeholder"),
    27  		},
    28  	})
    29  
    30  	plan, err := ctx.Plan()
    31  	if err != nil {
    32  		t.Fatalf("err: %s", err)
    33  	}
    34  
    35  	if len(plan.Diff.RootModule().Resources) < 2 {
    36  		t.Fatalf("bad: %#v", plan.Diff.RootModule().Resources)
    37  	}
    38  
    39  	if !reflect.DeepEqual(plan.ProviderSHA256s, ctx.providerSHA256s) {
    40  		t.Errorf("wrong ProviderSHA256s %#v; want %#v", plan.ProviderSHA256s, ctx.providerSHA256s)
    41  	}
    42  
    43  	actual := strings.TrimSpace(plan.String())
    44  	expected := strings.TrimSpace(testTerraformPlanStr)
    45  	if actual != expected {
    46  		t.Fatalf("bad:\n%s", actual)
    47  	}
    48  }
    49  
    50  func TestContext2Plan_createBefore_deposed(t *testing.T) {
    51  	m := testModule(t, "plan-cbd")
    52  	p := testProvider("aws")
    53  	p.DiffFn = testDiffFn
    54  
    55  	s := &State{
    56  		Modules: []*ModuleState{
    57  			&ModuleState{
    58  				Path: []string{"root"},
    59  				Resources: map[string]*ResourceState{
    60  					"aws_instance.foo": &ResourceState{
    61  						Type: "aws_instance",
    62  						Primary: &InstanceState{
    63  							ID: "baz",
    64  						},
    65  						Deposed: []*InstanceState{
    66  							&InstanceState{ID: "foo"},
    67  						},
    68  					},
    69  				},
    70  			},
    71  		},
    72  	}
    73  
    74  	ctx := testContext2(t, &ContextOpts{
    75  		Module: m,
    76  		ProviderResolver: ResourceProviderResolverFixed(
    77  			map[string]ResourceProviderFactory{
    78  				"aws": testProviderFuncFixed(p),
    79  			},
    80  		),
    81  		State: s,
    82  	})
    83  
    84  	plan, err := ctx.Plan()
    85  	if err != nil {
    86  		t.Fatalf("err: %s", err)
    87  	}
    88  
    89  	actual := strings.TrimSpace(plan.String())
    90  	expected := strings.TrimSpace(`
    91  DIFF:
    92  
    93  DESTROY: aws_instance.foo (deposed only)
    94  
    95  STATE:
    96  
    97  aws_instance.foo: (1 deposed)
    98    ID = baz
    99    Deposed ID 1 = foo
   100  		`)
   101  	if actual != expected {
   102  		t.Fatalf("expected:\n%s, got:\n%s", expected, actual)
   103  	}
   104  }
   105  
   106  func TestContext2Plan_createBefore_maintainRoot(t *testing.T) {
   107  	m := testModule(t, "plan-cbd-maintain-root")
   108  	p := testProvider("aws")
   109  	p.DiffFn = testDiffFn
   110  	ctx := testContext2(t, &ContextOpts{
   111  		Module: m,
   112  		ProviderResolver: ResourceProviderResolverFixed(
   113  			map[string]ResourceProviderFactory{
   114  				"aws": testProviderFuncFixed(p),
   115  			},
   116  		),
   117  		Variables: map[string]interface{}{
   118  			"in": "a,b,c",
   119  		},
   120  	})
   121  
   122  	plan, err := ctx.Plan()
   123  	if err != nil {
   124  		t.Fatalf("err: %s", err)
   125  	}
   126  
   127  	actual := strings.TrimSpace(plan.String())
   128  	expected := strings.TrimSpace(`
   129  DIFF:
   130  
   131  CREATE: aws_instance.bar.0
   132  CREATE: aws_instance.bar.1
   133  CREATE: aws_instance.foo.0
   134  CREATE: aws_instance.foo.1
   135  
   136  STATE:
   137  
   138  <no state>
   139  		`)
   140  	if actual != expected {
   141  		t.Fatalf("expected:\n%s, got:\n%s", expected, actual)
   142  	}
   143  }
   144  
   145  func TestContext2Plan_emptyDiff(t *testing.T) {
   146  	m := testModule(t, "plan-empty")
   147  	p := testProvider("aws")
   148  	p.DiffFn = func(
   149  		info *InstanceInfo,
   150  		s *InstanceState,
   151  		c *ResourceConfig) (*InstanceDiff, error) {
   152  		return nil, nil
   153  	}
   154  
   155  	ctx := testContext2(t, &ContextOpts{
   156  		Module: m,
   157  		ProviderResolver: ResourceProviderResolverFixed(
   158  			map[string]ResourceProviderFactory{
   159  				"aws": testProviderFuncFixed(p),
   160  			},
   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(testTerraformPlanEmptyStr)
   171  	if actual != expected {
   172  		t.Fatalf("bad:\n%s", actual)
   173  	}
   174  }
   175  
   176  func TestContext2Plan_escapedVar(t *testing.T) {
   177  	m := testModule(t, "plan-escaped-var")
   178  	p := testProvider("aws")
   179  	p.DiffFn = testDiffFn
   180  	ctx := testContext2(t, &ContextOpts{
   181  		Module: m,
   182  		ProviderResolver: ResourceProviderResolverFixed(
   183  			map[string]ResourceProviderFactory{
   184  				"aws": testProviderFuncFixed(p),
   185  			},
   186  		),
   187  	})
   188  
   189  	plan, err := ctx.Plan()
   190  	if err != nil {
   191  		t.Fatalf("err: %s", err)
   192  	}
   193  
   194  	actual := strings.TrimSpace(plan.String())
   195  	expected := strings.TrimSpace(testTerraformPlanEscapedVarStr)
   196  	if actual != expected {
   197  		t.Fatalf("bad:\n%s", actual)
   198  	}
   199  }
   200  
   201  func TestContext2Plan_minimal(t *testing.T) {
   202  	m := testModule(t, "plan-empty")
   203  	p := testProvider("aws")
   204  	p.DiffFn = testDiffFn
   205  	ctx := testContext2(t, &ContextOpts{
   206  		Module: m,
   207  		ProviderResolver: ResourceProviderResolverFixed(
   208  			map[string]ResourceProviderFactory{
   209  				"aws": testProviderFuncFixed(p),
   210  			},
   211  		),
   212  	})
   213  
   214  	plan, err := ctx.Plan()
   215  	if err != nil {
   216  		t.Fatalf("err: %s", err)
   217  	}
   218  
   219  	actual := strings.TrimSpace(plan.String())
   220  	expected := strings.TrimSpace(testTerraformPlanEmptyStr)
   221  	if actual != expected {
   222  		t.Fatalf("bad:\n%s", actual)
   223  	}
   224  }
   225  
   226  func TestContext2Plan_modules(t *testing.T) {
   227  	m := testModule(t, "plan-modules")
   228  	p := testProvider("aws")
   229  	p.DiffFn = testDiffFn
   230  	ctx := testContext2(t, &ContextOpts{
   231  		Module: m,
   232  		ProviderResolver: ResourceProviderResolverFixed(
   233  			map[string]ResourceProviderFactory{
   234  				"aws": testProviderFuncFixed(p),
   235  			},
   236  		),
   237  	})
   238  
   239  	plan, err := ctx.Plan()
   240  	if err != nil {
   241  		t.Fatalf("err: %s", err)
   242  	}
   243  
   244  	actual := strings.TrimSpace(plan.String())
   245  	expected := strings.TrimSpace(testTerraformPlanModulesStr)
   246  	if actual != expected {
   247  		t.Fatalf("bad:\n%s", actual)
   248  	}
   249  }
   250  
   251  // GH-1475
   252  func TestContext2Plan_moduleCycle(t *testing.T) {
   253  	m := testModule(t, "plan-module-cycle")
   254  	p := testProvider("aws")
   255  	p.DiffFn = testDiffFn
   256  	ctx := testContext2(t, &ContextOpts{
   257  		Module: m,
   258  		ProviderResolver: ResourceProviderResolverFixed(
   259  			map[string]ResourceProviderFactory{
   260  				"aws": testProviderFuncFixed(p),
   261  			},
   262  		),
   263  	})
   264  
   265  	plan, err := ctx.Plan()
   266  	if err != nil {
   267  		t.Fatalf("err: %s", err)
   268  	}
   269  
   270  	actual := strings.TrimSpace(plan.String())
   271  	expected := strings.TrimSpace(testTerraformPlanModuleCycleStr)
   272  	if actual != expected {
   273  		t.Fatalf("bad:\n%s", actual)
   274  	}
   275  }
   276  
   277  func TestContext2Plan_moduleDeadlock(t *testing.T) {
   278  	testCheckDeadlock(t, func() {
   279  		m := testModule(t, "plan-module-deadlock")
   280  		p := testProvider("aws")
   281  		p.DiffFn = testDiffFn
   282  
   283  		ctx := testContext2(t, &ContextOpts{
   284  			Module: m,
   285  			ProviderResolver: ResourceProviderResolverFixed(
   286  				map[string]ResourceProviderFactory{
   287  					"aws": testProviderFuncFixed(p),
   288  				},
   289  			),
   290  		})
   291  
   292  		plan, err := ctx.Plan()
   293  		if err != nil {
   294  			t.Fatalf("err: %s", err)
   295  		}
   296  
   297  		actual := strings.TrimSpace(plan.String())
   298  		expected := strings.TrimSpace(`
   299  DIFF:
   300  
   301  module.child:
   302    CREATE: aws_instance.foo.0
   303    CREATE: aws_instance.foo.1
   304    CREATE: aws_instance.foo.2
   305  
   306  STATE:
   307  
   308  <no state>
   309  		`)
   310  		if actual != expected {
   311  			t.Fatalf("expected:\n%sgot:\n%s", expected, actual)
   312  		}
   313  	})
   314  }
   315  
   316  func TestContext2Plan_moduleInput(t *testing.T) {
   317  	m := testModule(t, "plan-module-input")
   318  	p := testProvider("aws")
   319  	p.DiffFn = testDiffFn
   320  	ctx := testContext2(t, &ContextOpts{
   321  		Module: m,
   322  		ProviderResolver: ResourceProviderResolverFixed(
   323  			map[string]ResourceProviderFactory{
   324  				"aws": testProviderFuncFixed(p),
   325  			},
   326  		),
   327  	})
   328  
   329  	plan, err := ctx.Plan()
   330  	if err != nil {
   331  		t.Fatalf("err: %s", err)
   332  	}
   333  
   334  	actual := strings.TrimSpace(plan.String())
   335  	expected := strings.TrimSpace(testTerraformPlanModuleInputStr)
   336  	if actual != expected {
   337  		t.Fatalf("bad:\n%s", actual)
   338  	}
   339  }
   340  
   341  func TestContext2Plan_moduleInputComputed(t *testing.T) {
   342  	m := testModule(t, "plan-module-input-computed")
   343  	p := testProvider("aws")
   344  	p.DiffFn = testDiffFn
   345  	ctx := testContext2(t, &ContextOpts{
   346  		Module: m,
   347  		ProviderResolver: ResourceProviderResolverFixed(
   348  			map[string]ResourceProviderFactory{
   349  				"aws": testProviderFuncFixed(p),
   350  			},
   351  		),
   352  	})
   353  
   354  	plan, err := ctx.Plan()
   355  	if err != nil {
   356  		t.Fatalf("err: %s", err)
   357  	}
   358  
   359  	actual := strings.TrimSpace(plan.String())
   360  	expected := strings.TrimSpace(testTerraformPlanModuleInputComputedStr)
   361  	if actual != expected {
   362  		t.Fatalf("bad:\n%s", actual)
   363  	}
   364  }
   365  
   366  func TestContext2Plan_moduleInputFromVar(t *testing.T) {
   367  	m := testModule(t, "plan-module-input-var")
   368  	p := testProvider("aws")
   369  	p.DiffFn = testDiffFn
   370  	ctx := testContext2(t, &ContextOpts{
   371  		Module: m,
   372  		ProviderResolver: ResourceProviderResolverFixed(
   373  			map[string]ResourceProviderFactory{
   374  				"aws": testProviderFuncFixed(p),
   375  			},
   376  		),
   377  		Variables: map[string]interface{}{
   378  			"foo": "52",
   379  		},
   380  	})
   381  
   382  	plan, err := ctx.Plan()
   383  	if err != nil {
   384  		t.Fatalf("err: %s", err)
   385  	}
   386  
   387  	actual := strings.TrimSpace(plan.String())
   388  	expected := strings.TrimSpace(testTerraformPlanModuleInputVarStr)
   389  	if actual != expected {
   390  		t.Fatalf("bad:\n%s", actual)
   391  	}
   392  }
   393  
   394  func TestContext2Plan_moduleMultiVar(t *testing.T) {
   395  	m := testModule(t, "plan-module-multi-var")
   396  	p := testProvider("aws")
   397  	p.DiffFn = testDiffFn
   398  	ctx := testContext2(t, &ContextOpts{
   399  		Module: m,
   400  		ProviderResolver: ResourceProviderResolverFixed(
   401  			map[string]ResourceProviderFactory{
   402  				"aws": testProviderFuncFixed(p),
   403  			},
   404  		),
   405  	})
   406  
   407  	plan, err := ctx.Plan()
   408  	if err != nil {
   409  		t.Fatalf("err: %s", err)
   410  	}
   411  
   412  	actual := strings.TrimSpace(plan.String())
   413  	expected := strings.TrimSpace(testTerraformPlanModuleMultiVarStr)
   414  	if actual != expected {
   415  		t.Fatalf("bad:\n%s", actual)
   416  	}
   417  }
   418  
   419  func TestContext2Plan_moduleOrphans(t *testing.T) {
   420  	m := testModule(t, "plan-modules-remove")
   421  	p := testProvider("aws")
   422  	p.DiffFn = testDiffFn
   423  	s := &State{
   424  		Modules: []*ModuleState{
   425  			&ModuleState{
   426  				Path: []string{"root", "child"},
   427  				Resources: map[string]*ResourceState{
   428  					"aws_instance.foo": &ResourceState{
   429  						Type: "aws_instance",
   430  						Primary: &InstanceState{
   431  							ID: "baz",
   432  						},
   433  					},
   434  				},
   435  			},
   436  		},
   437  	}
   438  	ctx := testContext2(t, &ContextOpts{
   439  		Module: m,
   440  		ProviderResolver: ResourceProviderResolverFixed(
   441  			map[string]ResourceProviderFactory{
   442  				"aws": testProviderFuncFixed(p),
   443  			},
   444  		),
   445  		State: s,
   446  	})
   447  
   448  	plan, err := ctx.Plan()
   449  	if err != nil {
   450  		t.Fatalf("err: %s", err)
   451  	}
   452  
   453  	actual := strings.TrimSpace(plan.String())
   454  	expected := strings.TrimSpace(testTerraformPlanModuleOrphansStr)
   455  	if actual != expected {
   456  		t.Fatalf("bad:\n%s", actual)
   457  	}
   458  }
   459  
   460  // https://github.com/hashicorp/terraform/issues/3114
   461  func TestContext2Plan_moduleOrphansWithProvisioner(t *testing.T) {
   462  	m := testModule(t, "plan-modules-remove-provisioners")
   463  	p := testProvider("aws")
   464  	pr := testProvisioner()
   465  	p.DiffFn = testDiffFn
   466  	s := &State{
   467  		Modules: []*ModuleState{
   468  			&ModuleState{
   469  				Path: []string{"root"},
   470  				Resources: map[string]*ResourceState{
   471  					"aws_instance.top": &ResourceState{
   472  						Type: "aws_instance",
   473  						Primary: &InstanceState{
   474  							ID: "top",
   475  						},
   476  					},
   477  				},
   478  			},
   479  			&ModuleState{
   480  				Path: []string{"root", "parent", "childone"},
   481  				Resources: map[string]*ResourceState{
   482  					"aws_instance.foo": &ResourceState{
   483  						Type: "aws_instance",
   484  						Primary: &InstanceState{
   485  							ID: "baz",
   486  						},
   487  					},
   488  				},
   489  			},
   490  			&ModuleState{
   491  				Path: []string{"root", "parent", "childtwo"},
   492  				Resources: map[string]*ResourceState{
   493  					"aws_instance.foo": &ResourceState{
   494  						Type: "aws_instance",
   495  						Primary: &InstanceState{
   496  							ID: "baz",
   497  						},
   498  					},
   499  				},
   500  			},
   501  		},
   502  	}
   503  	ctx := testContext2(t, &ContextOpts{
   504  		Module: m,
   505  		ProviderResolver: ResourceProviderResolverFixed(
   506  			map[string]ResourceProviderFactory{
   507  				"aws": testProviderFuncFixed(p),
   508  			},
   509  		),
   510  		Provisioners: map[string]ResourceProvisionerFactory{
   511  			"shell": testProvisionerFuncFixed(pr),
   512  		},
   513  		State: s,
   514  	})
   515  
   516  	plan, err := ctx.Plan()
   517  	if err != nil {
   518  		t.Fatalf("err: %s", err)
   519  	}
   520  
   521  	actual := strings.TrimSpace(plan.String())
   522  	expected := strings.TrimSpace(`
   523  DIFF:
   524  
   525  module.parent.childone:
   526    DESTROY: aws_instance.foo
   527  module.parent.childtwo:
   528    DESTROY: aws_instance.foo
   529  
   530  STATE:
   531  
   532  aws_instance.top:
   533    ID = top
   534  
   535  module.parent.childone:
   536    aws_instance.foo:
   537      ID = baz
   538  module.parent.childtwo:
   539    aws_instance.foo:
   540      ID = baz
   541  	`)
   542  	if actual != expected {
   543  		t.Fatalf("bad:\n%s", actual)
   544  	}
   545  }
   546  
   547  func TestContext2Plan_moduleProviderInherit(t *testing.T) {
   548  	var l sync.Mutex
   549  	var calls []string
   550  
   551  	m := testModule(t, "plan-module-provider-inherit")
   552  	ctx := testContext2(t, &ContextOpts{
   553  		Module: m,
   554  		ProviderResolver: ResourceProviderResolverFixed(
   555  			map[string]ResourceProviderFactory{
   556  				"aws": func() (ResourceProvider, error) {
   557  					l.Lock()
   558  					defer l.Unlock()
   559  
   560  					p := testProvider("aws")
   561  					p.ConfigureFn = func(c *ResourceConfig) error {
   562  						if v, ok := c.Get("from"); !ok || v.(string) != "root" {
   563  							return fmt.Errorf("bad")
   564  						}
   565  
   566  						return nil
   567  					}
   568  					p.DiffFn = func(
   569  						info *InstanceInfo,
   570  						state *InstanceState,
   571  						c *ResourceConfig) (*InstanceDiff, error) {
   572  						v, _ := c.Get("from")
   573  
   574  						l.Lock()
   575  						defer l.Unlock()
   576  						calls = append(calls, v.(string))
   577  						return testDiffFn(info, state, c)
   578  					}
   579  					return p, nil
   580  				},
   581  			},
   582  		),
   583  	})
   584  
   585  	_, err := ctx.Plan()
   586  	if err != nil {
   587  		t.Fatalf("err: %s", err)
   588  	}
   589  
   590  	actual := calls
   591  	sort.Strings(actual)
   592  	expected := []string{"child", "root"}
   593  	if !reflect.DeepEqual(actual, expected) {
   594  		t.Fatalf("bad: %#v", actual)
   595  	}
   596  }
   597  
   598  // This tests (for GH-11282) that deeply nested modules properly inherit
   599  // configuration.
   600  func TestContext2Plan_moduleProviderInheritDeep(t *testing.T) {
   601  	var l sync.Mutex
   602  
   603  	m := testModule(t, "plan-module-provider-inherit-deep")
   604  	ctx := testContext2(t, &ContextOpts{
   605  		Module: m,
   606  		ProviderResolver: ResourceProviderResolverFixed(
   607  			map[string]ResourceProviderFactory{
   608  				"aws": func() (ResourceProvider, error) {
   609  					l.Lock()
   610  					defer l.Unlock()
   611  
   612  					var from string
   613  					p := testProvider("aws")
   614  					p.ConfigureFn = func(c *ResourceConfig) error {
   615  						v, ok := c.Get("from")
   616  						if !ok || v.(string) != "root" {
   617  							return fmt.Errorf("bad")
   618  						}
   619  
   620  						from = v.(string)
   621  						return nil
   622  					}
   623  
   624  					p.DiffFn = func(
   625  						info *InstanceInfo,
   626  						state *InstanceState,
   627  						c *ResourceConfig) (*InstanceDiff, error) {
   628  						if from != "root" {
   629  							return nil, fmt.Errorf("bad resource")
   630  						}
   631  
   632  						return testDiffFn(info, state, c)
   633  					}
   634  					return p, nil
   635  				},
   636  			},
   637  		),
   638  	})
   639  
   640  	_, err := ctx.Plan()
   641  	if err != nil {
   642  		t.Fatalf("err: %s", err)
   643  	}
   644  }
   645  
   646  func TestContext2Plan_moduleProviderDefaults(t *testing.T) {
   647  	var l sync.Mutex
   648  	var calls []string
   649  	toCount := 0
   650  
   651  	m := testModule(t, "plan-module-provider-defaults")
   652  	ctx := testContext2(t, &ContextOpts{
   653  		Module: m,
   654  		ProviderResolver: ResourceProviderResolverFixed(
   655  			map[string]ResourceProviderFactory{
   656  				"aws": func() (ResourceProvider, error) {
   657  					l.Lock()
   658  					defer l.Unlock()
   659  
   660  					p := testProvider("aws")
   661  					p.ConfigureFn = func(c *ResourceConfig) error {
   662  						if v, ok := c.Get("from"); !ok || v.(string) != "root" {
   663  							return fmt.Errorf("bad")
   664  						}
   665  						if v, ok := c.Get("to"); ok && v.(string) == "child" {
   666  							toCount++
   667  						}
   668  
   669  						return nil
   670  					}
   671  					p.DiffFn = func(
   672  						info *InstanceInfo,
   673  						state *InstanceState,
   674  						c *ResourceConfig) (*InstanceDiff, error) {
   675  						v, _ := c.Get("from")
   676  
   677  						l.Lock()
   678  						defer l.Unlock()
   679  						calls = append(calls, v.(string))
   680  						return testDiffFn(info, state, c)
   681  					}
   682  					return p, nil
   683  				},
   684  			},
   685  		),
   686  	})
   687  
   688  	_, err := ctx.Plan()
   689  	if err != nil {
   690  		t.Fatalf("err: %s", err)
   691  	}
   692  
   693  	if toCount != 1 {
   694  		t.Fatalf(
   695  			"provider in child didn't set proper config\n\n"+
   696  				"toCount: %d", toCount)
   697  	}
   698  
   699  	actual := calls
   700  	sort.Strings(actual)
   701  	expected := []string{"child", "root"}
   702  	if !reflect.DeepEqual(actual, expected) {
   703  		t.Fatalf("bad: %#v", actual)
   704  	}
   705  }
   706  
   707  func TestContext2Plan_moduleProviderDefaultsVar(t *testing.T) {
   708  	var l sync.Mutex
   709  	var calls []string
   710  
   711  	m := testModule(t, "plan-module-provider-defaults-var")
   712  	ctx := testContext2(t, &ContextOpts{
   713  		Module: m,
   714  		ProviderResolver: ResourceProviderResolverFixed(
   715  			map[string]ResourceProviderFactory{
   716  				"aws": func() (ResourceProvider, error) {
   717  					l.Lock()
   718  					defer l.Unlock()
   719  
   720  					p := testProvider("aws")
   721  					p.ConfigureFn = func(c *ResourceConfig) error {
   722  						var buf bytes.Buffer
   723  						if v, ok := c.Get("from"); ok {
   724  							buf.WriteString(v.(string) + "\n")
   725  						}
   726  						if v, ok := c.Get("to"); ok {
   727  							buf.WriteString(v.(string) + "\n")
   728  						}
   729  
   730  						l.Lock()
   731  						defer l.Unlock()
   732  						calls = append(calls, buf.String())
   733  						return nil
   734  					}
   735  					p.DiffFn = testDiffFn
   736  					return p, nil
   737  				},
   738  			},
   739  		),
   740  		Variables: map[string]interface{}{
   741  			"foo": "root",
   742  		},
   743  	})
   744  
   745  	_, err := ctx.Plan()
   746  	if err != nil {
   747  		t.Fatalf("err: %s", err)
   748  	}
   749  
   750  	expected := []string{
   751  		"root\n",
   752  		"root\nchild\n",
   753  	}
   754  	if !reflect.DeepEqual(calls, expected) {
   755  		t.Fatalf("BAD: %#v", calls)
   756  	}
   757  }
   758  
   759  func TestContext2Plan_moduleProviderVar(t *testing.T) {
   760  	m := testModule(t, "plan-module-provider-var")
   761  	p := testProvider("aws")
   762  	p.DiffFn = testDiffFn
   763  	ctx := testContext2(t, &ContextOpts{
   764  		Module: m,
   765  		ProviderResolver: ResourceProviderResolverFixed(
   766  			map[string]ResourceProviderFactory{
   767  				"aws": testProviderFuncFixed(p),
   768  			},
   769  		),
   770  	})
   771  
   772  	plan, err := ctx.Plan()
   773  	if err != nil {
   774  		t.Fatalf("err: %s", err)
   775  	}
   776  
   777  	actual := strings.TrimSpace(plan.String())
   778  	expected := strings.TrimSpace(testTerraformPlanModuleProviderVarStr)
   779  	if actual != expected {
   780  		t.Fatalf("bad:\n%s", actual)
   781  	}
   782  }
   783  
   784  func TestContext2Plan_moduleVar(t *testing.T) {
   785  	m := testModule(t, "plan-module-var")
   786  	p := testProvider("aws")
   787  	p.DiffFn = testDiffFn
   788  	ctx := testContext2(t, &ContextOpts{
   789  		Module: m,
   790  		ProviderResolver: ResourceProviderResolverFixed(
   791  			map[string]ResourceProviderFactory{
   792  				"aws": testProviderFuncFixed(p),
   793  			},
   794  		),
   795  	})
   796  
   797  	plan, err := ctx.Plan()
   798  	if err != nil {
   799  		t.Fatalf("err: %s", err)
   800  	}
   801  
   802  	actual := strings.TrimSpace(plan.String())
   803  	expected := strings.TrimSpace(testTerraformPlanModuleVarStr)
   804  	if actual != expected {
   805  		t.Fatalf("bad:\n%s", actual)
   806  	}
   807  }
   808  
   809  func TestContext2Plan_moduleVarWrongTypeBasic(t *testing.T) {
   810  	m := testModule(t, "plan-module-wrong-var-type")
   811  	p := testProvider("aws")
   812  	p.DiffFn = testDiffFn
   813  	ctx := testContext2(t, &ContextOpts{
   814  		Module: m,
   815  		ProviderResolver: ResourceProviderResolverFixed(
   816  			map[string]ResourceProviderFactory{
   817  				"aws": testProviderFuncFixed(p),
   818  			},
   819  		),
   820  	})
   821  
   822  	_, err := ctx.Plan()
   823  	if err == nil {
   824  		t.Fatalf("should error")
   825  	}
   826  }
   827  
   828  func TestContext2Plan_moduleVarWrongTypeNested(t *testing.T) {
   829  	m := testModule(t, "plan-module-wrong-var-type-nested")
   830  	p := testProvider("null")
   831  	p.DiffFn = testDiffFn
   832  	ctx := testContext2(t, &ContextOpts{
   833  		Module: m,
   834  		ProviderResolver: ResourceProviderResolverFixed(
   835  			map[string]ResourceProviderFactory{
   836  				"null": testProviderFuncFixed(p),
   837  			},
   838  		),
   839  	})
   840  
   841  	_, err := ctx.Plan()
   842  	if err == nil {
   843  		t.Fatalf("should error")
   844  	}
   845  }
   846  
   847  func TestContext2Plan_moduleVarWithDefaultValue(t *testing.T) {
   848  	m := testModule(t, "plan-module-var-with-default-value")
   849  	p := testProvider("null")
   850  	p.DiffFn = testDiffFn
   851  	ctx := testContext2(t, &ContextOpts{
   852  		Module: m,
   853  		ProviderResolver: ResourceProviderResolverFixed(
   854  			map[string]ResourceProviderFactory{
   855  				"null": testProviderFuncFixed(p),
   856  			},
   857  		),
   858  	})
   859  
   860  	_, err := ctx.Plan()
   861  	if err != nil {
   862  		t.Fatalf("bad: %s", err)
   863  	}
   864  }
   865  
   866  func TestContext2Plan_moduleVarComputed(t *testing.T) {
   867  	m := testModule(t, "plan-module-var-computed")
   868  	p := testProvider("aws")
   869  	p.DiffFn = testDiffFn
   870  	ctx := testContext2(t, &ContextOpts{
   871  		Module: m,
   872  		ProviderResolver: ResourceProviderResolverFixed(
   873  			map[string]ResourceProviderFactory{
   874  				"aws": testProviderFuncFixed(p),
   875  			},
   876  		),
   877  	})
   878  
   879  	plan, err := ctx.Plan()
   880  	if err != nil {
   881  		t.Fatalf("err: %s", err)
   882  	}
   883  
   884  	actual := strings.TrimSpace(plan.String())
   885  	expected := strings.TrimSpace(testTerraformPlanModuleVarComputedStr)
   886  	if actual != expected {
   887  		t.Fatalf("bad:\n%s", actual)
   888  	}
   889  }
   890  
   891  func TestContext2Plan_nil(t *testing.T) {
   892  	m := testModule(t, "plan-nil")
   893  	p := testProvider("aws")
   894  	p.DiffFn = testDiffFn
   895  	ctx := testContext2(t, &ContextOpts{
   896  		Module: m,
   897  		ProviderResolver: ResourceProviderResolverFixed(
   898  			map[string]ResourceProviderFactory{
   899  				"aws": testProviderFuncFixed(p),
   900  			},
   901  		),
   902  		State: &State{
   903  			Modules: []*ModuleState{
   904  				&ModuleState{
   905  					Path: rootModulePath,
   906  					Resources: map[string]*ResourceState{
   907  						"aws_instance.foo": &ResourceState{
   908  							Type: "aws_instance",
   909  							Primary: &InstanceState{
   910  								ID: "bar",
   911  							},
   912  						},
   913  					},
   914  				},
   915  			},
   916  		},
   917  	})
   918  
   919  	plan, err := ctx.Plan()
   920  	if err != nil {
   921  		t.Fatalf("err: %s", err)
   922  	}
   923  	if len(plan.Diff.RootModule().Resources) != 0 {
   924  		t.Fatalf("bad: %#v", plan.Diff.RootModule().Resources)
   925  	}
   926  }
   927  
   928  func TestContext2Plan_preventDestroy_bad(t *testing.T) {
   929  	m := testModule(t, "plan-prevent-destroy-bad")
   930  	p := testProvider("aws")
   931  	p.DiffFn = testDiffFn
   932  	ctx := testContext2(t, &ContextOpts{
   933  		Module: m,
   934  		ProviderResolver: ResourceProviderResolverFixed(
   935  			map[string]ResourceProviderFactory{
   936  				"aws": testProviderFuncFixed(p),
   937  			},
   938  		),
   939  		State: &State{
   940  			Modules: []*ModuleState{
   941  				&ModuleState{
   942  					Path: rootModulePath,
   943  					Resources: map[string]*ResourceState{
   944  						"aws_instance.foo": &ResourceState{
   945  							Type: "aws_instance",
   946  							Primary: &InstanceState{
   947  								ID: "i-abc123",
   948  							},
   949  						},
   950  					},
   951  				},
   952  			},
   953  		},
   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_preventDestroy_good(t *testing.T) {
   966  	m := testModule(t, "plan-prevent-destroy-good")
   967  	p := testProvider("aws")
   968  	p.DiffFn = testDiffFn
   969  	ctx := testContext2(t, &ContextOpts{
   970  		Module: m,
   971  		ProviderResolver: ResourceProviderResolverFixed(
   972  			map[string]ResourceProviderFactory{
   973  				"aws": testProviderFuncFixed(p),
   974  			},
   975  		),
   976  		State: &State{
   977  			Modules: []*ModuleState{
   978  				&ModuleState{
   979  					Path: rootModulePath,
   980  					Resources: map[string]*ResourceState{
   981  						"aws_instance.foo": &ResourceState{
   982  							Type: "aws_instance",
   983  							Primary: &InstanceState{
   984  								ID: "i-abc123",
   985  							},
   986  						},
   987  					},
   988  				},
   989  			},
   990  		},
   991  	})
   992  
   993  	plan, err := ctx.Plan()
   994  	if err != nil {
   995  		t.Fatalf("err: %s", err)
   996  	}
   997  	if !plan.Diff.Empty() {
   998  		t.Fatalf("Expected empty plan, got %s", plan.String())
   999  	}
  1000  }
  1001  
  1002  func TestContext2Plan_preventDestroy_countBad(t *testing.T) {
  1003  	m := testModule(t, "plan-prevent-destroy-count-bad")
  1004  	p := testProvider("aws")
  1005  	p.DiffFn = testDiffFn
  1006  	ctx := testContext2(t, &ContextOpts{
  1007  		Module: m,
  1008  		ProviderResolver: ResourceProviderResolverFixed(
  1009  			map[string]ResourceProviderFactory{
  1010  				"aws": testProviderFuncFixed(p),
  1011  			},
  1012  		),
  1013  		State: &State{
  1014  			Modules: []*ModuleState{
  1015  				&ModuleState{
  1016  					Path: rootModulePath,
  1017  					Resources: map[string]*ResourceState{
  1018  						"aws_instance.foo.0": &ResourceState{
  1019  							Type: "aws_instance",
  1020  							Primary: &InstanceState{
  1021  								ID: "i-abc123",
  1022  							},
  1023  						},
  1024  						"aws_instance.foo.1": &ResourceState{
  1025  							Type: "aws_instance",
  1026  							Primary: &InstanceState{
  1027  								ID: "i-abc345",
  1028  							},
  1029  						},
  1030  					},
  1031  				},
  1032  			},
  1033  		},
  1034  	})
  1035  
  1036  	plan, err := ctx.Plan()
  1037  
  1038  	expectedErr := "aws_instance.foo.1: the plan would destroy"
  1039  	if !strings.Contains(fmt.Sprintf("%s", err), expectedErr) {
  1040  		t.Fatalf("expected err would contain %q\nerr: %s\nplan: %s",
  1041  			expectedErr, err, plan)
  1042  	}
  1043  }
  1044  
  1045  func TestContext2Plan_preventDestroy_countGood(t *testing.T) {
  1046  	m := testModule(t, "plan-prevent-destroy-count-good")
  1047  	p := testProvider("aws")
  1048  	p.DiffFn = testDiffFn
  1049  	ctx := testContext2(t, &ContextOpts{
  1050  		Module: m,
  1051  		ProviderResolver: ResourceProviderResolverFixed(
  1052  			map[string]ResourceProviderFactory{
  1053  				"aws": testProviderFuncFixed(p),
  1054  			},
  1055  		),
  1056  		State: &State{
  1057  			Modules: []*ModuleState{
  1058  				&ModuleState{
  1059  					Path: rootModulePath,
  1060  					Resources: map[string]*ResourceState{
  1061  						"aws_instance.foo.0": &ResourceState{
  1062  							Type: "aws_instance",
  1063  							Primary: &InstanceState{
  1064  								ID: "i-abc123",
  1065  							},
  1066  						},
  1067  						"aws_instance.foo.1": &ResourceState{
  1068  							Type: "aws_instance",
  1069  							Primary: &InstanceState{
  1070  								ID: "i-abc345",
  1071  							},
  1072  						},
  1073  					},
  1074  				},
  1075  			},
  1076  		},
  1077  	})
  1078  
  1079  	plan, err := ctx.Plan()
  1080  	if err != nil {
  1081  		t.Fatalf("err: %s", err)
  1082  	}
  1083  	if plan.Diff.Empty() {
  1084  		t.Fatalf("Expected non-empty plan, got %s", plan.String())
  1085  	}
  1086  }
  1087  
  1088  func TestContext2Plan_preventDestroy_countGoodNoChange(t *testing.T) {
  1089  	m := testModule(t, "plan-prevent-destroy-count-good")
  1090  	p := testProvider("aws")
  1091  	p.DiffFn = testDiffFn
  1092  	ctx := testContext2(t, &ContextOpts{
  1093  		Module: m,
  1094  		ProviderResolver: ResourceProviderResolverFixed(
  1095  			map[string]ResourceProviderFactory{
  1096  				"aws": testProviderFuncFixed(p),
  1097  			},
  1098  		),
  1099  		State: &State{
  1100  			Modules: []*ModuleState{
  1101  				&ModuleState{
  1102  					Path: rootModulePath,
  1103  					Resources: map[string]*ResourceState{
  1104  						"aws_instance.foo.0": &ResourceState{
  1105  							Type: "aws_instance",
  1106  							Primary: &InstanceState{
  1107  								ID: "i-abc123",
  1108  								Attributes: map[string]string{
  1109  									"current": "0",
  1110  									"type":    "aws_instance",
  1111  								},
  1112  							},
  1113  						},
  1114  					},
  1115  				},
  1116  			},
  1117  		},
  1118  	})
  1119  
  1120  	plan, err := ctx.Plan()
  1121  	if err != nil {
  1122  		t.Fatalf("err: %s", err)
  1123  	}
  1124  	if !plan.Diff.Empty() {
  1125  		t.Fatalf("Expected empty plan, got %s", plan.String())
  1126  	}
  1127  }
  1128  
  1129  func TestContext2Plan_preventDestroy_destroyPlan(t *testing.T) {
  1130  	m := testModule(t, "plan-prevent-destroy-good")
  1131  	p := testProvider("aws")
  1132  	p.DiffFn = testDiffFn
  1133  	ctx := testContext2(t, &ContextOpts{
  1134  		Module: m,
  1135  		ProviderResolver: ResourceProviderResolverFixed(
  1136  			map[string]ResourceProviderFactory{
  1137  				"aws": testProviderFuncFixed(p),
  1138  			},
  1139  		),
  1140  		State: &State{
  1141  			Modules: []*ModuleState{
  1142  				&ModuleState{
  1143  					Path: rootModulePath,
  1144  					Resources: map[string]*ResourceState{
  1145  						"aws_instance.foo": &ResourceState{
  1146  							Type: "aws_instance",
  1147  							Primary: &InstanceState{
  1148  								ID: "i-abc123",
  1149  							},
  1150  						},
  1151  					},
  1152  				},
  1153  			},
  1154  		},
  1155  		Destroy: true,
  1156  	})
  1157  
  1158  	plan, err := ctx.Plan()
  1159  
  1160  	expectedErr := "aws_instance.foo: the plan would destroy"
  1161  	if !strings.Contains(fmt.Sprintf("%s", err), expectedErr) {
  1162  		t.Fatalf("expected err would contain %q\nerr: %s\nplan: %s",
  1163  			expectedErr, err, plan)
  1164  	}
  1165  }
  1166  
  1167  func TestContext2Plan_provisionerCycle(t *testing.T) {
  1168  	m := testModule(t, "plan-provisioner-cycle")
  1169  	p := testProvider("aws")
  1170  	p.DiffFn = testDiffFn
  1171  	pr := testProvisioner()
  1172  	ctx := testContext2(t, &ContextOpts{
  1173  		Module: m,
  1174  		ProviderResolver: ResourceProviderResolverFixed(
  1175  			map[string]ResourceProviderFactory{
  1176  				"aws": testProviderFuncFixed(p),
  1177  			},
  1178  		),
  1179  		Provisioners: map[string]ResourceProvisionerFactory{
  1180  			"local-exec": testProvisionerFuncFixed(pr),
  1181  		},
  1182  	})
  1183  
  1184  	_, err := ctx.Plan()
  1185  	if err == nil {
  1186  		t.Fatalf("should error")
  1187  	}
  1188  }
  1189  
  1190  func TestContext2Plan_computed(t *testing.T) {
  1191  	m := testModule(t, "plan-computed")
  1192  	p := testProvider("aws")
  1193  	p.DiffFn = testDiffFn
  1194  	ctx := testContext2(t, &ContextOpts{
  1195  		Module: m,
  1196  		ProviderResolver: ResourceProviderResolverFixed(
  1197  			map[string]ResourceProviderFactory{
  1198  				"aws": testProviderFuncFixed(p),
  1199  			},
  1200  		),
  1201  	})
  1202  
  1203  	plan, err := ctx.Plan()
  1204  	if err != nil {
  1205  		t.Fatalf("err: %s", err)
  1206  	}
  1207  
  1208  	actual := strings.TrimSpace(plan.String())
  1209  	expected := strings.TrimSpace(testTerraformPlanComputedStr)
  1210  	if actual != expected {
  1211  		t.Fatalf("bad:\n%s", actual)
  1212  	}
  1213  }
  1214  
  1215  func TestContext2Plan_computedDataResource(t *testing.T) {
  1216  	m := testModule(t, "plan-computed-data-resource")
  1217  	p := testProvider("aws")
  1218  	p.DiffFn = testDiffFn
  1219  	ctx := testContext2(t, &ContextOpts{
  1220  		Module: m,
  1221  		ProviderResolver: ResourceProviderResolverFixed(
  1222  			map[string]ResourceProviderFactory{
  1223  				"aws": testProviderFuncFixed(p),
  1224  			},
  1225  		),
  1226  	})
  1227  
  1228  	plan, err := ctx.Plan()
  1229  	if err != nil {
  1230  		t.Fatalf("err: %s", err)
  1231  	}
  1232  
  1233  	if got := len(plan.Diff.Modules); got != 1 {
  1234  		t.Fatalf("got %d modules; want 1", got)
  1235  	}
  1236  
  1237  	moduleDiff := plan.Diff.Modules[0]
  1238  
  1239  	if _, ok := moduleDiff.Resources["aws_instance.foo"]; !ok {
  1240  		t.Fatalf("missing diff for aws_instance.foo")
  1241  	}
  1242  	iDiff, ok := moduleDiff.Resources["data.aws_vpc.bar"]
  1243  	if !ok {
  1244  		t.Fatalf("missing diff for data.aws_vpc.bar")
  1245  	}
  1246  
  1247  	expectedDiff := &InstanceDiff{
  1248  		Attributes: map[string]*ResourceAttrDiff{
  1249  			"id": {
  1250  				NewComputed: true,
  1251  				RequiresNew: true,
  1252  				Type:        DiffAttrOutput,
  1253  			},
  1254  		},
  1255  	}
  1256  	if same, _ := expectedDiff.Same(iDiff); !same {
  1257  		t.Fatalf(
  1258  			"incorrect diff for data.aws_vpc.bar\ngot:  %#v\nwant: %#v",
  1259  			iDiff, expectedDiff,
  1260  		)
  1261  	}
  1262  }
  1263  
  1264  func TestContext2Plan_computedDataCountResource(t *testing.T) {
  1265  	m := testModule(t, "plan-computed-data-count")
  1266  	p := testProvider("aws")
  1267  	p.DiffFn = testDiffFn
  1268  	ctx := testContext2(t, &ContextOpts{
  1269  		Module: m,
  1270  		ProviderResolver: ResourceProviderResolverFixed(
  1271  			map[string]ResourceProviderFactory{
  1272  				"aws": testProviderFuncFixed(p),
  1273  			},
  1274  		),
  1275  	})
  1276  
  1277  	plan, err := ctx.Plan()
  1278  	if err != nil {
  1279  		t.Fatalf("err: %s", err)
  1280  	}
  1281  
  1282  	if got := len(plan.Diff.Modules); got != 1 {
  1283  		t.Fatalf("got %d modules; want 1", got)
  1284  	}
  1285  
  1286  	moduleDiff := plan.Diff.Modules[0]
  1287  
  1288  	// make sure we created 3 "bar"s
  1289  	for i := 0; i < 3; i++ {
  1290  		resource := fmt.Sprintf("data.aws_vpc.bar.%d", i)
  1291  		if _, ok := moduleDiff.Resources[resource]; !ok {
  1292  			t.Fatalf("missing diff for %s", resource)
  1293  		}
  1294  	}
  1295  }
  1296  
  1297  // Higher level test at TestResource_dataSourceListPlanPanic
  1298  func TestContext2Plan_dataSourceTypeMismatch(t *testing.T) {
  1299  	m := testModule(t, "plan-data-source-type-mismatch")
  1300  	p := testProvider("aws")
  1301  	p.ValidateResourceFn = func(t string, c *ResourceConfig) (ws []string, es []error) {
  1302  		// Emulate the type checking behavior of helper/schema based validation
  1303  		if t == "aws_instance" {
  1304  			ami, _ := c.Get("ami")
  1305  			switch a := ami.(type) {
  1306  			case string:
  1307  				// ok
  1308  			default:
  1309  				es = append(es, fmt.Errorf("Expected ami to be string, got %T", a))
  1310  			}
  1311  		}
  1312  		return
  1313  	}
  1314  	p.DiffFn = func(
  1315  		info *InstanceInfo,
  1316  		state *InstanceState,
  1317  		c *ResourceConfig) (*InstanceDiff, error) {
  1318  		if info.Type == "aws_instance" {
  1319  			// If we get to the diff, we should be able to assume types
  1320  			ami, _ := c.Get("ami")
  1321  			_ = ami.(string)
  1322  		}
  1323  		return nil, nil
  1324  	}
  1325  	ctx := testContext2(t, &ContextOpts{
  1326  		Module: m,
  1327  		// Pretend like we ran a Refresh and the AZs data source was populated.
  1328  		State: &State{
  1329  			Modules: []*ModuleState{
  1330  				&ModuleState{
  1331  					Path: rootModulePath,
  1332  					Resources: map[string]*ResourceState{
  1333  						"data.aws_availability_zones.azs": &ResourceState{
  1334  							Type: "aws_availability_zones",
  1335  							Primary: &InstanceState{
  1336  								ID: "i-abc123",
  1337  								Attributes: map[string]string{
  1338  									"names.#": "2",
  1339  									"names.0": "us-east-1a",
  1340  									"names.1": "us-east-1b",
  1341  								},
  1342  							},
  1343  						},
  1344  					},
  1345  				},
  1346  			},
  1347  		},
  1348  		ProviderResolver: ResourceProviderResolverFixed(
  1349  			map[string]ResourceProviderFactory{
  1350  				"aws": testProviderFuncFixed(p),
  1351  			},
  1352  		),
  1353  	})
  1354  
  1355  	_, err := ctx.Plan()
  1356  
  1357  	if err == nil {
  1358  		t.Fatalf("Expected err, got none!")
  1359  	}
  1360  	expected := "Expected ami to be string"
  1361  	if !strings.Contains(err.Error(), expected) {
  1362  		t.Fatalf("expected:\n\n%s\n\nto contain:\n\n%s", err, expected)
  1363  	}
  1364  }
  1365  
  1366  func TestContext2Plan_dataResourceBecomesComputed(t *testing.T) {
  1367  	m := testModule(t, "plan-data-resource-becomes-computed")
  1368  	p := testProvider("aws")
  1369  
  1370  	p.DiffFn = func(info *InstanceInfo, state *InstanceState, config *ResourceConfig) (*InstanceDiff, error) {
  1371  		if info.Type != "aws_instance" {
  1372  			t.Fatalf("don't know how to diff %s", info.Id)
  1373  			return nil, nil
  1374  		}
  1375  
  1376  		return &InstanceDiff{
  1377  			Attributes: map[string]*ResourceAttrDiff{
  1378  				"computed": &ResourceAttrDiff{
  1379  					Old:         "",
  1380  					New:         "",
  1381  					NewComputed: true,
  1382  				},
  1383  			},
  1384  		}, nil
  1385  	}
  1386  	p.ReadDataDiffReturn = &InstanceDiff{
  1387  		Attributes: map[string]*ResourceAttrDiff{
  1388  			"foo": &ResourceAttrDiff{
  1389  				Old:         "",
  1390  				New:         "",
  1391  				NewComputed: true,
  1392  			},
  1393  		},
  1394  	}
  1395  
  1396  	ctx := testContext2(t, &ContextOpts{
  1397  		Module: m,
  1398  		ProviderResolver: ResourceProviderResolverFixed(
  1399  			map[string]ResourceProviderFactory{
  1400  				"aws": testProviderFuncFixed(p),
  1401  			},
  1402  		),
  1403  		State: &State{
  1404  			Modules: []*ModuleState{
  1405  				&ModuleState{
  1406  					Path: rootModulePath,
  1407  					Resources: map[string]*ResourceState{
  1408  						"data.aws_data_resource.foo": &ResourceState{
  1409  							Type: "aws_data_resource",
  1410  							Primary: &InstanceState{
  1411  								ID: "i-abc123",
  1412  								Attributes: map[string]string{
  1413  									"id":    "i-abc123",
  1414  									"value": "baz",
  1415  								},
  1416  							},
  1417  						},
  1418  					},
  1419  				},
  1420  			},
  1421  		},
  1422  	})
  1423  
  1424  	plan, err := ctx.Plan()
  1425  	if err != nil {
  1426  		t.Fatalf("err: %s", err)
  1427  	}
  1428  
  1429  	if got := len(plan.Diff.Modules); got != 1 {
  1430  		t.Fatalf("got %d modules; want 1", got)
  1431  	}
  1432  
  1433  	if !p.ReadDataDiffCalled {
  1434  		t.Fatal("ReadDataDiff wasn't called, but should've been")
  1435  	}
  1436  	if got, want := p.ReadDataDiffInfo.Id, "data.aws_data_resource.foo"; got != want {
  1437  		t.Fatalf("ReadDataDiff info id is %s; want %s", got, want)
  1438  	}
  1439  
  1440  	moduleDiff := plan.Diff.Modules[0]
  1441  
  1442  	iDiff, ok := moduleDiff.Resources["data.aws_data_resource.foo"]
  1443  	if !ok {
  1444  		t.Fatalf("missing diff for data.aws_data_resource.foo")
  1445  	}
  1446  
  1447  	// This is added by the diff but we want to verify that we got
  1448  	// the same diff as above minus the dynamic stuff.
  1449  	delete(iDiff.Attributes, "id")
  1450  
  1451  	if same, _ := p.ReadDataDiffReturn.Same(iDiff); !same {
  1452  		t.Fatalf(
  1453  			"incorrect diff for data.data_resource.foo\ngot:  %#v\nwant: %#v",
  1454  			iDiff, p.ReadDataDiffReturn,
  1455  		)
  1456  	}
  1457  }
  1458  
  1459  func TestContext2Plan_computedList(t *testing.T) {
  1460  	m := testModule(t, "plan-computed-list")
  1461  	p := testProvider("aws")
  1462  	p.DiffFn = testDiffFn
  1463  	ctx := testContext2(t, &ContextOpts{
  1464  		Module: m,
  1465  		ProviderResolver: ResourceProviderResolverFixed(
  1466  			map[string]ResourceProviderFactory{
  1467  				"aws": testProviderFuncFixed(p),
  1468  			},
  1469  		),
  1470  	})
  1471  
  1472  	plan, err := ctx.Plan()
  1473  	if err != nil {
  1474  		t.Fatalf("err: %s", err)
  1475  	}
  1476  
  1477  	actual := strings.TrimSpace(plan.String())
  1478  	expected := strings.TrimSpace(testTerraformPlanComputedListStr)
  1479  	if actual != expected {
  1480  		t.Fatalf("bad:\n%s", actual)
  1481  	}
  1482  }
  1483  
  1484  // GH-8695. This tests that you can index into a computed list on a
  1485  // splatted resource.
  1486  func TestContext2Plan_computedMultiIndex(t *testing.T) {
  1487  	m := testModule(t, "plan-computed-multi-index")
  1488  	p := testProvider("aws")
  1489  	p.DiffFn = testDiffFn
  1490  	ctx := testContext2(t, &ContextOpts{
  1491  		Module: m,
  1492  		ProviderResolver: ResourceProviderResolverFixed(
  1493  			map[string]ResourceProviderFactory{
  1494  				"aws": testProviderFuncFixed(p),
  1495  			},
  1496  		),
  1497  	})
  1498  
  1499  	plan, err := ctx.Plan()
  1500  	if err != nil {
  1501  		t.Fatalf("err: %s", err)
  1502  	}
  1503  
  1504  	actual := strings.TrimSpace(plan.String())
  1505  	expected := strings.TrimSpace(testTerraformPlanComputedMultiIndexStr)
  1506  	if actual != expected {
  1507  		t.Fatalf("bad:\n%s", actual)
  1508  	}
  1509  }
  1510  
  1511  func TestContext2Plan_count(t *testing.T) {
  1512  	m := testModule(t, "plan-count")
  1513  	p := testProvider("aws")
  1514  	p.DiffFn = testDiffFn
  1515  	ctx := testContext2(t, &ContextOpts{
  1516  		Module: m,
  1517  		ProviderResolver: ResourceProviderResolverFixed(
  1518  			map[string]ResourceProviderFactory{
  1519  				"aws": testProviderFuncFixed(p),
  1520  			},
  1521  		),
  1522  	})
  1523  
  1524  	plan, err := ctx.Plan()
  1525  	if err != nil {
  1526  		t.Fatalf("err: %s", err)
  1527  	}
  1528  
  1529  	if len(plan.Diff.RootModule().Resources) < 6 {
  1530  		t.Fatalf("bad: %#v", plan.Diff.RootModule().Resources)
  1531  	}
  1532  
  1533  	actual := strings.TrimSpace(plan.String())
  1534  	expected := strings.TrimSpace(testTerraformPlanCountStr)
  1535  	if actual != expected {
  1536  		t.Fatalf("bad:\n%s", actual)
  1537  	}
  1538  }
  1539  
  1540  func TestContext2Plan_countComputed(t *testing.T) {
  1541  	m := testModule(t, "plan-count-computed")
  1542  	p := testProvider("aws")
  1543  	p.DiffFn = testDiffFn
  1544  	ctx := testContext2(t, &ContextOpts{
  1545  		Module: m,
  1546  		ProviderResolver: ResourceProviderResolverFixed(
  1547  			map[string]ResourceProviderFactory{
  1548  				"aws": testProviderFuncFixed(p),
  1549  			},
  1550  		),
  1551  	})
  1552  
  1553  	_, err := ctx.Plan()
  1554  	if err == nil {
  1555  		t.Fatal("should error")
  1556  	}
  1557  }
  1558  
  1559  func TestContext2Plan_countComputedModule(t *testing.T) {
  1560  	m := testModule(t, "plan-count-computed-module")
  1561  	p := testProvider("aws")
  1562  	p.DiffFn = testDiffFn
  1563  	ctx := testContext2(t, &ContextOpts{
  1564  		Module: m,
  1565  		ProviderResolver: ResourceProviderResolverFixed(
  1566  			map[string]ResourceProviderFactory{
  1567  				"aws": testProviderFuncFixed(p),
  1568  			},
  1569  		),
  1570  	})
  1571  
  1572  	_, err := ctx.Plan()
  1573  
  1574  	expectedErr := "aws_instance.bar: value of 'count'"
  1575  	if !strings.Contains(fmt.Sprintf("%s", err), expectedErr) {
  1576  		t.Fatalf("expected err would contain %q\nerr: %s\n",
  1577  			expectedErr, err)
  1578  	}
  1579  }
  1580  
  1581  func TestContext2Plan_countModuleStatic(t *testing.T) {
  1582  	m := testModule(t, "plan-count-module-static")
  1583  	p := testProvider("aws")
  1584  	p.DiffFn = testDiffFn
  1585  	ctx := testContext2(t, &ContextOpts{
  1586  		Module: m,
  1587  		ProviderResolver: ResourceProviderResolverFixed(
  1588  			map[string]ResourceProviderFactory{
  1589  				"aws": testProviderFuncFixed(p),
  1590  			},
  1591  		),
  1592  	})
  1593  
  1594  	plan, err := ctx.Plan()
  1595  	if err != nil {
  1596  		t.Fatalf("err: %s", err)
  1597  	}
  1598  
  1599  	actual := strings.TrimSpace(plan.String())
  1600  	expected := strings.TrimSpace(`
  1601  DIFF:
  1602  
  1603  module.child:
  1604    CREATE: aws_instance.foo.0
  1605    CREATE: aws_instance.foo.1
  1606    CREATE: aws_instance.foo.2
  1607  
  1608  STATE:
  1609  
  1610  <no state>
  1611  `)
  1612  	if actual != expected {
  1613  		t.Fatalf("bad:\n%s", actual)
  1614  	}
  1615  }
  1616  
  1617  func TestContext2Plan_countModuleStaticGrandchild(t *testing.T) {
  1618  	m := testModule(t, "plan-count-module-static-grandchild")
  1619  	p := testProvider("aws")
  1620  	p.DiffFn = testDiffFn
  1621  	ctx := testContext2(t, &ContextOpts{
  1622  		Module: m,
  1623  		ProviderResolver: ResourceProviderResolverFixed(
  1624  			map[string]ResourceProviderFactory{
  1625  				"aws": testProviderFuncFixed(p),
  1626  			},
  1627  		),
  1628  	})
  1629  
  1630  	plan, err := ctx.Plan()
  1631  	if err != nil {
  1632  		t.Fatalf("err: %s", err)
  1633  	}
  1634  
  1635  	actual := strings.TrimSpace(plan.String())
  1636  	expected := strings.TrimSpace(`
  1637  DIFF:
  1638  
  1639  module.child.child:
  1640    CREATE: aws_instance.foo.0
  1641    CREATE: aws_instance.foo.1
  1642    CREATE: aws_instance.foo.2
  1643  
  1644  STATE:
  1645  
  1646  <no state>
  1647  `)
  1648  	if actual != expected {
  1649  		t.Fatalf("bad:\n%s", actual)
  1650  	}
  1651  }
  1652  
  1653  func TestContext2Plan_countIndex(t *testing.T) {
  1654  	m := testModule(t, "plan-count-index")
  1655  	p := testProvider("aws")
  1656  	p.DiffFn = testDiffFn
  1657  	ctx := testContext2(t, &ContextOpts{
  1658  		Module: m,
  1659  		ProviderResolver: ResourceProviderResolverFixed(
  1660  			map[string]ResourceProviderFactory{
  1661  				"aws": testProviderFuncFixed(p),
  1662  			},
  1663  		),
  1664  	})
  1665  
  1666  	plan, err := ctx.Plan()
  1667  	if err != nil {
  1668  		t.Fatalf("err: %s", err)
  1669  	}
  1670  
  1671  	actual := strings.TrimSpace(plan.String())
  1672  	expected := strings.TrimSpace(testTerraformPlanCountIndexStr)
  1673  	if actual != expected {
  1674  		t.Fatalf("bad:\n%s", actual)
  1675  	}
  1676  }
  1677  
  1678  func TestContext2Plan_countIndexZero(t *testing.T) {
  1679  	m := testModule(t, "plan-count-index-zero")
  1680  	p := testProvider("aws")
  1681  	p.DiffFn = testDiffFn
  1682  	ctx := testContext2(t, &ContextOpts{
  1683  		Module: m,
  1684  		ProviderResolver: ResourceProviderResolverFixed(
  1685  			map[string]ResourceProviderFactory{
  1686  				"aws": testProviderFuncFixed(p),
  1687  			},
  1688  		),
  1689  	})
  1690  
  1691  	plan, err := ctx.Plan()
  1692  	if err != nil {
  1693  		t.Fatalf("err: %s", err)
  1694  	}
  1695  
  1696  	actual := strings.TrimSpace(plan.String())
  1697  	expected := strings.TrimSpace(testTerraformPlanCountIndexZeroStr)
  1698  	if actual != expected {
  1699  		t.Fatalf("bad:\n%s", actual)
  1700  	}
  1701  }
  1702  
  1703  func TestContext2Plan_countVar(t *testing.T) {
  1704  	m := testModule(t, "plan-count-var")
  1705  	p := testProvider("aws")
  1706  	p.DiffFn = testDiffFn
  1707  	ctx := testContext2(t, &ContextOpts{
  1708  		Module: m,
  1709  		ProviderResolver: ResourceProviderResolverFixed(
  1710  			map[string]ResourceProviderFactory{
  1711  				"aws": testProviderFuncFixed(p),
  1712  			},
  1713  		),
  1714  		Variables: map[string]interface{}{
  1715  			"count": "3",
  1716  		},
  1717  	})
  1718  
  1719  	plan, err := ctx.Plan()
  1720  	if err != nil {
  1721  		t.Fatalf("err: %s", err)
  1722  	}
  1723  
  1724  	actual := strings.TrimSpace(plan.String())
  1725  	expected := strings.TrimSpace(testTerraformPlanCountVarStr)
  1726  	if actual != expected {
  1727  		t.Fatalf("bad:\n%s", actual)
  1728  	}
  1729  }
  1730  
  1731  func TestContext2Plan_countZero(t *testing.T) {
  1732  	m := testModule(t, "plan-count-zero")
  1733  	p := testProvider("aws")
  1734  	p.DiffFn = testDiffFn
  1735  	ctx := testContext2(t, &ContextOpts{
  1736  		Module: m,
  1737  		ProviderResolver: ResourceProviderResolverFixed(
  1738  			map[string]ResourceProviderFactory{
  1739  				"aws": testProviderFuncFixed(p),
  1740  			},
  1741  		),
  1742  	})
  1743  
  1744  	plan, err := ctx.Plan()
  1745  	if err != nil {
  1746  		t.Fatalf("err: %s", err)
  1747  	}
  1748  
  1749  	actual := strings.TrimSpace(plan.String())
  1750  	expected := strings.TrimSpace(testTerraformPlanCountZeroStr)
  1751  	if actual != expected {
  1752  		t.Logf("expected:\n%s", expected)
  1753  		t.Fatalf("bad:\n%s", actual)
  1754  	}
  1755  }
  1756  
  1757  func TestContext2Plan_countOneIndex(t *testing.T) {
  1758  	m := testModule(t, "plan-count-one-index")
  1759  	p := testProvider("aws")
  1760  	p.DiffFn = testDiffFn
  1761  	ctx := testContext2(t, &ContextOpts{
  1762  		Module: m,
  1763  		ProviderResolver: ResourceProviderResolverFixed(
  1764  			map[string]ResourceProviderFactory{
  1765  				"aws": testProviderFuncFixed(p),
  1766  			},
  1767  		),
  1768  	})
  1769  
  1770  	plan, err := ctx.Plan()
  1771  	if err != nil {
  1772  		t.Fatalf("err: %s", err)
  1773  	}
  1774  
  1775  	actual := strings.TrimSpace(plan.String())
  1776  	expected := strings.TrimSpace(testTerraformPlanCountOneIndexStr)
  1777  	if actual != expected {
  1778  		t.Fatalf("bad:\n%s", actual)
  1779  	}
  1780  }
  1781  
  1782  func TestContext2Plan_countDecreaseToOne(t *testing.T) {
  1783  	m := testModule(t, "plan-count-dec")
  1784  	p := testProvider("aws")
  1785  	p.DiffFn = testDiffFn
  1786  	s := &State{
  1787  		Modules: []*ModuleState{
  1788  			&ModuleState{
  1789  				Path: rootModulePath,
  1790  				Resources: map[string]*ResourceState{
  1791  					"aws_instance.foo.0": &ResourceState{
  1792  						Type: "aws_instance",
  1793  						Primary: &InstanceState{
  1794  							ID: "bar",
  1795  							Attributes: map[string]string{
  1796  								"foo":  "foo",
  1797  								"type": "aws_instance",
  1798  							},
  1799  						},
  1800  					},
  1801  					"aws_instance.foo.1": &ResourceState{
  1802  						Type: "aws_instance",
  1803  						Primary: &InstanceState{
  1804  							ID: "bar",
  1805  						},
  1806  					},
  1807  					"aws_instance.foo.2": &ResourceState{
  1808  						Type: "aws_instance",
  1809  						Primary: &InstanceState{
  1810  							ID: "bar",
  1811  						},
  1812  					},
  1813  				},
  1814  			},
  1815  		},
  1816  	}
  1817  	ctx := testContext2(t, &ContextOpts{
  1818  		Module: m,
  1819  		ProviderResolver: ResourceProviderResolverFixed(
  1820  			map[string]ResourceProviderFactory{
  1821  				"aws": testProviderFuncFixed(p),
  1822  			},
  1823  		),
  1824  		State: s,
  1825  	})
  1826  
  1827  	plan, err := ctx.Plan()
  1828  	if err != nil {
  1829  		t.Fatalf("err: %s", err)
  1830  	}
  1831  
  1832  	actual := strings.TrimSpace(plan.String())
  1833  	expected := strings.TrimSpace(testTerraformPlanCountDecreaseStr)
  1834  	if actual != expected {
  1835  		t.Fatalf("bad:\n%s", actual)
  1836  	}
  1837  }
  1838  
  1839  func TestContext2Plan_countIncreaseFromNotSet(t *testing.T) {
  1840  	m := testModule(t, "plan-count-inc")
  1841  	p := testProvider("aws")
  1842  	p.DiffFn = testDiffFn
  1843  	s := &State{
  1844  		Modules: []*ModuleState{
  1845  			&ModuleState{
  1846  				Path: rootModulePath,
  1847  				Resources: map[string]*ResourceState{
  1848  					"aws_instance.foo": &ResourceState{
  1849  						Type: "aws_instance",
  1850  						Primary: &InstanceState{
  1851  							ID: "bar",
  1852  							Attributes: map[string]string{
  1853  								"foo":  "foo",
  1854  								"type": "aws_instance",
  1855  							},
  1856  						},
  1857  					},
  1858  				},
  1859  			},
  1860  		},
  1861  	}
  1862  	ctx := testContext2(t, &ContextOpts{
  1863  		Module: m,
  1864  		ProviderResolver: ResourceProviderResolverFixed(
  1865  			map[string]ResourceProviderFactory{
  1866  				"aws": testProviderFuncFixed(p),
  1867  			},
  1868  		),
  1869  		State: s,
  1870  	})
  1871  
  1872  	plan, err := ctx.Plan()
  1873  	if err != nil {
  1874  		t.Fatalf("err: %s", err)
  1875  	}
  1876  
  1877  	actual := strings.TrimSpace(plan.String())
  1878  	expected := strings.TrimSpace(testTerraformPlanCountIncreaseStr)
  1879  	if actual != expected {
  1880  		t.Fatalf("bad:\n%s", actual)
  1881  	}
  1882  }
  1883  
  1884  func TestContext2Plan_countIncreaseFromOne(t *testing.T) {
  1885  	m := testModule(t, "plan-count-inc")
  1886  	p := testProvider("aws")
  1887  	p.DiffFn = testDiffFn
  1888  	s := &State{
  1889  		Modules: []*ModuleState{
  1890  			&ModuleState{
  1891  				Path: rootModulePath,
  1892  				Resources: map[string]*ResourceState{
  1893  					"aws_instance.foo.0": &ResourceState{
  1894  						Type: "aws_instance",
  1895  						Primary: &InstanceState{
  1896  							ID: "bar",
  1897  							Attributes: map[string]string{
  1898  								"foo":  "foo",
  1899  								"type": "aws_instance",
  1900  							},
  1901  						},
  1902  					},
  1903  				},
  1904  			},
  1905  		},
  1906  	}
  1907  	ctx := testContext2(t, &ContextOpts{
  1908  		Module: m,
  1909  		ProviderResolver: ResourceProviderResolverFixed(
  1910  			map[string]ResourceProviderFactory{
  1911  				"aws": testProviderFuncFixed(p),
  1912  			},
  1913  		),
  1914  		State: s,
  1915  	})
  1916  
  1917  	plan, err := ctx.Plan()
  1918  	if err != nil {
  1919  		t.Fatalf("err: %s", err)
  1920  	}
  1921  
  1922  	actual := strings.TrimSpace(plan.String())
  1923  	expected := strings.TrimSpace(testTerraformPlanCountIncreaseFromOneStr)
  1924  	if actual != expected {
  1925  		t.Fatalf("bad:\n%s", actual)
  1926  	}
  1927  }
  1928  
  1929  // https://github.com/PeoplePerHour/terraform/pull/11
  1930  //
  1931  // This tests a case where both a "resource" and "resource.0" are in
  1932  // the state file, which apparently is a reasonable backwards compatibility
  1933  // concern found in the above 3rd party repo.
  1934  func TestContext2Plan_countIncreaseFromOneCorrupted(t *testing.T) {
  1935  	m := testModule(t, "plan-count-inc")
  1936  	p := testProvider("aws")
  1937  	p.DiffFn = testDiffFn
  1938  	s := &State{
  1939  		Modules: []*ModuleState{
  1940  			&ModuleState{
  1941  				Path: rootModulePath,
  1942  				Resources: map[string]*ResourceState{
  1943  					"aws_instance.foo": &ResourceState{
  1944  						Type: "aws_instance",
  1945  						Primary: &InstanceState{
  1946  							ID: "bar",
  1947  							Attributes: map[string]string{
  1948  								"foo":  "foo",
  1949  								"type": "aws_instance",
  1950  							},
  1951  						},
  1952  					},
  1953  					"aws_instance.foo.0": &ResourceState{
  1954  						Type: "aws_instance",
  1955  						Primary: &InstanceState{
  1956  							ID: "bar",
  1957  							Attributes: map[string]string{
  1958  								"foo":  "foo",
  1959  								"type": "aws_instance",
  1960  							},
  1961  						},
  1962  					},
  1963  				},
  1964  			},
  1965  		},
  1966  	}
  1967  	ctx := testContext2(t, &ContextOpts{
  1968  		Module: m,
  1969  		ProviderResolver: ResourceProviderResolverFixed(
  1970  			map[string]ResourceProviderFactory{
  1971  				"aws": testProviderFuncFixed(p),
  1972  			},
  1973  		),
  1974  		State: s,
  1975  	})
  1976  
  1977  	plan, err := ctx.Plan()
  1978  	if err != nil {
  1979  		t.Fatalf("err: %s", err)
  1980  	}
  1981  
  1982  	actual := strings.TrimSpace(plan.String())
  1983  	expected := strings.TrimSpace(testTerraformPlanCountIncreaseFromOneCorruptedStr)
  1984  	if actual != expected {
  1985  		t.Fatalf("bad:\n%s", actual)
  1986  	}
  1987  }
  1988  
  1989  // A common pattern in TF configs is to have a set of resources with the same
  1990  // count and to use count.index to create correspondences between them:
  1991  //
  1992  //    foo_id = "${foo.bar.*.id[count.index]}"
  1993  //
  1994  // This test is for the situation where some instances already exist and the
  1995  // count is increased. In that case, we should see only the create diffs
  1996  // for the new instances and not any update diffs for the existing ones.
  1997  func TestContext2Plan_countIncreaseWithSplatReference(t *testing.T) {
  1998  	m := testModule(t, "plan-count-splat-reference")
  1999  	p := testProvider("aws")
  2000  	p.DiffFn = testDiffFn
  2001  	s := &State{
  2002  		Modules: []*ModuleState{
  2003  			&ModuleState{
  2004  				Path: rootModulePath,
  2005  				Resources: map[string]*ResourceState{
  2006  					"aws_instance.foo.0": &ResourceState{
  2007  						Type: "aws_instance",
  2008  						Primary: &InstanceState{
  2009  							ID: "bar",
  2010  							Attributes: map[string]string{
  2011  								"name": "foo 0",
  2012  							},
  2013  						},
  2014  					},
  2015  					"aws_instance.foo.1": &ResourceState{
  2016  						Type: "aws_instance",
  2017  						Primary: &InstanceState{
  2018  							ID: "bar",
  2019  							Attributes: map[string]string{
  2020  								"name": "foo 1",
  2021  							},
  2022  						},
  2023  					},
  2024  					"aws_instance.bar.0": &ResourceState{
  2025  						Type: "aws_instance",
  2026  						Primary: &InstanceState{
  2027  							ID: "bar",
  2028  							Attributes: map[string]string{
  2029  								"foo_name": "foo 0",
  2030  							},
  2031  						},
  2032  					},
  2033  					"aws_instance.bar.1": &ResourceState{
  2034  						Type: "aws_instance",
  2035  						Primary: &InstanceState{
  2036  							ID: "bar",
  2037  							Attributes: map[string]string{
  2038  								"foo_name": "foo 1",
  2039  							},
  2040  						},
  2041  					},
  2042  				},
  2043  			},
  2044  		},
  2045  	}
  2046  	ctx := testContext2(t, &ContextOpts{
  2047  		Module: m,
  2048  		ProviderResolver: ResourceProviderResolverFixed(
  2049  			map[string]ResourceProviderFactory{
  2050  				"aws": testProviderFuncFixed(p),
  2051  			},
  2052  		),
  2053  		State: s,
  2054  	})
  2055  
  2056  	plan, err := ctx.Plan()
  2057  	if err != nil {
  2058  		t.Fatalf("err: %s", err)
  2059  	}
  2060  
  2061  	actual := strings.TrimSpace(plan.String())
  2062  	expected := strings.TrimSpace(`
  2063  DIFF:
  2064  
  2065  CREATE: aws_instance.bar.2
  2066    foo_name: "" => "foo 2"
  2067    type:     "" => "aws_instance"
  2068  CREATE: aws_instance.foo.2
  2069    name: "" => "foo 2"
  2070    type: "" => "aws_instance"
  2071  
  2072  STATE:
  2073  
  2074  aws_instance.bar.0:
  2075    ID = bar
  2076    foo_name = foo 0
  2077  aws_instance.bar.1:
  2078    ID = bar
  2079    foo_name = foo 1
  2080  aws_instance.foo.0:
  2081    ID = bar
  2082    name = foo 0
  2083  aws_instance.foo.1:
  2084    ID = bar
  2085    name = foo 1
  2086  `)
  2087  	if actual != expected {
  2088  		t.Fatalf("bad:\n%s", actual)
  2089  	}
  2090  }
  2091  
  2092  func TestContext2Plan_destroy(t *testing.T) {
  2093  	m := testModule(t, "plan-destroy")
  2094  	p := testProvider("aws")
  2095  	p.DiffFn = testDiffFn
  2096  	s := &State{
  2097  		Modules: []*ModuleState{
  2098  			&ModuleState{
  2099  				Path: rootModulePath,
  2100  				Resources: map[string]*ResourceState{
  2101  					"aws_instance.one": &ResourceState{
  2102  						Type: "aws_instance",
  2103  						Primary: &InstanceState{
  2104  							ID: "bar",
  2105  						},
  2106  					},
  2107  					"aws_instance.two": &ResourceState{
  2108  						Type: "aws_instance",
  2109  						Primary: &InstanceState{
  2110  							ID: "baz",
  2111  						},
  2112  					},
  2113  				},
  2114  			},
  2115  		},
  2116  	}
  2117  	ctx := testContext2(t, &ContextOpts{
  2118  		Module: m,
  2119  		ProviderResolver: ResourceProviderResolverFixed(
  2120  			map[string]ResourceProviderFactory{
  2121  				"aws": testProviderFuncFixed(p),
  2122  			},
  2123  		),
  2124  		State:   s,
  2125  		Destroy: true,
  2126  	})
  2127  
  2128  	plan, err := ctx.Plan()
  2129  	if err != nil {
  2130  		t.Fatalf("err: %s", err)
  2131  	}
  2132  
  2133  	if len(plan.Diff.RootModule().Resources) != 2 {
  2134  		t.Fatalf("bad: %#v", plan.Diff.RootModule().Resources)
  2135  	}
  2136  
  2137  	actual := strings.TrimSpace(plan.String())
  2138  	expected := strings.TrimSpace(testTerraformPlanDestroyStr)
  2139  	if actual != expected {
  2140  		t.Fatalf("bad:\n%s", actual)
  2141  	}
  2142  }
  2143  
  2144  func TestContext2Plan_moduleDestroy(t *testing.T) {
  2145  	m := testModule(t, "plan-module-destroy")
  2146  	p := testProvider("aws")
  2147  	p.DiffFn = testDiffFn
  2148  	s := &State{
  2149  		Modules: []*ModuleState{
  2150  			&ModuleState{
  2151  				Path: rootModulePath,
  2152  				Resources: map[string]*ResourceState{
  2153  					"aws_instance.foo": &ResourceState{
  2154  						Type: "aws_instance",
  2155  						Primary: &InstanceState{
  2156  							ID: "bar",
  2157  						},
  2158  					},
  2159  				},
  2160  			},
  2161  			&ModuleState{
  2162  				Path: []string{"root", "child"},
  2163  				Resources: map[string]*ResourceState{
  2164  					"aws_instance.foo": &ResourceState{
  2165  						Type: "aws_instance",
  2166  						Primary: &InstanceState{
  2167  							ID: "bar",
  2168  						},
  2169  					},
  2170  				},
  2171  			},
  2172  		},
  2173  	}
  2174  	ctx := testContext2(t, &ContextOpts{
  2175  		Module: m,
  2176  		ProviderResolver: ResourceProviderResolverFixed(
  2177  			map[string]ResourceProviderFactory{
  2178  				"aws": testProviderFuncFixed(p),
  2179  			},
  2180  		),
  2181  		State:   s,
  2182  		Destroy: true,
  2183  	})
  2184  
  2185  	plan, err := ctx.Plan()
  2186  	if err != nil {
  2187  		t.Fatalf("err: %s", err)
  2188  	}
  2189  
  2190  	actual := strings.TrimSpace(plan.String())
  2191  	expected := strings.TrimSpace(testTerraformPlanModuleDestroyStr)
  2192  	if actual != expected {
  2193  		t.Fatalf("bad:\n%s\n\nexpected:\n\n%s", actual, expected)
  2194  	}
  2195  }
  2196  
  2197  // GH-1835
  2198  func TestContext2Plan_moduleDestroyCycle(t *testing.T) {
  2199  	m := testModule(t, "plan-module-destroy-gh-1835")
  2200  	p := testProvider("aws")
  2201  	p.DiffFn = testDiffFn
  2202  	s := &State{
  2203  		Modules: []*ModuleState{
  2204  			&ModuleState{
  2205  				Path: []string{"root", "a_module"},
  2206  				Resources: map[string]*ResourceState{
  2207  					"aws_instance.a": &ResourceState{
  2208  						Type: "aws_instance",
  2209  						Primary: &InstanceState{
  2210  							ID: "a",
  2211  						},
  2212  					},
  2213  				},
  2214  			},
  2215  			&ModuleState{
  2216  				Path: []string{"root", "b_module"},
  2217  				Resources: map[string]*ResourceState{
  2218  					"aws_instance.b": &ResourceState{
  2219  						Type: "aws_instance",
  2220  						Primary: &InstanceState{
  2221  							ID: "b",
  2222  						},
  2223  					},
  2224  				},
  2225  			},
  2226  		},
  2227  	}
  2228  	ctx := testContext2(t, &ContextOpts{
  2229  		Module: m,
  2230  		ProviderResolver: ResourceProviderResolverFixed(
  2231  			map[string]ResourceProviderFactory{
  2232  				"aws": testProviderFuncFixed(p),
  2233  			},
  2234  		),
  2235  		State:   s,
  2236  		Destroy: true,
  2237  	})
  2238  
  2239  	plan, err := ctx.Plan()
  2240  	if err != nil {
  2241  		t.Fatalf("err: %s", err)
  2242  	}
  2243  
  2244  	actual := strings.TrimSpace(plan.String())
  2245  	expected := strings.TrimSpace(testTerraformPlanModuleDestroyCycleStr)
  2246  	if actual != expected {
  2247  		t.Fatalf("bad:\n%s\n\nexpected:\n\n%s", actual, expected)
  2248  	}
  2249  }
  2250  
  2251  func TestContext2Plan_moduleDestroyMultivar(t *testing.T) {
  2252  	m := testModule(t, "plan-module-destroy-multivar")
  2253  	p := testProvider("aws")
  2254  	p.DiffFn = testDiffFn
  2255  	s := &State{
  2256  		Modules: []*ModuleState{
  2257  			&ModuleState{
  2258  				Path:      rootModulePath,
  2259  				Resources: map[string]*ResourceState{},
  2260  			},
  2261  			&ModuleState{
  2262  				Path: []string{"root", "child"},
  2263  				Resources: map[string]*ResourceState{
  2264  					"aws_instance.foo.0": &ResourceState{
  2265  						Type: "aws_instance",
  2266  						Primary: &InstanceState{
  2267  							ID: "bar0",
  2268  						},
  2269  					},
  2270  					"aws_instance.foo.1": &ResourceState{
  2271  						Type: "aws_instance",
  2272  						Primary: &InstanceState{
  2273  							ID: "bar1",
  2274  						},
  2275  					},
  2276  				},
  2277  			},
  2278  		},
  2279  	}
  2280  	ctx := testContext2(t, &ContextOpts{
  2281  		Module: m,
  2282  		ProviderResolver: ResourceProviderResolverFixed(
  2283  			map[string]ResourceProviderFactory{
  2284  				"aws": testProviderFuncFixed(p),
  2285  			},
  2286  		),
  2287  		State:   s,
  2288  		Destroy: true,
  2289  	})
  2290  
  2291  	plan, err := ctx.Plan()
  2292  	if err != nil {
  2293  		t.Fatalf("err: %s", err)
  2294  	}
  2295  
  2296  	actual := strings.TrimSpace(plan.String())
  2297  	expected := strings.TrimSpace(testTerraformPlanModuleDestroyMultivarStr)
  2298  	if actual != expected {
  2299  		t.Fatalf("bad:\n%s\n\nexpected:\n\n%s", actual, expected)
  2300  	}
  2301  }
  2302  
  2303  func TestContext2Plan_pathVar(t *testing.T) {
  2304  	cwd, err := os.Getwd()
  2305  	if err != nil {
  2306  		t.Fatalf("err: %s", err)
  2307  	}
  2308  
  2309  	m := testModule(t, "plan-path-var")
  2310  	p := testProvider("aws")
  2311  	p.DiffFn = testDiffFn
  2312  	ctx := testContext2(t, &ContextOpts{
  2313  		Module: m,
  2314  		ProviderResolver: ResourceProviderResolverFixed(
  2315  			map[string]ResourceProviderFactory{
  2316  				"aws": testProviderFuncFixed(p),
  2317  			},
  2318  		),
  2319  	})
  2320  
  2321  	plan, err := ctx.Plan()
  2322  	if err != nil {
  2323  		t.Fatalf("err: %s", err)
  2324  	}
  2325  
  2326  	actual := strings.TrimSpace(plan.String())
  2327  	expected := strings.TrimSpace(testTerraformPlanPathVarStr)
  2328  
  2329  	// Warning: this ordering REALLY matters for this test. The
  2330  	// order is: cwd, module, root.
  2331  	expected = fmt.Sprintf(
  2332  		expected,
  2333  		cwd,
  2334  		m.Config().Dir,
  2335  		m.Config().Dir)
  2336  
  2337  	if actual != expected {
  2338  		t.Fatalf("bad:\n%s\n\nexpected:\n\n%s", actual, expected)
  2339  	}
  2340  }
  2341  
  2342  func TestContext2Plan_diffVar(t *testing.T) {
  2343  	m := testModule(t, "plan-diffvar")
  2344  	p := testProvider("aws")
  2345  	s := &State{
  2346  		Modules: []*ModuleState{
  2347  			&ModuleState{
  2348  				Path: rootModulePath,
  2349  				Resources: map[string]*ResourceState{
  2350  					"aws_instance.foo": &ResourceState{
  2351  						Type: "aws_instance",
  2352  						Primary: &InstanceState{
  2353  							ID: "bar",
  2354  							Attributes: map[string]string{
  2355  								"num": "2",
  2356  							},
  2357  						},
  2358  					},
  2359  				},
  2360  			},
  2361  		},
  2362  	}
  2363  	ctx := testContext2(t, &ContextOpts{
  2364  		Module: m,
  2365  		ProviderResolver: ResourceProviderResolverFixed(
  2366  			map[string]ResourceProviderFactory{
  2367  				"aws": testProviderFuncFixed(p),
  2368  			},
  2369  		),
  2370  		State: s,
  2371  	})
  2372  
  2373  	p.DiffFn = func(
  2374  		info *InstanceInfo,
  2375  		s *InstanceState,
  2376  		c *ResourceConfig) (*InstanceDiff, error) {
  2377  		if s.ID != "bar" {
  2378  			return testDiffFn(info, s, c)
  2379  		}
  2380  
  2381  		return &InstanceDiff{
  2382  			Attributes: map[string]*ResourceAttrDiff{
  2383  				"num": &ResourceAttrDiff{
  2384  					Old: "2",
  2385  					New: "3",
  2386  				},
  2387  			},
  2388  		}, nil
  2389  	}
  2390  
  2391  	plan, err := ctx.Plan()
  2392  	if err != nil {
  2393  		t.Fatalf("err: %s", err)
  2394  	}
  2395  
  2396  	actual := strings.TrimSpace(plan.String())
  2397  	expected := strings.TrimSpace(testTerraformPlanDiffVarStr)
  2398  	if actual != expected {
  2399  		t.Fatalf("actual:\n%s\n\nexpected:\n%s", actual, expected)
  2400  	}
  2401  }
  2402  
  2403  func TestContext2Plan_hook(t *testing.T) {
  2404  	m := testModule(t, "plan-good")
  2405  	h := new(MockHook)
  2406  	p := testProvider("aws")
  2407  	p.DiffFn = testDiffFn
  2408  	ctx := testContext2(t, &ContextOpts{
  2409  		Module: m,
  2410  		Hooks:  []Hook{h},
  2411  		ProviderResolver: ResourceProviderResolverFixed(
  2412  			map[string]ResourceProviderFactory{
  2413  				"aws": testProviderFuncFixed(p),
  2414  			},
  2415  		),
  2416  	})
  2417  
  2418  	_, err := ctx.Plan()
  2419  	if err != nil {
  2420  		t.Fatalf("err: %s", err)
  2421  	}
  2422  
  2423  	if !h.PreDiffCalled {
  2424  		t.Fatal("should be called")
  2425  	}
  2426  	if !h.PostDiffCalled {
  2427  		t.Fatal("should be called")
  2428  	}
  2429  }
  2430  
  2431  func TestContext2Plan_orphan(t *testing.T) {
  2432  	m := testModule(t, "plan-orphan")
  2433  	p := testProvider("aws")
  2434  	p.DiffFn = testDiffFn
  2435  	s := &State{
  2436  		Modules: []*ModuleState{
  2437  			&ModuleState{
  2438  				Path: rootModulePath,
  2439  				Resources: map[string]*ResourceState{
  2440  					"aws_instance.baz": &ResourceState{
  2441  						Type: "aws_instance",
  2442  						Primary: &InstanceState{
  2443  							ID: "bar",
  2444  						},
  2445  					},
  2446  				},
  2447  			},
  2448  		},
  2449  	}
  2450  	ctx := testContext2(t, &ContextOpts{
  2451  		Module: m,
  2452  		ProviderResolver: ResourceProviderResolverFixed(
  2453  			map[string]ResourceProviderFactory{
  2454  				"aws": testProviderFuncFixed(p),
  2455  			},
  2456  		),
  2457  		State: s,
  2458  	})
  2459  
  2460  	plan, err := ctx.Plan()
  2461  	if err != nil {
  2462  		t.Fatalf("err: %s", err)
  2463  	}
  2464  
  2465  	actual := strings.TrimSpace(plan.String())
  2466  	expected := strings.TrimSpace(testTerraformPlanOrphanStr)
  2467  	if actual != expected {
  2468  		t.Fatalf("bad:\n%s", actual)
  2469  	}
  2470  }
  2471  
  2472  // This tests that configurations with UUIDs don't produce errors.
  2473  // For shadows, this would produce errors since a UUID changes every time.
  2474  func TestContext2Plan_shadowUuid(t *testing.T) {
  2475  	m := testModule(t, "plan-shadow-uuid")
  2476  	p := testProvider("aws")
  2477  	p.DiffFn = testDiffFn
  2478  	ctx := testContext2(t, &ContextOpts{
  2479  		Module: m,
  2480  		ProviderResolver: ResourceProviderResolverFixed(
  2481  			map[string]ResourceProviderFactory{
  2482  				"aws": testProviderFuncFixed(p),
  2483  			},
  2484  		),
  2485  	})
  2486  
  2487  	_, err := ctx.Plan()
  2488  	if err != nil {
  2489  		t.Fatalf("err: %s", err)
  2490  	}
  2491  }
  2492  
  2493  func TestContext2Plan_state(t *testing.T) {
  2494  	m := testModule(t, "plan-good")
  2495  	p := testProvider("aws")
  2496  	p.DiffFn = testDiffFn
  2497  	s := &State{
  2498  		Modules: []*ModuleState{
  2499  			&ModuleState{
  2500  				Path: rootModulePath,
  2501  				Resources: map[string]*ResourceState{
  2502  					"aws_instance.foo": &ResourceState{
  2503  						Type: "aws_instance",
  2504  						Primary: &InstanceState{
  2505  							ID: "bar",
  2506  						},
  2507  					},
  2508  				},
  2509  			},
  2510  		},
  2511  	}
  2512  	ctx := testContext2(t, &ContextOpts{
  2513  		Module: m,
  2514  		ProviderResolver: ResourceProviderResolverFixed(
  2515  			map[string]ResourceProviderFactory{
  2516  				"aws": testProviderFuncFixed(p),
  2517  			},
  2518  		),
  2519  		State: s,
  2520  	})
  2521  
  2522  	plan, err := ctx.Plan()
  2523  	if err != nil {
  2524  		t.Fatalf("err: %s", err)
  2525  	}
  2526  
  2527  	if len(plan.Diff.RootModule().Resources) < 2 {
  2528  		t.Fatalf("bad: %#v", plan.Diff.RootModule().Resources)
  2529  	}
  2530  
  2531  	actual := strings.TrimSpace(plan.String())
  2532  	expected := strings.TrimSpace(testTerraformPlanStateStr)
  2533  	if actual != expected {
  2534  		t.Fatalf("bad:\n%s\n\nexpected:\n\n%s", actual, expected)
  2535  	}
  2536  }
  2537  
  2538  func TestContext2Plan_taint(t *testing.T) {
  2539  	m := testModule(t, "plan-taint")
  2540  	p := testProvider("aws")
  2541  	p.DiffFn = testDiffFn
  2542  	s := &State{
  2543  		Modules: []*ModuleState{
  2544  			&ModuleState{
  2545  				Path: rootModulePath,
  2546  				Resources: map[string]*ResourceState{
  2547  					"aws_instance.foo": &ResourceState{
  2548  						Type: "aws_instance",
  2549  						Primary: &InstanceState{
  2550  							ID:         "bar",
  2551  							Attributes: map[string]string{"num": "2"},
  2552  						},
  2553  					},
  2554  					"aws_instance.bar": &ResourceState{
  2555  						Type: "aws_instance",
  2556  						Primary: &InstanceState{
  2557  							ID:      "baz",
  2558  							Tainted: true,
  2559  						},
  2560  					},
  2561  				},
  2562  			},
  2563  		},
  2564  	}
  2565  	ctx := testContext2(t, &ContextOpts{
  2566  		Module: m,
  2567  		ProviderResolver: ResourceProviderResolverFixed(
  2568  			map[string]ResourceProviderFactory{
  2569  				"aws": testProviderFuncFixed(p),
  2570  			},
  2571  		),
  2572  		State: s,
  2573  	})
  2574  
  2575  	plan, err := ctx.Plan()
  2576  	if err != nil {
  2577  		t.Fatalf("err: %s", err)
  2578  	}
  2579  
  2580  	actual := strings.TrimSpace(plan.String())
  2581  	expected := strings.TrimSpace(testTerraformPlanTaintStr)
  2582  	if actual != expected {
  2583  		t.Fatalf("bad:\n%s", actual)
  2584  	}
  2585  }
  2586  
  2587  func TestContext2Apply_taintIgnoreChanges(t *testing.T) {
  2588  	m := testModule(t, "plan-taint-ignore-changes")
  2589  	p := testProvider("aws")
  2590  	p.ApplyFn = testApplyFn
  2591  	p.DiffFn = testDiffFn
  2592  	s := &State{
  2593  		Modules: []*ModuleState{
  2594  			&ModuleState{
  2595  				Path: rootModulePath,
  2596  				Resources: map[string]*ResourceState{
  2597  					"aws_instance.foo": &ResourceState{
  2598  						Type: "aws_instance",
  2599  						Primary: &InstanceState{
  2600  							ID: "foo",
  2601  							Attributes: map[string]string{
  2602  								"vars": "foo",
  2603  								"type": "aws_instance",
  2604  							},
  2605  							Tainted: true,
  2606  						},
  2607  					},
  2608  				},
  2609  			},
  2610  		},
  2611  	}
  2612  	ctx := testContext2(t, &ContextOpts{
  2613  		Module: m,
  2614  		ProviderResolver: ResourceProviderResolverFixed(
  2615  			map[string]ResourceProviderFactory{
  2616  				"aws": testProviderFuncFixed(p),
  2617  			},
  2618  		),
  2619  		State: s,
  2620  	})
  2621  
  2622  	plan, err := ctx.Plan()
  2623  	if err != nil {
  2624  		t.Fatalf("err: %s", err)
  2625  	}
  2626  
  2627  	actual := strings.TrimSpace(plan.String())
  2628  	expected := strings.TrimSpace(testTerraformPlanTaintIgnoreChangesStr)
  2629  	if actual != expected {
  2630  		t.Fatalf("bad:\n%s", actual)
  2631  	}
  2632  }
  2633  
  2634  // Fails about 50% of the time before the fix for GH-4982, covers the fix.
  2635  func TestContext2Plan_taintDestroyInterpolatedCountRace(t *testing.T) {
  2636  	m := testModule(t, "plan-taint-interpolated-count")
  2637  	p := testProvider("aws")
  2638  	p.DiffFn = testDiffFn
  2639  	s := &State{
  2640  		Modules: []*ModuleState{
  2641  			&ModuleState{
  2642  				Path: rootModulePath,
  2643  				Resources: map[string]*ResourceState{
  2644  					"aws_instance.foo.0": &ResourceState{
  2645  						Type: "aws_instance",
  2646  						Primary: &InstanceState{
  2647  							ID:      "bar",
  2648  							Tainted: true,
  2649  						},
  2650  					},
  2651  					"aws_instance.foo.1": &ResourceState{
  2652  						Type:    "aws_instance",
  2653  						Primary: &InstanceState{ID: "bar"},
  2654  					},
  2655  					"aws_instance.foo.2": &ResourceState{
  2656  						Type:    "aws_instance",
  2657  						Primary: &InstanceState{ID: "bar"},
  2658  					},
  2659  				},
  2660  			},
  2661  		},
  2662  	}
  2663  	ctx := testContext2(t, &ContextOpts{
  2664  		Module: m,
  2665  		ProviderResolver: ResourceProviderResolverFixed(
  2666  			map[string]ResourceProviderFactory{
  2667  				"aws": testProviderFuncFixed(p),
  2668  			},
  2669  		),
  2670  		State: s,
  2671  	})
  2672  
  2673  	for i := 0; i < 100; i++ {
  2674  		plan, err := ctx.Plan()
  2675  		if err != nil {
  2676  			t.Fatalf("err: %s", err)
  2677  		}
  2678  
  2679  		actual := strings.TrimSpace(plan.String())
  2680  		expected := strings.TrimSpace(`
  2681  DIFF:
  2682  
  2683  DESTROY/CREATE: aws_instance.foo.0
  2684    type: "" => "aws_instance"
  2685  
  2686  STATE:
  2687  
  2688  aws_instance.foo.0: (tainted)
  2689    ID = bar
  2690  aws_instance.foo.1:
  2691    ID = bar
  2692  aws_instance.foo.2:
  2693    ID = bar
  2694  		`)
  2695  		if actual != expected {
  2696  			t.Fatalf("[%d] bad:\n%s\nexpected:\n%s\n", i, actual, expected)
  2697  		}
  2698  	}
  2699  }
  2700  
  2701  func TestContext2Plan_targeted(t *testing.T) {
  2702  	m := testModule(t, "plan-targeted")
  2703  	p := testProvider("aws")
  2704  	p.DiffFn = testDiffFn
  2705  	ctx := testContext2(t, &ContextOpts{
  2706  		Module: m,
  2707  		ProviderResolver: ResourceProviderResolverFixed(
  2708  			map[string]ResourceProviderFactory{
  2709  				"aws": testProviderFuncFixed(p),
  2710  			},
  2711  		),
  2712  		Targets: []string{"aws_instance.foo"},
  2713  	})
  2714  
  2715  	plan, err := ctx.Plan()
  2716  	if err != nil {
  2717  		t.Fatalf("err: %s", err)
  2718  	}
  2719  
  2720  	actual := strings.TrimSpace(plan.String())
  2721  	expected := strings.TrimSpace(`
  2722  DIFF:
  2723  
  2724  CREATE: aws_instance.foo
  2725    num:  "" => "2"
  2726    type: "" => "aws_instance"
  2727  
  2728  STATE:
  2729  
  2730  <no state>
  2731  	`)
  2732  	if actual != expected {
  2733  		t.Fatalf("expected:\n%s\n\ngot:\n%s", expected, actual)
  2734  	}
  2735  }
  2736  
  2737  // Test that targeting a module properly plans any inputs that depend
  2738  // on another module.
  2739  func TestContext2Plan_targetedCrossModule(t *testing.T) {
  2740  	m := testModule(t, "plan-targeted-cross-module")
  2741  	p := testProvider("aws")
  2742  	p.DiffFn = testDiffFn
  2743  	ctx := testContext2(t, &ContextOpts{
  2744  		Module: m,
  2745  		ProviderResolver: ResourceProviderResolverFixed(
  2746  			map[string]ResourceProviderFactory{
  2747  				"aws": testProviderFuncFixed(p),
  2748  			},
  2749  		),
  2750  		Targets: []string{"module.B"},
  2751  	})
  2752  
  2753  	plan, err := ctx.Plan()
  2754  	if err != nil {
  2755  		t.Fatalf("err: %s", err)
  2756  	}
  2757  
  2758  	actual := strings.TrimSpace(plan.String())
  2759  	expected := strings.TrimSpace(`
  2760  DIFF:
  2761  
  2762  module.A:
  2763    CREATE: aws_instance.foo
  2764      foo:  "" => "bar"
  2765      type: "" => "aws_instance"
  2766  module.B:
  2767    CREATE: aws_instance.bar
  2768      foo:  "" => "<computed>"
  2769      type: "" => "aws_instance"
  2770  
  2771  STATE:
  2772  
  2773  <no state>
  2774  	`)
  2775  	if actual != expected {
  2776  		t.Fatalf("expected:\n%s\n\ngot:\n%s", expected, actual)
  2777  	}
  2778  }
  2779  
  2780  func TestContext2Plan_targetedModuleWithProvider(t *testing.T) {
  2781  	m := testModule(t, "plan-targeted-module-with-provider")
  2782  	p := testProvider("null")
  2783  	p.DiffFn = testDiffFn
  2784  	ctx := testContext2(t, &ContextOpts{
  2785  		Module: m,
  2786  		ProviderResolver: ResourceProviderResolverFixed(
  2787  			map[string]ResourceProviderFactory{
  2788  				"null": testProviderFuncFixed(p),
  2789  			},
  2790  		),
  2791  		Targets: []string{"module.child2"},
  2792  	})
  2793  
  2794  	plan, err := ctx.Plan()
  2795  	if err != nil {
  2796  		t.Fatalf("err: %s", err)
  2797  	}
  2798  
  2799  	actual := strings.TrimSpace(plan.String())
  2800  	expected := strings.TrimSpace(`
  2801  DIFF:
  2802  
  2803  module.child2:
  2804    CREATE: null_resource.foo
  2805  
  2806  STATE:
  2807  
  2808  <no state>
  2809  	`)
  2810  	if actual != expected {
  2811  		t.Fatalf("expected:\n%s\n\ngot:\n%s", expected, actual)
  2812  	}
  2813  }
  2814  
  2815  func TestContext2Plan_targetedOrphan(t *testing.T) {
  2816  	m := testModule(t, "plan-targeted-orphan")
  2817  	p := testProvider("aws")
  2818  	p.DiffFn = testDiffFn
  2819  	ctx := testContext2(t, &ContextOpts{
  2820  		Module: m,
  2821  		ProviderResolver: ResourceProviderResolverFixed(
  2822  			map[string]ResourceProviderFactory{
  2823  				"aws": testProviderFuncFixed(p),
  2824  			},
  2825  		),
  2826  		State: &State{
  2827  			Modules: []*ModuleState{
  2828  				&ModuleState{
  2829  					Path: rootModulePath,
  2830  					Resources: map[string]*ResourceState{
  2831  						"aws_instance.orphan": &ResourceState{
  2832  							Type: "aws_instance",
  2833  							Primary: &InstanceState{
  2834  								ID: "i-789xyz",
  2835  							},
  2836  						},
  2837  						"aws_instance.nottargeted": &ResourceState{
  2838  							Type: "aws_instance",
  2839  							Primary: &InstanceState{
  2840  								ID: "i-abc123",
  2841  							},
  2842  						},
  2843  					},
  2844  				},
  2845  			},
  2846  		},
  2847  		Destroy: true,
  2848  		Targets: []string{"aws_instance.orphan"},
  2849  	})
  2850  
  2851  	plan, err := ctx.Plan()
  2852  	if err != nil {
  2853  		t.Fatalf("err: %s", err)
  2854  	}
  2855  
  2856  	actual := strings.TrimSpace(plan.String())
  2857  	expected := strings.TrimSpace(`DIFF:
  2858  
  2859  DESTROY: aws_instance.orphan
  2860  
  2861  STATE:
  2862  
  2863  aws_instance.nottargeted:
  2864    ID = i-abc123
  2865  aws_instance.orphan:
  2866    ID = i-789xyz
  2867  `)
  2868  	if actual != expected {
  2869  		t.Fatalf("expected:\n%s\n\ngot:\n%s", expected, actual)
  2870  	}
  2871  }
  2872  
  2873  // https://github.com/hashicorp/terraform/issues/2538
  2874  func TestContext2Plan_targetedModuleOrphan(t *testing.T) {
  2875  	m := testModule(t, "plan-targeted-module-orphan")
  2876  	p := testProvider("aws")
  2877  	p.DiffFn = testDiffFn
  2878  	ctx := testContext2(t, &ContextOpts{
  2879  		Module: m,
  2880  		ProviderResolver: ResourceProviderResolverFixed(
  2881  			map[string]ResourceProviderFactory{
  2882  				"aws": testProviderFuncFixed(p),
  2883  			},
  2884  		),
  2885  		State: &State{
  2886  			Modules: []*ModuleState{
  2887  				&ModuleState{
  2888  					Path: []string{"root", "child"},
  2889  					Resources: map[string]*ResourceState{
  2890  						"aws_instance.orphan": &ResourceState{
  2891  							Type: "aws_instance",
  2892  							Primary: &InstanceState{
  2893  								ID: "i-789xyz",
  2894  							},
  2895  						},
  2896  						"aws_instance.nottargeted": &ResourceState{
  2897  							Type: "aws_instance",
  2898  							Primary: &InstanceState{
  2899  								ID: "i-abc123",
  2900  							},
  2901  						},
  2902  					},
  2903  				},
  2904  			},
  2905  		},
  2906  		Destroy: true,
  2907  		Targets: []string{"module.child.aws_instance.orphan"},
  2908  	})
  2909  
  2910  	plan, err := ctx.Plan()
  2911  	if err != nil {
  2912  		t.Fatalf("err: %s", err)
  2913  	}
  2914  
  2915  	actual := strings.TrimSpace(plan.String())
  2916  	expected := strings.TrimSpace(`DIFF:
  2917  
  2918  module.child:
  2919    DESTROY: aws_instance.orphan
  2920  
  2921  STATE:
  2922  
  2923  module.child:
  2924    aws_instance.nottargeted:
  2925      ID = i-abc123
  2926    aws_instance.orphan:
  2927      ID = i-789xyz
  2928  `)
  2929  	if actual != expected {
  2930  		t.Fatalf("expected:\n%s\n\ngot:\n%s", expected, actual)
  2931  	}
  2932  }
  2933  
  2934  func TestContext2Plan_targetedModuleUntargetedVariable(t *testing.T) {
  2935  	m := testModule(t, "plan-targeted-module-untargeted-variable")
  2936  	p := testProvider("aws")
  2937  	p.DiffFn = testDiffFn
  2938  	ctx := testContext2(t, &ContextOpts{
  2939  		Module: m,
  2940  		ProviderResolver: ResourceProviderResolverFixed(
  2941  			map[string]ResourceProviderFactory{
  2942  				"aws": testProviderFuncFixed(p),
  2943  			},
  2944  		),
  2945  		Targets: []string{"aws_instance.blue", "module.blue_mod"},
  2946  	})
  2947  
  2948  	plan, err := ctx.Plan()
  2949  	if err != nil {
  2950  		t.Fatalf("err: %s", err)
  2951  	}
  2952  
  2953  	actual := strings.TrimSpace(plan.String())
  2954  	expected := strings.TrimSpace(`
  2955  DIFF:
  2956  
  2957  CREATE: aws_instance.blue
  2958  
  2959  module.blue_mod:
  2960    CREATE: aws_instance.mod
  2961      type:  "" => "aws_instance"
  2962      value: "" => "<computed>"
  2963  
  2964  STATE:
  2965  
  2966  <no state>
  2967  `)
  2968  	if actual != expected {
  2969  		t.Fatalf("expected:\n%s\n\ngot:\n%s", expected, actual)
  2970  	}
  2971  }
  2972  
  2973  // https://github.com/hashicorp/terraform/issues/4515
  2974  func TestContext2Plan_targetedOverTen(t *testing.T) {
  2975  	m := testModule(t, "plan-targeted-over-ten")
  2976  	p := testProvider("aws")
  2977  	p.DiffFn = testDiffFn
  2978  
  2979  	resources := make(map[string]*ResourceState)
  2980  	var expectedState []string
  2981  	for i := 0; i < 13; i++ {
  2982  		key := fmt.Sprintf("aws_instance.foo.%d", i)
  2983  		id := fmt.Sprintf("i-abc%d", i)
  2984  		resources[key] = &ResourceState{
  2985  			Type:    "aws_instance",
  2986  			Primary: &InstanceState{ID: id},
  2987  		}
  2988  		expectedState = append(expectedState,
  2989  			fmt.Sprintf("%s:\n  ID = %s\n", key, id))
  2990  	}
  2991  	ctx := testContext2(t, &ContextOpts{
  2992  		Module: m,
  2993  		ProviderResolver: ResourceProviderResolverFixed(
  2994  			map[string]ResourceProviderFactory{
  2995  				"aws": testProviderFuncFixed(p),
  2996  			},
  2997  		),
  2998  		State: &State{
  2999  			Modules: []*ModuleState{
  3000  				&ModuleState{
  3001  					Path:      rootModulePath,
  3002  					Resources: resources,
  3003  				},
  3004  			},
  3005  		},
  3006  		Targets: []string{"aws_instance.foo[1]"},
  3007  	})
  3008  
  3009  	plan, err := ctx.Plan()
  3010  	if err != nil {
  3011  		t.Fatalf("err: %s", err)
  3012  	}
  3013  
  3014  	actual := strings.TrimSpace(plan.String())
  3015  	sort.Strings(expectedState)
  3016  	expected := strings.TrimSpace(`
  3017  DIFF:
  3018  
  3019  
  3020  
  3021  STATE:
  3022  
  3023  aws_instance.foo.0:
  3024    ID = i-abc0
  3025  aws_instance.foo.1:
  3026    ID = i-abc1
  3027  aws_instance.foo.2:
  3028    ID = i-abc2
  3029  aws_instance.foo.3:
  3030    ID = i-abc3
  3031  aws_instance.foo.4:
  3032    ID = i-abc4
  3033  aws_instance.foo.5:
  3034    ID = i-abc5
  3035  aws_instance.foo.6:
  3036    ID = i-abc6
  3037  aws_instance.foo.7:
  3038    ID = i-abc7
  3039  aws_instance.foo.8:
  3040    ID = i-abc8
  3041  aws_instance.foo.9:
  3042    ID = i-abc9
  3043  aws_instance.foo.10:
  3044    ID = i-abc10
  3045  aws_instance.foo.11:
  3046    ID = i-abc11
  3047  aws_instance.foo.12:
  3048    ID = i-abc12
  3049  	`)
  3050  	if actual != expected {
  3051  		t.Fatalf("expected:\n%s\n\ngot:\n%s", expected, actual)
  3052  	}
  3053  }
  3054  
  3055  func TestContext2Plan_provider(t *testing.T) {
  3056  	m := testModule(t, "plan-provider")
  3057  	p := testProvider("aws")
  3058  	p.DiffFn = testDiffFn
  3059  
  3060  	var value interface{}
  3061  	p.ConfigureFn = func(c *ResourceConfig) error {
  3062  		value, _ = c.Get("foo")
  3063  		return nil
  3064  	}
  3065  
  3066  	ctx := testContext2(t, &ContextOpts{
  3067  		Module: m,
  3068  		ProviderResolver: ResourceProviderResolverFixed(
  3069  			map[string]ResourceProviderFactory{
  3070  				"aws": testProviderFuncFixed(p),
  3071  			},
  3072  		),
  3073  		Variables: map[string]interface{}{
  3074  			"foo": "bar",
  3075  		},
  3076  	})
  3077  
  3078  	if _, err := ctx.Plan(); err != nil {
  3079  		t.Fatalf("err: %s", err)
  3080  	}
  3081  
  3082  	if value != "bar" {
  3083  		t.Fatalf("bad: %#v", value)
  3084  	}
  3085  }
  3086  
  3087  func TestContext2Plan_varListErr(t *testing.T) {
  3088  	m := testModule(t, "plan-var-list-err")
  3089  	p := testProvider("aws")
  3090  	ctx := testContext2(t, &ContextOpts{
  3091  		Module: m,
  3092  		ProviderResolver: ResourceProviderResolverFixed(
  3093  			map[string]ResourceProviderFactory{
  3094  				"aws": testProviderFuncFixed(p),
  3095  			},
  3096  		),
  3097  	})
  3098  
  3099  	_, err := ctx.Plan()
  3100  
  3101  	if err == nil {
  3102  		t.Fatal("should error")
  3103  	}
  3104  }
  3105  
  3106  func TestContext2Plan_ignoreChanges(t *testing.T) {
  3107  	m := testModule(t, "plan-ignore-changes")
  3108  	p := testProvider("aws")
  3109  	p.DiffFn = testDiffFn
  3110  	s := &State{
  3111  		Modules: []*ModuleState{
  3112  			&ModuleState{
  3113  				Path: rootModulePath,
  3114  				Resources: map[string]*ResourceState{
  3115  					"aws_instance.foo": &ResourceState{
  3116  						Type: "aws_instance",
  3117  						Primary: &InstanceState{
  3118  							ID:         "bar",
  3119  							Attributes: map[string]string{"ami": "ami-abcd1234"},
  3120  						},
  3121  					},
  3122  				},
  3123  			},
  3124  		},
  3125  	}
  3126  	ctx := testContext2(t, &ContextOpts{
  3127  		Module: m,
  3128  		ProviderResolver: ResourceProviderResolverFixed(
  3129  			map[string]ResourceProviderFactory{
  3130  				"aws": testProviderFuncFixed(p),
  3131  			},
  3132  		),
  3133  		Variables: map[string]interface{}{
  3134  			"foo": "ami-1234abcd",
  3135  		},
  3136  		State: s,
  3137  	})
  3138  
  3139  	plan, err := ctx.Plan()
  3140  	if err != nil {
  3141  		t.Fatalf("err: %s", err)
  3142  	}
  3143  
  3144  	if len(plan.Diff.RootModule().Resources) < 1 {
  3145  		t.Fatalf("bad: %#v", plan.Diff.RootModule().Resources)
  3146  	}
  3147  
  3148  	actual := strings.TrimSpace(plan.String())
  3149  	expected := strings.TrimSpace(testTerraformPlanIgnoreChangesStr)
  3150  	if actual != expected {
  3151  		t.Fatalf("bad:\n%s\n\nexpected\n\n%s", actual, expected)
  3152  	}
  3153  }
  3154  
  3155  func TestContext2Plan_ignoreChangesWildcard(t *testing.T) {
  3156  	m := testModule(t, "plan-ignore-changes-wildcard")
  3157  	p := testProvider("aws")
  3158  	p.DiffFn = testDiffFn
  3159  	s := &State{
  3160  		Modules: []*ModuleState{
  3161  			&ModuleState{
  3162  				Path: rootModulePath,
  3163  				Resources: map[string]*ResourceState{
  3164  					"aws_instance.foo": &ResourceState{
  3165  						Type: "aws_instance",
  3166  						Primary: &InstanceState{
  3167  							ID: "bar",
  3168  							Attributes: map[string]string{
  3169  								"ami":           "ami-abcd1234",
  3170  								"instance_type": "t2.micro",
  3171  							},
  3172  						},
  3173  					},
  3174  				},
  3175  			},
  3176  		},
  3177  	}
  3178  	ctx := testContext2(t, &ContextOpts{
  3179  		Module: m,
  3180  		ProviderResolver: ResourceProviderResolverFixed(
  3181  			map[string]ResourceProviderFactory{
  3182  				"aws": testProviderFuncFixed(p),
  3183  			},
  3184  		),
  3185  		Variables: map[string]interface{}{
  3186  			"foo": "ami-1234abcd",
  3187  			"bar": "t2.small",
  3188  		},
  3189  		State: s,
  3190  	})
  3191  
  3192  	plan, err := ctx.Plan()
  3193  	if err != nil {
  3194  		t.Fatalf("err: %s", err)
  3195  	}
  3196  
  3197  	if len(plan.Diff.RootModule().Resources) > 0 {
  3198  		t.Fatalf("bad: %#v", plan.Diff.RootModule().Resources)
  3199  	}
  3200  
  3201  	actual := strings.TrimSpace(plan.String())
  3202  	expected := strings.TrimSpace(testTerraformPlanIgnoreChangesWildcardStr)
  3203  	if actual != expected {
  3204  		t.Fatalf("bad:\n%s\n\nexpected\n\n%s", actual, expected)
  3205  	}
  3206  }
  3207  
  3208  func TestContext2Plan_moduleMapLiteral(t *testing.T) {
  3209  	m := testModule(t, "plan-module-map-literal")
  3210  	p := testProvider("aws")
  3211  	p.ApplyFn = testApplyFn
  3212  	p.DiffFn = func(i *InstanceInfo, s *InstanceState, c *ResourceConfig) (*InstanceDiff, error) {
  3213  		// Here we verify that both the populated and empty map literals made it
  3214  		// through to the resource attributes
  3215  		val, _ := c.Get("tags")
  3216  		m, ok := val.(map[string]interface{})
  3217  		if !ok {
  3218  			t.Fatalf("Tags attr not map: %#v", val)
  3219  		}
  3220  		if m["foo"] != "bar" {
  3221  			t.Fatalf("Bad value in tags attr: %#v", m)
  3222  		}
  3223  		{
  3224  			val, _ := c.Get("meta")
  3225  			m, ok := val.(map[string]interface{})
  3226  			if !ok {
  3227  				t.Fatalf("Meta attr not map: %#v", val)
  3228  			}
  3229  			if len(m) != 0 {
  3230  				t.Fatalf("Meta attr not empty: %#v", val)
  3231  			}
  3232  		}
  3233  		return nil, nil
  3234  	}
  3235  	ctx := testContext2(t, &ContextOpts{
  3236  		Module: m,
  3237  		ProviderResolver: ResourceProviderResolverFixed(
  3238  			map[string]ResourceProviderFactory{
  3239  				"aws": testProviderFuncFixed(p),
  3240  			},
  3241  		),
  3242  	})
  3243  
  3244  	if _, err := ctx.Plan(); err != nil {
  3245  		t.Fatalf("err: %s", err)
  3246  	}
  3247  }
  3248  
  3249  func TestContext2Plan_computedValueInMap(t *testing.T) {
  3250  	m := testModule(t, "plan-computed-value-in-map")
  3251  	p := testProvider("aws")
  3252  	p.DiffFn = func(info *InstanceInfo, state *InstanceState, c *ResourceConfig) (*InstanceDiff, error) {
  3253  		switch info.Type {
  3254  		case "aws_computed_source":
  3255  			return &InstanceDiff{
  3256  				Attributes: map[string]*ResourceAttrDiff{
  3257  					"computed_read_only": &ResourceAttrDiff{
  3258  						NewComputed: true,
  3259  					},
  3260  				},
  3261  			}, nil
  3262  		}
  3263  
  3264  		return testDiffFn(info, state, c)
  3265  	}
  3266  	ctx := testContext2(t, &ContextOpts{
  3267  		Module: m,
  3268  		ProviderResolver: ResourceProviderResolverFixed(
  3269  			map[string]ResourceProviderFactory{
  3270  				"aws": testProviderFuncFixed(p),
  3271  			},
  3272  		),
  3273  	})
  3274  
  3275  	if _, err := ctx.Plan(); err != nil {
  3276  		t.Fatalf("err: %s", err)
  3277  	}
  3278  
  3279  	plan, err := ctx.Plan()
  3280  	if err != nil {
  3281  		t.Fatalf("err: %s", err)
  3282  	}
  3283  
  3284  	actual := strings.TrimSpace(plan.String())
  3285  	expected := strings.TrimSpace(testTerraformPlanComputedValueInMap)
  3286  	if actual != expected {
  3287  		t.Fatalf("bad:\n%s\n\nexpected\n\n%s", actual, expected)
  3288  	}
  3289  }
  3290  
  3291  func TestContext2Plan_moduleVariableFromSplat(t *testing.T) {
  3292  	m := testModule(t, "plan-module-variable-from-splat")
  3293  	p := testProvider("aws")
  3294  	p.DiffFn = testDiffFn
  3295  	ctx := testContext2(t, &ContextOpts{
  3296  		Module: m,
  3297  		ProviderResolver: ResourceProviderResolverFixed(
  3298  			map[string]ResourceProviderFactory{
  3299  				"aws": testProviderFuncFixed(p),
  3300  			},
  3301  		),
  3302  	})
  3303  
  3304  	if _, err := ctx.Plan(); err != nil {
  3305  		t.Fatalf("err: %s", err)
  3306  	}
  3307  
  3308  	plan, err := ctx.Plan()
  3309  	if err != nil {
  3310  		t.Fatalf("err: %s", err)
  3311  	}
  3312  
  3313  	actual := strings.TrimSpace(plan.String())
  3314  	expected := strings.TrimSpace(testTerraformPlanModuleVariableFromSplat)
  3315  	if actual != expected {
  3316  		t.Fatalf("bad:\n%s\n\nexpected\n\n%s", actual, expected)
  3317  	}
  3318  }
  3319  
  3320  func TestContext2Plan_createBeforeDestroy_depends_datasource(t *testing.T) {
  3321  	m := testModule(t, "plan-cdb-depends-datasource")
  3322  	p := testProvider("aws")
  3323  	p.DiffFn = testDiffFn
  3324  	ctx := testContext2(t, &ContextOpts{
  3325  		Module: m,
  3326  		ProviderResolver: ResourceProviderResolverFixed(
  3327  			map[string]ResourceProviderFactory{
  3328  				"aws": testProviderFuncFixed(p),
  3329  			},
  3330  		),
  3331  	})
  3332  
  3333  	plan, err := ctx.Plan()
  3334  	if err != nil {
  3335  		t.Fatalf("err: %s", err)
  3336  	}
  3337  
  3338  	if got := len(plan.Diff.Modules); got != 1 {
  3339  		t.Fatalf("got %d modules; want 1", got)
  3340  	}
  3341  
  3342  	moduleDiff := plan.Diff.Modules[0]
  3343  
  3344  	if _, ok := moduleDiff.Resources["aws_instance.foo.0"]; !ok {
  3345  		t.Fatalf("missing diff for aws_instance.foo.0")
  3346  	}
  3347  	if _, ok := moduleDiff.Resources["aws_instance.foo.1"]; !ok {
  3348  		t.Fatalf("missing diff for aws_instance.foo.1")
  3349  	}
  3350  	if _, ok := moduleDiff.Resources["data.aws_vpc.bar.0"]; !ok {
  3351  		t.Fatalf("missing diff for data.aws_vpc.bar.0")
  3352  	}
  3353  	if _, ok := moduleDiff.Resources["data.aws_vpc.bar.1"]; !ok {
  3354  		t.Fatalf("missing diff for data.aws_vpc.bar.1")
  3355  	}
  3356  }
  3357  
  3358  // interpolated lists need to be stored in the original order.
  3359  func TestContext2Plan_listOrder(t *testing.T) {
  3360  	m := testModule(t, "plan-list-order")
  3361  	p := testProvider("aws")
  3362  	p.ApplyFn = testApplyFn
  3363  	p.DiffFn = testDiffFn
  3364  	ctx := testContext2(t, &ContextOpts{
  3365  		Module: m,
  3366  		ProviderResolver: ResourceProviderResolverFixed(
  3367  			map[string]ResourceProviderFactory{
  3368  				"aws": testProviderFuncFixed(p),
  3369  			},
  3370  		),
  3371  	})
  3372  
  3373  	plan, err := ctx.Plan()
  3374  	if err != nil {
  3375  		t.Fatalf("err: %s", err)
  3376  	}
  3377  
  3378  	rDiffs := plan.Diff.Modules[0].Resources
  3379  	rDiffA := rDiffs["aws_instance.a"]
  3380  	rDiffB := rDiffs["aws_instance.b"]
  3381  
  3382  	if !rDiffA.Equal(rDiffB) {
  3383  		t.Fatal("aws_instance.a and aws_instance.b diffs should match:\n", plan)
  3384  	}
  3385  }
  3386  
  3387  // Make sure ignore-changes doesn't interfere with set/list/map diffs.
  3388  // If a resource was being replaced by a RequiresNew attribute that gets
  3389  // ignored, we need to filter the diff properly to properly update rather than
  3390  // replace.
  3391  func TestContext2Plan_ignoreChangesWithFlatmaps(t *testing.T) {
  3392  	m := testModule(t, "plan-ignore-changes-with-flatmaps")
  3393  	p := testProvider("aws")
  3394  	p.DiffFn = testDiffFn
  3395  	s := &State{
  3396  		Modules: []*ModuleState{
  3397  			&ModuleState{
  3398  				Path: rootModulePath,
  3399  				Resources: map[string]*ResourceState{
  3400  					"aws_instance.foo": &ResourceState{
  3401  						Type: "aws_instance",
  3402  						Primary: &InstanceState{
  3403  							ID: "bar",
  3404  							Attributes: map[string]string{
  3405  								"user_data":   "x",
  3406  								"require_new": "",
  3407  								"set.#":       "1",
  3408  								"set.0.a":     "1",
  3409  								"lst.#":       "1",
  3410  								"lst.0":       "j",
  3411  							},
  3412  						},
  3413  					},
  3414  				},
  3415  			},
  3416  		},
  3417  	}
  3418  	ctx := testContext2(t, &ContextOpts{
  3419  		Module: m,
  3420  		ProviderResolver: ResourceProviderResolverFixed(
  3421  			map[string]ResourceProviderFactory{
  3422  				"aws": testProviderFuncFixed(p),
  3423  			},
  3424  		),
  3425  		State: s,
  3426  	})
  3427  
  3428  	plan, err := ctx.Plan()
  3429  	if err != nil {
  3430  		t.Fatalf("err: %s", err)
  3431  	}
  3432  
  3433  	actual := strings.TrimSpace(plan.Diff.String())
  3434  	expected := strings.TrimSpace(testTFPlanDiffIgnoreChangesWithFlatmaps)
  3435  	if actual != expected {
  3436  		t.Fatalf("bad:\n%s\n\nexpected\n\n%s", actual, expected)
  3437  	}
  3438  }
  3439  
  3440  // TestContext2Plan_resourceNestedCount ensures resource sets that depend on
  3441  // the count of another resource set (ie: count of a data source that depends
  3442  // on another data source's instance count - data.x.foo.*.id) get properly
  3443  // normalized to the indexes they should be. This case comes up when there is
  3444  // an existing state (after an initial apply).
  3445  func TestContext2Plan_resourceNestedCount(t *testing.T) {
  3446  	m := testModule(t, "nested-resource-count-plan")
  3447  	p := testProvider("aws")
  3448  	p.DiffFn = testDiffFn
  3449  	p.RefreshFn = func(i *InstanceInfo, is *InstanceState) (*InstanceState, error) {
  3450  		return is, nil
  3451  	}
  3452  	s := &State{
  3453  		Modules: []*ModuleState{
  3454  			&ModuleState{
  3455  				Path: rootModulePath,
  3456  				Resources: map[string]*ResourceState{
  3457  					"aws_instance.foo.0": &ResourceState{
  3458  						Type: "aws_instance",
  3459  						Primary: &InstanceState{
  3460  							ID: "foo0",
  3461  							Attributes: map[string]string{
  3462  								"id": "foo0",
  3463  							},
  3464  						},
  3465  					},
  3466  					"aws_instance.foo.1": &ResourceState{
  3467  						Type: "aws_instance",
  3468  						Primary: &InstanceState{
  3469  							ID: "foo1",
  3470  							Attributes: map[string]string{
  3471  								"id": "foo1",
  3472  							},
  3473  						},
  3474  					},
  3475  					"aws_instance.bar.0": &ResourceState{
  3476  						Type:         "aws_instance",
  3477  						Dependencies: []string{"aws_instance.foo.*"},
  3478  						Primary: &InstanceState{
  3479  							ID: "bar0",
  3480  							Attributes: map[string]string{
  3481  								"id": "bar0",
  3482  							},
  3483  						},
  3484  					},
  3485  					"aws_instance.bar.1": &ResourceState{
  3486  						Type:         "aws_instance",
  3487  						Dependencies: []string{"aws_instance.foo.*"},
  3488  						Primary: &InstanceState{
  3489  							ID: "bar1",
  3490  							Attributes: map[string]string{
  3491  								"id": "bar1",
  3492  							},
  3493  						},
  3494  					},
  3495  					"aws_instance.baz.0": &ResourceState{
  3496  						Type:         "aws_instance",
  3497  						Dependencies: []string{"aws_instance.bar.*"},
  3498  						Primary: &InstanceState{
  3499  							ID: "baz0",
  3500  							Attributes: map[string]string{
  3501  								"id": "baz0",
  3502  							},
  3503  						},
  3504  					},
  3505  					"aws_instance.baz.1": &ResourceState{
  3506  						Type:         "aws_instance",
  3507  						Dependencies: []string{"aws_instance.bar.*"},
  3508  						Primary: &InstanceState{
  3509  							ID: "baz1",
  3510  							Attributes: map[string]string{
  3511  								"id": "baz1",
  3512  							},
  3513  						},
  3514  					},
  3515  				},
  3516  			},
  3517  		},
  3518  	}
  3519  	ctx := testContext2(t, &ContextOpts{
  3520  		Module: m,
  3521  		ProviderResolver: ResourceProviderResolverFixed(
  3522  			map[string]ResourceProviderFactory{
  3523  				"aws": testProviderFuncFixed(p),
  3524  			},
  3525  		),
  3526  		State: s,
  3527  	})
  3528  
  3529  	w, e := ctx.Validate()
  3530  	if len(w) > 0 {
  3531  		t.Fatalf("warnings generated on validate: %#v", w)
  3532  	}
  3533  	if len(e) > 0 {
  3534  		t.Fatalf("errors generated on validate: %#v", e)
  3535  	}
  3536  
  3537  	_, err := ctx.Refresh()
  3538  	if err != nil {
  3539  		t.Fatalf("refresh err: %s", err)
  3540  	}
  3541  
  3542  	plan, err := ctx.Plan()
  3543  	if err != nil {
  3544  		t.Fatalf("plan err: %s", err)
  3545  	}
  3546  
  3547  	actual := strings.TrimSpace(plan.String())
  3548  	expected := strings.TrimSpace(`
  3549  DIFF:
  3550  
  3551  
  3552  
  3553  STATE:
  3554  
  3555  aws_instance.bar.0:
  3556    ID = bar0
  3557  
  3558    Dependencies:
  3559      aws_instance.foo.*
  3560  aws_instance.bar.1:
  3561    ID = bar1
  3562  
  3563    Dependencies:
  3564      aws_instance.foo.*
  3565  aws_instance.baz.0:
  3566    ID = baz0
  3567  
  3568    Dependencies:
  3569      aws_instance.bar.*
  3570  aws_instance.baz.1:
  3571    ID = baz1
  3572  
  3573    Dependencies:
  3574      aws_instance.bar.*
  3575  aws_instance.foo.0:
  3576    ID = foo0
  3577  aws_instance.foo.1:
  3578    ID = foo1
  3579  `)
  3580  	if actual != expected {
  3581  		t.Fatalf("bad:\n%s\n\nexpected\n\n%s", actual, expected)
  3582  	}
  3583  }