github.com/inge4pres/terraform@v0.7.5-0.20160930053151-bd083f84f376/terraform/context_plan_test.go (about)

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