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