github.com/recobe182/terraform@v0.8.5-0.20170117231232-49ab22a935b7/terraform/context_plan_test.go (about)

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