github.com/xsb/terraform@v0.6.13-0.20160314145438-fe415c2f09d7/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]string{
    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]string{
   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]string{
   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_moduleVarComputed(t *testing.T) {
   630  	m := testModule(t, "plan-module-var-computed")
   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  	plan, err := ctx.Plan()
   641  	if err != nil {
   642  		t.Fatalf("err: %s", err)
   643  	}
   644  
   645  	actual := strings.TrimSpace(plan.String())
   646  	expected := strings.TrimSpace(testTerraformPlanModuleVarComputedStr)
   647  	if actual != expected {
   648  		t.Fatalf("bad:\n%s", actual)
   649  	}
   650  }
   651  
   652  func TestContext2Plan_nil(t *testing.T) {
   653  	m := testModule(t, "plan-nil")
   654  	p := testProvider("aws")
   655  	p.DiffFn = testDiffFn
   656  	ctx := testContext2(t, &ContextOpts{
   657  		Module: m,
   658  		Providers: map[string]ResourceProviderFactory{
   659  			"aws": testProviderFuncFixed(p),
   660  		},
   661  		State: &State{
   662  			Modules: []*ModuleState{
   663  				&ModuleState{
   664  					Path: rootModulePath,
   665  					Resources: map[string]*ResourceState{
   666  						"aws_instance.foo": &ResourceState{
   667  							Type: "aws_instance",
   668  							Primary: &InstanceState{
   669  								ID: "bar",
   670  							},
   671  						},
   672  					},
   673  				},
   674  			},
   675  		},
   676  	})
   677  
   678  	plan, err := ctx.Plan()
   679  	if err != nil {
   680  		t.Fatalf("err: %s", err)
   681  	}
   682  	if len(plan.Diff.RootModule().Resources) != 0 {
   683  		t.Fatalf("bad: %#v", plan.Diff.RootModule().Resources)
   684  	}
   685  }
   686  
   687  func TestContext2Plan_preventDestroy_bad(t *testing.T) {
   688  	m := testModule(t, "plan-prevent-destroy-bad")
   689  	p := testProvider("aws")
   690  	p.DiffFn = testDiffFn
   691  	ctx := testContext2(t, &ContextOpts{
   692  		Module: m,
   693  		Providers: map[string]ResourceProviderFactory{
   694  			"aws": testProviderFuncFixed(p),
   695  		},
   696  		State: &State{
   697  			Modules: []*ModuleState{
   698  				&ModuleState{
   699  					Path: rootModulePath,
   700  					Resources: map[string]*ResourceState{
   701  						"aws_instance.foo": &ResourceState{
   702  							Type: "aws_instance",
   703  							Primary: &InstanceState{
   704  								ID: "i-abc123",
   705  							},
   706  						},
   707  					},
   708  				},
   709  			},
   710  		},
   711  	})
   712  
   713  	plan, err := ctx.Plan()
   714  
   715  	expectedErr := "aws_instance.foo: the plan would destroy"
   716  	if !strings.Contains(fmt.Sprintf("%s", err), expectedErr) {
   717  		t.Fatalf("expected err would contain %q\nerr: %s\nplan: %s",
   718  			expectedErr, err, plan)
   719  	}
   720  }
   721  
   722  func TestContext2Plan_preventDestroy_good(t *testing.T) {
   723  	m := testModule(t, "plan-prevent-destroy-good")
   724  	p := testProvider("aws")
   725  	p.DiffFn = testDiffFn
   726  	ctx := testContext2(t, &ContextOpts{
   727  		Module: m,
   728  		Providers: map[string]ResourceProviderFactory{
   729  			"aws": testProviderFuncFixed(p),
   730  		},
   731  		State: &State{
   732  			Modules: []*ModuleState{
   733  				&ModuleState{
   734  					Path: rootModulePath,
   735  					Resources: map[string]*ResourceState{
   736  						"aws_instance.foo": &ResourceState{
   737  							Type: "aws_instance",
   738  							Primary: &InstanceState{
   739  								ID: "i-abc123",
   740  							},
   741  						},
   742  					},
   743  				},
   744  			},
   745  		},
   746  	})
   747  
   748  	plan, err := ctx.Plan()
   749  	if err != nil {
   750  		t.Fatalf("err: %s", err)
   751  	}
   752  	if !plan.Diff.Empty() {
   753  		t.Fatalf("Expected empty plan, got %s", plan.String())
   754  	}
   755  }
   756  
   757  func TestContext2Plan_preventDestroy_destroyPlan(t *testing.T) {
   758  	m := testModule(t, "plan-prevent-destroy-good")
   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  		State: &State{
   767  			Modules: []*ModuleState{
   768  				&ModuleState{
   769  					Path: rootModulePath,
   770  					Resources: map[string]*ResourceState{
   771  						"aws_instance.foo": &ResourceState{
   772  							Type: "aws_instance",
   773  							Primary: &InstanceState{
   774  								ID: "i-abc123",
   775  							},
   776  						},
   777  					},
   778  				},
   779  			},
   780  		},
   781  		Destroy: true,
   782  	})
   783  
   784  	plan, err := ctx.Plan()
   785  
   786  	expectedErr := "aws_instance.foo: the plan would destroy"
   787  	if !strings.Contains(fmt.Sprintf("%s", err), expectedErr) {
   788  		t.Fatalf("expected err would contain %q\nerr: %s\nplan: %s",
   789  			expectedErr, err, plan)
   790  	}
   791  }
   792  
   793  func TestContext2Plan_computed(t *testing.T) {
   794  	m := testModule(t, "plan-computed")
   795  	p := testProvider("aws")
   796  	p.DiffFn = testDiffFn
   797  	ctx := testContext2(t, &ContextOpts{
   798  		Module: m,
   799  		Providers: map[string]ResourceProviderFactory{
   800  			"aws": testProviderFuncFixed(p),
   801  		},
   802  	})
   803  
   804  	plan, err := ctx.Plan()
   805  	if err != nil {
   806  		t.Fatalf("err: %s", err)
   807  	}
   808  
   809  	actual := strings.TrimSpace(plan.String())
   810  	expected := strings.TrimSpace(testTerraformPlanComputedStr)
   811  	if actual != expected {
   812  		t.Fatalf("bad:\n%s", actual)
   813  	}
   814  }
   815  
   816  func TestContext2Plan_computedList(t *testing.T) {
   817  	m := testModule(t, "plan-computed-list")
   818  	p := testProvider("aws")
   819  	p.DiffFn = testDiffFn
   820  	ctx := testContext2(t, &ContextOpts{
   821  		Module: m,
   822  		Providers: map[string]ResourceProviderFactory{
   823  			"aws": testProviderFuncFixed(p),
   824  		},
   825  	})
   826  
   827  	plan, err := ctx.Plan()
   828  	if err != nil {
   829  		t.Fatalf("err: %s", err)
   830  	}
   831  
   832  	actual := strings.TrimSpace(plan.String())
   833  	expected := strings.TrimSpace(testTerraformPlanComputedListStr)
   834  	if actual != expected {
   835  		t.Fatalf("bad:\n%s", actual)
   836  	}
   837  }
   838  
   839  func TestContext2Plan_count(t *testing.T) {
   840  	m := testModule(t, "plan-count")
   841  	p := testProvider("aws")
   842  	p.DiffFn = testDiffFn
   843  	ctx := testContext2(t, &ContextOpts{
   844  		Module: m,
   845  		Providers: map[string]ResourceProviderFactory{
   846  			"aws": testProviderFuncFixed(p),
   847  		},
   848  	})
   849  
   850  	plan, err := ctx.Plan()
   851  	if err != nil {
   852  		t.Fatalf("err: %s", err)
   853  	}
   854  
   855  	if len(plan.Diff.RootModule().Resources) < 6 {
   856  		t.Fatalf("bad: %#v", plan.Diff.RootModule().Resources)
   857  	}
   858  
   859  	actual := strings.TrimSpace(plan.String())
   860  	expected := strings.TrimSpace(testTerraformPlanCountStr)
   861  	if actual != expected {
   862  		t.Fatalf("bad:\n%s", actual)
   863  	}
   864  }
   865  
   866  func TestContext2Plan_countComputed(t *testing.T) {
   867  	m := testModule(t, "plan-count-computed")
   868  	p := testProvider("aws")
   869  	p.DiffFn = testDiffFn
   870  	ctx := testContext2(t, &ContextOpts{
   871  		Module: m,
   872  		Providers: map[string]ResourceProviderFactory{
   873  			"aws": testProviderFuncFixed(p),
   874  		},
   875  	})
   876  
   877  	_, err := ctx.Plan()
   878  	if err == nil {
   879  		t.Fatal("should error")
   880  	}
   881  }
   882  
   883  func TestContext2Plan_countIndex(t *testing.T) {
   884  	m := testModule(t, "plan-count-index")
   885  	p := testProvider("aws")
   886  	p.DiffFn = testDiffFn
   887  	ctx := testContext2(t, &ContextOpts{
   888  		Module: m,
   889  		Providers: map[string]ResourceProviderFactory{
   890  			"aws": testProviderFuncFixed(p),
   891  		},
   892  	})
   893  
   894  	plan, err := ctx.Plan()
   895  	if err != nil {
   896  		t.Fatalf("err: %s", err)
   897  	}
   898  
   899  	actual := strings.TrimSpace(plan.String())
   900  	expected := strings.TrimSpace(testTerraformPlanCountIndexStr)
   901  	if actual != expected {
   902  		t.Fatalf("bad:\n%s", actual)
   903  	}
   904  }
   905  
   906  func TestContext2Plan_countIndexZero(t *testing.T) {
   907  	m := testModule(t, "plan-count-index-zero")
   908  	p := testProvider("aws")
   909  	p.DiffFn = testDiffFn
   910  	ctx := testContext2(t, &ContextOpts{
   911  		Module: m,
   912  		Providers: map[string]ResourceProviderFactory{
   913  			"aws": testProviderFuncFixed(p),
   914  		},
   915  	})
   916  
   917  	plan, err := ctx.Plan()
   918  	if err != nil {
   919  		t.Fatalf("err: %s", err)
   920  	}
   921  
   922  	actual := strings.TrimSpace(plan.String())
   923  	expected := strings.TrimSpace(testTerraformPlanCountIndexZeroStr)
   924  	if actual != expected {
   925  		t.Fatalf("bad:\n%s", actual)
   926  	}
   927  }
   928  
   929  func TestContext2Plan_countVar(t *testing.T) {
   930  	m := testModule(t, "plan-count-var")
   931  	p := testProvider("aws")
   932  	p.DiffFn = testDiffFn
   933  	ctx := testContext2(t, &ContextOpts{
   934  		Module: m,
   935  		Providers: map[string]ResourceProviderFactory{
   936  			"aws": testProviderFuncFixed(p),
   937  		},
   938  		Variables: map[string]string{
   939  			"count": "3",
   940  		},
   941  	})
   942  
   943  	plan, err := ctx.Plan()
   944  	if err != nil {
   945  		t.Fatalf("err: %s", err)
   946  	}
   947  
   948  	actual := strings.TrimSpace(plan.String())
   949  	expected := strings.TrimSpace(testTerraformPlanCountVarStr)
   950  	if actual != expected {
   951  		t.Fatalf("bad:\n%s", actual)
   952  	}
   953  }
   954  
   955  func TestContext2Plan_countZero(t *testing.T) {
   956  	m := testModule(t, "plan-count-zero")
   957  	p := testProvider("aws")
   958  	p.DiffFn = testDiffFn
   959  	ctx := testContext2(t, &ContextOpts{
   960  		Module: m,
   961  		Providers: map[string]ResourceProviderFactory{
   962  			"aws": testProviderFuncFixed(p),
   963  		},
   964  	})
   965  
   966  	plan, err := ctx.Plan()
   967  	if err != nil {
   968  		t.Fatalf("err: %s", err)
   969  	}
   970  
   971  	actual := strings.TrimSpace(plan.String())
   972  	expected := strings.TrimSpace(testTerraformPlanCountZeroStr)
   973  	if actual != expected {
   974  		t.Fatalf("bad:\n%s", actual)
   975  	}
   976  }
   977  
   978  func TestContext2Plan_countOneIndex(t *testing.T) {
   979  	m := testModule(t, "plan-count-one-index")
   980  	p := testProvider("aws")
   981  	p.DiffFn = testDiffFn
   982  	ctx := testContext2(t, &ContextOpts{
   983  		Module: m,
   984  		Providers: map[string]ResourceProviderFactory{
   985  			"aws": testProviderFuncFixed(p),
   986  		},
   987  	})
   988  
   989  	plan, err := ctx.Plan()
   990  	if err != nil {
   991  		t.Fatalf("err: %s", err)
   992  	}
   993  
   994  	actual := strings.TrimSpace(plan.String())
   995  	expected := strings.TrimSpace(testTerraformPlanCountOneIndexStr)
   996  	if actual != expected {
   997  		t.Fatalf("bad:\n%s", actual)
   998  	}
   999  }
  1000  
  1001  func TestContext2Plan_countDecreaseToOne(t *testing.T) {
  1002  	m := testModule(t, "plan-count-dec")
  1003  	p := testProvider("aws")
  1004  	p.DiffFn = testDiffFn
  1005  	s := &State{
  1006  		Modules: []*ModuleState{
  1007  			&ModuleState{
  1008  				Path: rootModulePath,
  1009  				Resources: map[string]*ResourceState{
  1010  					"aws_instance.foo.0": &ResourceState{
  1011  						Type: "aws_instance",
  1012  						Primary: &InstanceState{
  1013  							ID: "bar",
  1014  							Attributes: map[string]string{
  1015  								"foo":  "foo",
  1016  								"type": "aws_instance",
  1017  							},
  1018  						},
  1019  					},
  1020  					"aws_instance.foo.1": &ResourceState{
  1021  						Type: "aws_instance",
  1022  						Primary: &InstanceState{
  1023  							ID: "bar",
  1024  						},
  1025  					},
  1026  					"aws_instance.foo.2": &ResourceState{
  1027  						Type: "aws_instance",
  1028  						Primary: &InstanceState{
  1029  							ID: "bar",
  1030  						},
  1031  					},
  1032  				},
  1033  			},
  1034  		},
  1035  	}
  1036  	ctx := testContext2(t, &ContextOpts{
  1037  		Module: m,
  1038  		Providers: map[string]ResourceProviderFactory{
  1039  			"aws": testProviderFuncFixed(p),
  1040  		},
  1041  		State: s,
  1042  	})
  1043  
  1044  	plan, err := ctx.Plan()
  1045  	if err != nil {
  1046  		t.Fatalf("err: %s", err)
  1047  	}
  1048  
  1049  	actual := strings.TrimSpace(plan.String())
  1050  	expected := strings.TrimSpace(testTerraformPlanCountDecreaseStr)
  1051  	if actual != expected {
  1052  		t.Fatalf("bad:\n%s", actual)
  1053  	}
  1054  }
  1055  
  1056  func TestContext2Plan_countIncreaseFromNotSet(t *testing.T) {
  1057  	m := testModule(t, "plan-count-inc")
  1058  	p := testProvider("aws")
  1059  	p.DiffFn = testDiffFn
  1060  	s := &State{
  1061  		Modules: []*ModuleState{
  1062  			&ModuleState{
  1063  				Path: rootModulePath,
  1064  				Resources: map[string]*ResourceState{
  1065  					"aws_instance.foo": &ResourceState{
  1066  						Type: "aws_instance",
  1067  						Primary: &InstanceState{
  1068  							ID: "bar",
  1069  							Attributes: map[string]string{
  1070  								"foo":  "foo",
  1071  								"type": "aws_instance",
  1072  							},
  1073  						},
  1074  					},
  1075  				},
  1076  			},
  1077  		},
  1078  	}
  1079  	ctx := testContext2(t, &ContextOpts{
  1080  		Module: m,
  1081  		Providers: map[string]ResourceProviderFactory{
  1082  			"aws": testProviderFuncFixed(p),
  1083  		},
  1084  		State: s,
  1085  	})
  1086  
  1087  	plan, err := ctx.Plan()
  1088  	if err != nil {
  1089  		t.Fatalf("err: %s", err)
  1090  	}
  1091  
  1092  	actual := strings.TrimSpace(plan.String())
  1093  	expected := strings.TrimSpace(testTerraformPlanCountIncreaseStr)
  1094  	if actual != expected {
  1095  		t.Fatalf("bad:\n%s", actual)
  1096  	}
  1097  }
  1098  
  1099  func TestContext2Plan_countIncreaseFromOne(t *testing.T) {
  1100  	m := testModule(t, "plan-count-inc")
  1101  	p := testProvider("aws")
  1102  	p.DiffFn = testDiffFn
  1103  	s := &State{
  1104  		Modules: []*ModuleState{
  1105  			&ModuleState{
  1106  				Path: rootModulePath,
  1107  				Resources: map[string]*ResourceState{
  1108  					"aws_instance.foo.0": &ResourceState{
  1109  						Type: "aws_instance",
  1110  						Primary: &InstanceState{
  1111  							ID: "bar",
  1112  							Attributes: map[string]string{
  1113  								"foo":  "foo",
  1114  								"type": "aws_instance",
  1115  							},
  1116  						},
  1117  					},
  1118  				},
  1119  			},
  1120  		},
  1121  	}
  1122  	ctx := testContext2(t, &ContextOpts{
  1123  		Module: m,
  1124  		Providers: map[string]ResourceProviderFactory{
  1125  			"aws": testProviderFuncFixed(p),
  1126  		},
  1127  		State: s,
  1128  	})
  1129  
  1130  	plan, err := ctx.Plan()
  1131  	if err != nil {
  1132  		t.Fatalf("err: %s", err)
  1133  	}
  1134  
  1135  	actual := strings.TrimSpace(plan.String())
  1136  	expected := strings.TrimSpace(testTerraformPlanCountIncreaseFromOneStr)
  1137  	if actual != expected {
  1138  		t.Fatalf("bad:\n%s", actual)
  1139  	}
  1140  }
  1141  
  1142  // https://github.com/PeoplePerHour/terraform/pull/11
  1143  //
  1144  // This tests a case where both a "resource" and "resource.0" are in
  1145  // the state file, which apparently is a reasonable backwards compatibility
  1146  // concern found in the above 3rd party repo.
  1147  func TestContext2Plan_countIncreaseFromOneCorrupted(t *testing.T) {
  1148  	m := testModule(t, "plan-count-inc")
  1149  	p := testProvider("aws")
  1150  	p.DiffFn = testDiffFn
  1151  	s := &State{
  1152  		Modules: []*ModuleState{
  1153  			&ModuleState{
  1154  				Path: rootModulePath,
  1155  				Resources: map[string]*ResourceState{
  1156  					"aws_instance.foo": &ResourceState{
  1157  						Type: "aws_instance",
  1158  						Primary: &InstanceState{
  1159  							ID: "bar",
  1160  							Attributes: map[string]string{
  1161  								"foo":  "foo",
  1162  								"type": "aws_instance",
  1163  							},
  1164  						},
  1165  					},
  1166  					"aws_instance.foo.0": &ResourceState{
  1167  						Type: "aws_instance",
  1168  						Primary: &InstanceState{
  1169  							ID: "bar",
  1170  							Attributes: map[string]string{
  1171  								"foo":  "foo",
  1172  								"type": "aws_instance",
  1173  							},
  1174  						},
  1175  					},
  1176  				},
  1177  			},
  1178  		},
  1179  	}
  1180  	ctx := testContext2(t, &ContextOpts{
  1181  		Module: m,
  1182  		Providers: map[string]ResourceProviderFactory{
  1183  			"aws": testProviderFuncFixed(p),
  1184  		},
  1185  		State: s,
  1186  	})
  1187  
  1188  	plan, err := ctx.Plan()
  1189  	if err != nil {
  1190  		t.Fatalf("err: %s", err)
  1191  	}
  1192  
  1193  	actual := strings.TrimSpace(plan.String())
  1194  	expected := strings.TrimSpace(testTerraformPlanCountIncreaseFromOneCorruptedStr)
  1195  	if actual != expected {
  1196  		t.Fatalf("bad:\n%s", actual)
  1197  	}
  1198  }
  1199  
  1200  func TestContext2Plan_destroy(t *testing.T) {
  1201  	m := testModule(t, "plan-destroy")
  1202  	p := testProvider("aws")
  1203  	p.DiffFn = testDiffFn
  1204  	s := &State{
  1205  		Modules: []*ModuleState{
  1206  			&ModuleState{
  1207  				Path: rootModulePath,
  1208  				Resources: map[string]*ResourceState{
  1209  					"aws_instance.one": &ResourceState{
  1210  						Type: "aws_instance",
  1211  						Primary: &InstanceState{
  1212  							ID: "bar",
  1213  						},
  1214  					},
  1215  					"aws_instance.two": &ResourceState{
  1216  						Type: "aws_instance",
  1217  						Primary: &InstanceState{
  1218  							ID: "baz",
  1219  						},
  1220  					},
  1221  				},
  1222  			},
  1223  		},
  1224  	}
  1225  	ctx := testContext2(t, &ContextOpts{
  1226  		Module: m,
  1227  		Providers: map[string]ResourceProviderFactory{
  1228  			"aws": testProviderFuncFixed(p),
  1229  		},
  1230  		State:   s,
  1231  		Destroy: true,
  1232  	})
  1233  
  1234  	plan, err := ctx.Plan()
  1235  	if err != nil {
  1236  		t.Fatalf("err: %s", err)
  1237  	}
  1238  
  1239  	if len(plan.Diff.RootModule().Resources) != 2 {
  1240  		t.Fatalf("bad: %#v", plan.Diff.RootModule().Resources)
  1241  	}
  1242  
  1243  	actual := strings.TrimSpace(plan.String())
  1244  	expected := strings.TrimSpace(testTerraformPlanDestroyStr)
  1245  	if actual != expected {
  1246  		t.Fatalf("bad:\n%s", actual)
  1247  	}
  1248  }
  1249  
  1250  func TestContext2Plan_moduleDestroy(t *testing.T) {
  1251  	m := testModule(t, "plan-module-destroy")
  1252  	p := testProvider("aws")
  1253  	p.DiffFn = testDiffFn
  1254  	s := &State{
  1255  		Modules: []*ModuleState{
  1256  			&ModuleState{
  1257  				Path: rootModulePath,
  1258  				Resources: map[string]*ResourceState{
  1259  					"aws_instance.foo": &ResourceState{
  1260  						Type: "aws_instance",
  1261  						Primary: &InstanceState{
  1262  							ID: "bar",
  1263  						},
  1264  					},
  1265  				},
  1266  			},
  1267  			&ModuleState{
  1268  				Path: []string{"root", "child"},
  1269  				Resources: map[string]*ResourceState{
  1270  					"aws_instance.foo": &ResourceState{
  1271  						Type: "aws_instance",
  1272  						Primary: &InstanceState{
  1273  							ID: "bar",
  1274  						},
  1275  					},
  1276  				},
  1277  			},
  1278  		},
  1279  	}
  1280  	ctx := testContext2(t, &ContextOpts{
  1281  		Module: m,
  1282  		Providers: map[string]ResourceProviderFactory{
  1283  			"aws": testProviderFuncFixed(p),
  1284  		},
  1285  		State:   s,
  1286  		Destroy: true,
  1287  	})
  1288  
  1289  	plan, err := ctx.Plan()
  1290  	if err != nil {
  1291  		t.Fatalf("err: %s", err)
  1292  	}
  1293  
  1294  	actual := strings.TrimSpace(plan.String())
  1295  	expected := strings.TrimSpace(testTerraformPlanModuleDestroyStr)
  1296  	if actual != expected {
  1297  		t.Fatalf("bad:\n%s", actual)
  1298  	}
  1299  }
  1300  
  1301  // GH-1835
  1302  func TestContext2Plan_moduleDestroyCycle(t *testing.T) {
  1303  	m := testModule(t, "plan-module-destroy-gh-1835")
  1304  	p := testProvider("aws")
  1305  	p.DiffFn = testDiffFn
  1306  	s := &State{
  1307  		Modules: []*ModuleState{
  1308  			&ModuleState{
  1309  				Path: []string{"root", "a_module"},
  1310  				Resources: map[string]*ResourceState{
  1311  					"aws_instance.a": &ResourceState{
  1312  						Type: "aws_instance",
  1313  						Primary: &InstanceState{
  1314  							ID: "a",
  1315  						},
  1316  					},
  1317  				},
  1318  			},
  1319  			&ModuleState{
  1320  				Path: []string{"root", "b_module"},
  1321  				Resources: map[string]*ResourceState{
  1322  					"aws_instance.b": &ResourceState{
  1323  						Type: "aws_instance",
  1324  						Primary: &InstanceState{
  1325  							ID: "b",
  1326  						},
  1327  					},
  1328  				},
  1329  			},
  1330  		},
  1331  	}
  1332  	ctx := testContext2(t, &ContextOpts{
  1333  		Module: m,
  1334  		Providers: map[string]ResourceProviderFactory{
  1335  			"aws": testProviderFuncFixed(p),
  1336  		},
  1337  		State:   s,
  1338  		Destroy: true,
  1339  	})
  1340  
  1341  	plan, err := ctx.Plan()
  1342  	if err != nil {
  1343  		t.Fatalf("err: %s", err)
  1344  	}
  1345  
  1346  	actual := strings.TrimSpace(plan.String())
  1347  	expected := strings.TrimSpace(testTerraformPlanModuleDestroyCycleStr)
  1348  	if actual != expected {
  1349  		t.Fatalf("bad:\n%s", actual)
  1350  	}
  1351  }
  1352  
  1353  func TestContext2Plan_moduleDestroyMultivar(t *testing.T) {
  1354  	m := testModule(t, "plan-module-destroy-multivar")
  1355  	p := testProvider("aws")
  1356  	p.DiffFn = testDiffFn
  1357  	s := &State{
  1358  		Modules: []*ModuleState{
  1359  			&ModuleState{
  1360  				Path:      rootModulePath,
  1361  				Resources: map[string]*ResourceState{},
  1362  			},
  1363  			&ModuleState{
  1364  				Path: []string{"root", "child"},
  1365  				Resources: map[string]*ResourceState{
  1366  					"aws_instance.foo.0": &ResourceState{
  1367  						Type: "aws_instance",
  1368  						Primary: &InstanceState{
  1369  							ID: "bar0",
  1370  						},
  1371  					},
  1372  					"aws_instance.foo.1": &ResourceState{
  1373  						Type: "aws_instance",
  1374  						Primary: &InstanceState{
  1375  							ID: "bar1",
  1376  						},
  1377  					},
  1378  				},
  1379  			},
  1380  		},
  1381  	}
  1382  	ctx := testContext2(t, &ContextOpts{
  1383  		Module: m,
  1384  		Providers: map[string]ResourceProviderFactory{
  1385  			"aws": testProviderFuncFixed(p),
  1386  		},
  1387  		State:   s,
  1388  		Destroy: true,
  1389  	})
  1390  
  1391  	plan, err := ctx.Plan()
  1392  	if err != nil {
  1393  		t.Fatalf("err: %s", err)
  1394  	}
  1395  
  1396  	actual := strings.TrimSpace(plan.String())
  1397  	expected := strings.TrimSpace(testTerraformPlanModuleDestroyMultivarStr)
  1398  	if actual != expected {
  1399  		t.Fatalf("bad:\n%s", actual)
  1400  	}
  1401  }
  1402  
  1403  func TestContext2Plan_pathVar(t *testing.T) {
  1404  	cwd, err := os.Getwd()
  1405  	if err != nil {
  1406  		t.Fatalf("err: %s", err)
  1407  	}
  1408  
  1409  	m := testModule(t, "plan-path-var")
  1410  	p := testProvider("aws")
  1411  	p.DiffFn = testDiffFn
  1412  	ctx := testContext2(t, &ContextOpts{
  1413  		Module: m,
  1414  		Providers: map[string]ResourceProviderFactory{
  1415  			"aws": testProviderFuncFixed(p),
  1416  		},
  1417  	})
  1418  
  1419  	plan, err := ctx.Plan()
  1420  	if err != nil {
  1421  		t.Fatalf("err: %s", err)
  1422  	}
  1423  
  1424  	actual := strings.TrimSpace(plan.String())
  1425  	expected := strings.TrimSpace(testTerraformPlanPathVarStr)
  1426  
  1427  	// Warning: this ordering REALLY matters for this test. The
  1428  	// order is: cwd, module, root.
  1429  	expected = fmt.Sprintf(
  1430  		expected,
  1431  		cwd,
  1432  		m.Config().Dir,
  1433  		m.Config().Dir)
  1434  
  1435  	if actual != expected {
  1436  		t.Fatalf("bad:\n%s\n\nexpected:\n\n%s", actual, expected)
  1437  	}
  1438  }
  1439  
  1440  func TestContext2Plan_diffVar(t *testing.T) {
  1441  	m := testModule(t, "plan-diffvar")
  1442  	p := testProvider("aws")
  1443  	s := &State{
  1444  		Modules: []*ModuleState{
  1445  			&ModuleState{
  1446  				Path: rootModulePath,
  1447  				Resources: map[string]*ResourceState{
  1448  					"aws_instance.foo": &ResourceState{
  1449  						Primary: &InstanceState{
  1450  							ID: "bar",
  1451  							Attributes: map[string]string{
  1452  								"num": "2",
  1453  							},
  1454  						},
  1455  					},
  1456  				},
  1457  			},
  1458  		},
  1459  	}
  1460  	ctx := testContext2(t, &ContextOpts{
  1461  		Module: m,
  1462  		Providers: map[string]ResourceProviderFactory{
  1463  			"aws": testProviderFuncFixed(p),
  1464  		},
  1465  		State: s,
  1466  	})
  1467  
  1468  	p.DiffFn = func(
  1469  		info *InstanceInfo,
  1470  		s *InstanceState,
  1471  		c *ResourceConfig) (*InstanceDiff, error) {
  1472  		if s.ID != "bar" {
  1473  			return testDiffFn(info, s, c)
  1474  		}
  1475  
  1476  		return &InstanceDiff{
  1477  			Attributes: map[string]*ResourceAttrDiff{
  1478  				"num": &ResourceAttrDiff{
  1479  					Old: "2",
  1480  					New: "3",
  1481  				},
  1482  			},
  1483  		}, nil
  1484  	}
  1485  
  1486  	plan, err := ctx.Plan()
  1487  	if err != nil {
  1488  		t.Fatalf("err: %s", err)
  1489  	}
  1490  
  1491  	actual := strings.TrimSpace(plan.String())
  1492  	expected := strings.TrimSpace(testTerraformPlanDiffVarStr)
  1493  	if actual != expected {
  1494  		t.Fatalf("actual:\n%s\n\nexpected:\n%s", actual, expected)
  1495  	}
  1496  }
  1497  
  1498  func TestContext2Plan_hook(t *testing.T) {
  1499  	m := testModule(t, "plan-good")
  1500  	h := new(MockHook)
  1501  	p := testProvider("aws")
  1502  	p.DiffFn = testDiffFn
  1503  	ctx := testContext2(t, &ContextOpts{
  1504  		Module: m,
  1505  		Hooks:  []Hook{h},
  1506  		Providers: map[string]ResourceProviderFactory{
  1507  			"aws": testProviderFuncFixed(p),
  1508  		},
  1509  	})
  1510  
  1511  	_, err := ctx.Plan()
  1512  	if err != nil {
  1513  		t.Fatalf("err: %s", err)
  1514  	}
  1515  
  1516  	if !h.PreDiffCalled {
  1517  		t.Fatal("should be called")
  1518  	}
  1519  	if !h.PostDiffCalled {
  1520  		t.Fatal("should be called")
  1521  	}
  1522  }
  1523  
  1524  func TestContext2Plan_orphan(t *testing.T) {
  1525  	m := testModule(t, "plan-orphan")
  1526  	p := testProvider("aws")
  1527  	p.DiffFn = testDiffFn
  1528  	s := &State{
  1529  		Modules: []*ModuleState{
  1530  			&ModuleState{
  1531  				Path: rootModulePath,
  1532  				Resources: map[string]*ResourceState{
  1533  					"aws_instance.baz": &ResourceState{
  1534  						Type: "aws_instance",
  1535  						Primary: &InstanceState{
  1536  							ID: "bar",
  1537  						},
  1538  					},
  1539  				},
  1540  			},
  1541  		},
  1542  	}
  1543  	ctx := testContext2(t, &ContextOpts{
  1544  		Module: m,
  1545  		Providers: map[string]ResourceProviderFactory{
  1546  			"aws": testProviderFuncFixed(p),
  1547  		},
  1548  		State: s,
  1549  	})
  1550  
  1551  	plan, err := ctx.Plan()
  1552  	if err != nil {
  1553  		t.Fatalf("err: %s", err)
  1554  	}
  1555  
  1556  	actual := strings.TrimSpace(plan.String())
  1557  	expected := strings.TrimSpace(testTerraformPlanOrphanStr)
  1558  	if actual != expected {
  1559  		t.Fatalf("bad:\n%s", actual)
  1560  	}
  1561  }
  1562  
  1563  func TestContext2Plan_state(t *testing.T) {
  1564  	m := testModule(t, "plan-good")
  1565  	p := testProvider("aws")
  1566  	p.DiffFn = testDiffFn
  1567  	s := &State{
  1568  		Modules: []*ModuleState{
  1569  			&ModuleState{
  1570  				Path: rootModulePath,
  1571  				Resources: map[string]*ResourceState{
  1572  					"aws_instance.foo": &ResourceState{
  1573  						Primary: &InstanceState{
  1574  							ID: "bar",
  1575  						},
  1576  					},
  1577  				},
  1578  			},
  1579  		},
  1580  	}
  1581  	ctx := testContext2(t, &ContextOpts{
  1582  		Module: m,
  1583  		Providers: map[string]ResourceProviderFactory{
  1584  			"aws": testProviderFuncFixed(p),
  1585  		},
  1586  		State: s,
  1587  	})
  1588  
  1589  	plan, err := ctx.Plan()
  1590  	if err != nil {
  1591  		t.Fatalf("err: %s", err)
  1592  	}
  1593  
  1594  	if len(plan.Diff.RootModule().Resources) < 2 {
  1595  		t.Fatalf("bad: %#v", plan.Diff.RootModule().Resources)
  1596  	}
  1597  
  1598  	actual := strings.TrimSpace(plan.String())
  1599  	expected := strings.TrimSpace(testTerraformPlanStateStr)
  1600  	if actual != expected {
  1601  		t.Fatalf("bad:\n%s\n\nexpected:\n\n%s", actual, expected)
  1602  	}
  1603  }
  1604  
  1605  func TestContext2Plan_taint(t *testing.T) {
  1606  	m := testModule(t, "plan-taint")
  1607  	p := testProvider("aws")
  1608  	p.DiffFn = testDiffFn
  1609  	s := &State{
  1610  		Modules: []*ModuleState{
  1611  			&ModuleState{
  1612  				Path: rootModulePath,
  1613  				Resources: map[string]*ResourceState{
  1614  					"aws_instance.foo": &ResourceState{
  1615  						Type: "aws_instance",
  1616  						Primary: &InstanceState{
  1617  							ID:         "bar",
  1618  							Attributes: map[string]string{"num": "2"},
  1619  						},
  1620  					},
  1621  					"aws_instance.bar": &ResourceState{
  1622  						Type: "aws_instance",
  1623  						Tainted: []*InstanceState{
  1624  							&InstanceState{
  1625  								ID: "baz",
  1626  							},
  1627  						},
  1628  					},
  1629  				},
  1630  			},
  1631  		},
  1632  	}
  1633  	ctx := testContext2(t, &ContextOpts{
  1634  		Module: m,
  1635  		Providers: map[string]ResourceProviderFactory{
  1636  			"aws": testProviderFuncFixed(p),
  1637  		},
  1638  		State: s,
  1639  	})
  1640  
  1641  	plan, err := ctx.Plan()
  1642  	if err != nil {
  1643  		t.Fatalf("err: %s", err)
  1644  	}
  1645  
  1646  	actual := strings.TrimSpace(plan.String())
  1647  	expected := strings.TrimSpace(testTerraformPlanTaintStr)
  1648  	if actual != expected {
  1649  		t.Fatalf("bad:\n%s", actual)
  1650  	}
  1651  }
  1652  
  1653  func TestContext2Plan_multiple_taint(t *testing.T) {
  1654  	m := testModule(t, "plan-taint")
  1655  	p := testProvider("aws")
  1656  	p.DiffFn = testDiffFn
  1657  	s := &State{
  1658  		Modules: []*ModuleState{
  1659  			&ModuleState{
  1660  				Path: rootModulePath,
  1661  				Resources: map[string]*ResourceState{
  1662  					"aws_instance.foo": &ResourceState{
  1663  						Type: "aws_instance",
  1664  						Primary: &InstanceState{
  1665  							ID:         "bar",
  1666  							Attributes: map[string]string{"num": "2"},
  1667  						},
  1668  					},
  1669  					"aws_instance.bar": &ResourceState{
  1670  						Type: "aws_instance",
  1671  						Tainted: []*InstanceState{
  1672  							&InstanceState{
  1673  								ID: "baz",
  1674  							},
  1675  							&InstanceState{
  1676  								ID: "zip",
  1677  							},
  1678  						},
  1679  					},
  1680  				},
  1681  			},
  1682  		},
  1683  	}
  1684  	ctx := testContext2(t, &ContextOpts{
  1685  		Module: m,
  1686  		Providers: map[string]ResourceProviderFactory{
  1687  			"aws": testProviderFuncFixed(p),
  1688  		},
  1689  		State: s,
  1690  	})
  1691  
  1692  	plan, err := ctx.Plan()
  1693  	if err != nil {
  1694  		t.Fatalf("err: %s", err)
  1695  	}
  1696  
  1697  	actual := strings.TrimSpace(plan.String())
  1698  	expected := strings.TrimSpace(testTerraformPlanMultipleTaintStr)
  1699  	if actual != expected {
  1700  		t.Fatalf("bad:\n%s", actual)
  1701  	}
  1702  }
  1703  
  1704  // Fails about 50% of the time before the fix for GH-4982, covers the fix.
  1705  func TestContext2Plan_taintDestroyInterpolatedCountRace(t *testing.T) {
  1706  	m := testModule(t, "plan-taint-interpolated-count")
  1707  	p := testProvider("aws")
  1708  	p.DiffFn = testDiffFn
  1709  	s := &State{
  1710  		Modules: []*ModuleState{
  1711  			&ModuleState{
  1712  				Path: rootModulePath,
  1713  				Resources: map[string]*ResourceState{
  1714  					"aws_instance.foo.0": &ResourceState{
  1715  						Type: "aws_instance",
  1716  						Tainted: []*InstanceState{
  1717  							&InstanceState{ID: "bar"},
  1718  						},
  1719  					},
  1720  					"aws_instance.foo.1": &ResourceState{
  1721  						Type:    "aws_instance",
  1722  						Primary: &InstanceState{ID: "bar"},
  1723  					},
  1724  					"aws_instance.foo.2": &ResourceState{
  1725  						Type:    "aws_instance",
  1726  						Primary: &InstanceState{ID: "bar"},
  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  	for i := 0; i < 100; i++ {
  1741  		plan, err := ctx.Plan()
  1742  		if err != nil {
  1743  			t.Fatalf("err: %s", err)
  1744  		}
  1745  
  1746  		actual := strings.TrimSpace(plan.String())
  1747  		expected := strings.TrimSpace(`
  1748  DIFF:
  1749  
  1750  DESTROY/CREATE: aws_instance.foo.0
  1751  
  1752  STATE:
  1753  
  1754  aws_instance.foo.0: (1 tainted)
  1755    ID = <not created>
  1756    Tainted ID 1 = bar
  1757  aws_instance.foo.1:
  1758    ID = bar
  1759  aws_instance.foo.2:
  1760    ID = bar
  1761  		`)
  1762  		if actual != expected {
  1763  			t.Fatalf("bad:\n%s", actual)
  1764  		}
  1765  	}
  1766  }
  1767  
  1768  func TestContext2Plan_targeted(t *testing.T) {
  1769  	m := testModule(t, "plan-targeted")
  1770  	p := testProvider("aws")
  1771  	p.DiffFn = testDiffFn
  1772  	ctx := testContext2(t, &ContextOpts{
  1773  		Module: m,
  1774  		Providers: map[string]ResourceProviderFactory{
  1775  			"aws": testProviderFuncFixed(p),
  1776  		},
  1777  		Targets: []string{"aws_instance.foo"},
  1778  	})
  1779  
  1780  	plan, err := ctx.Plan()
  1781  	if err != nil {
  1782  		t.Fatalf("err: %s", err)
  1783  	}
  1784  
  1785  	actual := strings.TrimSpace(plan.String())
  1786  	expected := strings.TrimSpace(`
  1787  DIFF:
  1788  
  1789  CREATE: aws_instance.foo
  1790    num:  "" => "2"
  1791    type: "" => "aws_instance"
  1792  
  1793  STATE:
  1794  
  1795  <no state>
  1796  	`)
  1797  	if actual != expected {
  1798  		t.Fatalf("expected:\n%s\n\ngot:\n%s", expected, actual)
  1799  	}
  1800  }
  1801  
  1802  func TestContext2Plan_targetedOrphan(t *testing.T) {
  1803  	m := testModule(t, "plan-targeted-orphan")
  1804  	p := testProvider("aws")
  1805  	p.DiffFn = testDiffFn
  1806  	ctx := testContext2(t, &ContextOpts{
  1807  		Module: m,
  1808  		Providers: map[string]ResourceProviderFactory{
  1809  			"aws": testProviderFuncFixed(p),
  1810  		},
  1811  		State: &State{
  1812  			Modules: []*ModuleState{
  1813  				&ModuleState{
  1814  					Path: rootModulePath,
  1815  					Resources: map[string]*ResourceState{
  1816  						"aws_instance.orphan": &ResourceState{
  1817  							Type: "aws_instance",
  1818  							Primary: &InstanceState{
  1819  								ID: "i-789xyz",
  1820  							},
  1821  						},
  1822  						"aws_instance.nottargeted": &ResourceState{
  1823  							Type: "aws_instance",
  1824  							Primary: &InstanceState{
  1825  								ID: "i-abc123",
  1826  							},
  1827  						},
  1828  					},
  1829  				},
  1830  			},
  1831  		},
  1832  		Destroy: true,
  1833  		Targets: []string{"aws_instance.orphan"},
  1834  	})
  1835  
  1836  	plan, err := ctx.Plan()
  1837  	if err != nil {
  1838  		t.Fatalf("err: %s", err)
  1839  	}
  1840  
  1841  	actual := strings.TrimSpace(plan.String())
  1842  	expected := strings.TrimSpace(`DIFF:
  1843  
  1844  DESTROY: aws_instance.orphan
  1845  
  1846  STATE:
  1847  
  1848  aws_instance.nottargeted:
  1849    ID = i-abc123
  1850  aws_instance.orphan:
  1851    ID = i-789xyz
  1852  `)
  1853  	if actual != expected {
  1854  		t.Fatalf("expected:\n%s\n\ngot:\n%s", expected, actual)
  1855  	}
  1856  }
  1857  
  1858  // https://github.com/hashicorp/terraform/issues/2538
  1859  func TestContext2Plan_targetedModuleOrphan(t *testing.T) {
  1860  	m := testModule(t, "plan-targeted-module-orphan")
  1861  	p := testProvider("aws")
  1862  	p.DiffFn = testDiffFn
  1863  	ctx := testContext2(t, &ContextOpts{
  1864  		Module: m,
  1865  		Providers: map[string]ResourceProviderFactory{
  1866  			"aws": testProviderFuncFixed(p),
  1867  		},
  1868  		State: &State{
  1869  			Modules: []*ModuleState{
  1870  				&ModuleState{
  1871  					Path: []string{"root", "child"},
  1872  					Resources: map[string]*ResourceState{
  1873  						"aws_instance.orphan": &ResourceState{
  1874  							Type: "aws_instance",
  1875  							Primary: &InstanceState{
  1876  								ID: "i-789xyz",
  1877  							},
  1878  						},
  1879  						"aws_instance.nottargeted": &ResourceState{
  1880  							Type: "aws_instance",
  1881  							Primary: &InstanceState{
  1882  								ID: "i-abc123",
  1883  							},
  1884  						},
  1885  					},
  1886  				},
  1887  			},
  1888  		},
  1889  		Destroy: true,
  1890  		Targets: []string{"module.child.aws_instance.orphan"},
  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(`DIFF:
  1900  
  1901  module.child:
  1902    DESTROY: aws_instance.orphan
  1903  
  1904  STATE:
  1905  
  1906  module.child:
  1907    aws_instance.nottargeted:
  1908      ID = i-abc123
  1909    aws_instance.orphan:
  1910      ID = i-789xyz
  1911  `)
  1912  	if actual != expected {
  1913  		t.Fatalf("expected:\n%s\n\ngot:\n%s", expected, actual)
  1914  	}
  1915  }
  1916  
  1917  // https://github.com/hashicorp/terraform/issues/4515
  1918  func TestContext2Plan_targetedOverTen(t *testing.T) {
  1919  	m := testModule(t, "plan-targeted-over-ten")
  1920  	p := testProvider("aws")
  1921  	p.DiffFn = testDiffFn
  1922  
  1923  	resources := make(map[string]*ResourceState)
  1924  	var expectedState []string
  1925  	for i := 0; i < 13; i++ {
  1926  		key := fmt.Sprintf("aws_instance.foo.%d", i)
  1927  		id := fmt.Sprintf("i-abc%d", i)
  1928  		resources[key] = &ResourceState{
  1929  			Type:    "aws_instance",
  1930  			Primary: &InstanceState{ID: id},
  1931  		}
  1932  		expectedState = append(expectedState,
  1933  			fmt.Sprintf("%s:\n  ID = %s\n", key, id))
  1934  	}
  1935  	ctx := testContext2(t, &ContextOpts{
  1936  		Module: m,
  1937  		Providers: map[string]ResourceProviderFactory{
  1938  			"aws": testProviderFuncFixed(p),
  1939  		},
  1940  		State: &State{
  1941  			Modules: []*ModuleState{
  1942  				&ModuleState{
  1943  					Path:      rootModulePath,
  1944  					Resources: resources,
  1945  				},
  1946  			},
  1947  		},
  1948  		Targets: []string{"aws_instance.foo[1]"},
  1949  	})
  1950  
  1951  	plan, err := ctx.Plan()
  1952  	if err != nil {
  1953  		t.Fatalf("err: %s", err)
  1954  	}
  1955  
  1956  	actual := strings.TrimSpace(plan.String())
  1957  	sort.Strings(expectedState)
  1958  	expected := strings.TrimSpace(`
  1959  DIFF:
  1960  
  1961  
  1962  
  1963  STATE:
  1964  
  1965  aws_instance.foo.0:
  1966    ID = i-abc0
  1967  aws_instance.foo.1:
  1968    ID = i-abc1
  1969  aws_instance.foo.10:
  1970    ID = i-abc10
  1971  aws_instance.foo.11:
  1972    ID = i-abc11
  1973  aws_instance.foo.12:
  1974    ID = i-abc12
  1975  aws_instance.foo.2:
  1976    ID = i-abc2
  1977  aws_instance.foo.3:
  1978    ID = i-abc3
  1979  aws_instance.foo.4:
  1980    ID = i-abc4
  1981  aws_instance.foo.5:
  1982    ID = i-abc5
  1983  aws_instance.foo.6:
  1984    ID = i-abc6
  1985  aws_instance.foo.7:
  1986    ID = i-abc7
  1987  aws_instance.foo.8:
  1988    ID = i-abc8
  1989  aws_instance.foo.9:
  1990    ID = i-abc9
  1991  	`)
  1992  	if actual != expected {
  1993  		t.Fatalf("expected:\n%s\n\ngot:\n%s", expected, actual)
  1994  	}
  1995  }
  1996  
  1997  func TestContext2Plan_provider(t *testing.T) {
  1998  	m := testModule(t, "plan-provider")
  1999  	p := testProvider("aws")
  2000  	p.DiffFn = testDiffFn
  2001  
  2002  	var value interface{}
  2003  	p.ConfigureFn = func(c *ResourceConfig) error {
  2004  		value, _ = c.Get("foo")
  2005  		return nil
  2006  	}
  2007  
  2008  	ctx := testContext2(t, &ContextOpts{
  2009  		Module: m,
  2010  		Providers: map[string]ResourceProviderFactory{
  2011  			"aws": testProviderFuncFixed(p),
  2012  		},
  2013  		Variables: map[string]string{
  2014  			"foo": "bar",
  2015  		},
  2016  	})
  2017  
  2018  	if _, err := ctx.Plan(); err != nil {
  2019  		t.Fatalf("err: %s", err)
  2020  	}
  2021  
  2022  	if value != "bar" {
  2023  		t.Fatalf("bad: %#v", value)
  2024  	}
  2025  }
  2026  
  2027  func TestContext2Plan_varListErr(t *testing.T) {
  2028  	m := testModule(t, "plan-var-list-err")
  2029  	p := testProvider("aws")
  2030  	ctx := testContext2(t, &ContextOpts{
  2031  		Module: m,
  2032  		Providers: map[string]ResourceProviderFactory{
  2033  			"aws": testProviderFuncFixed(p),
  2034  		},
  2035  	})
  2036  
  2037  	_, err := ctx.Plan()
  2038  	if err == nil {
  2039  		t.Fatal("should error")
  2040  	}
  2041  }
  2042  
  2043  func TestContext2Plan_ignoreChanges(t *testing.T) {
  2044  	m := testModule(t, "plan-ignore-changes")
  2045  	p := testProvider("aws")
  2046  	p.DiffFn = testDiffFn
  2047  	s := &State{
  2048  		Modules: []*ModuleState{
  2049  			&ModuleState{
  2050  				Path: rootModulePath,
  2051  				Resources: map[string]*ResourceState{
  2052  					"aws_instance.foo": &ResourceState{
  2053  						Primary: &InstanceState{
  2054  							ID:         "bar",
  2055  							Attributes: map[string]string{"ami": "ami-abcd1234"},
  2056  						},
  2057  					},
  2058  				},
  2059  			},
  2060  		},
  2061  	}
  2062  	ctx := testContext2(t, &ContextOpts{
  2063  		Module: m,
  2064  		Providers: map[string]ResourceProviderFactory{
  2065  			"aws": testProviderFuncFixed(p),
  2066  		},
  2067  		Variables: map[string]string{
  2068  			"foo": "ami-1234abcd",
  2069  		},
  2070  		State: s,
  2071  	})
  2072  
  2073  	plan, err := ctx.Plan()
  2074  	if err != nil {
  2075  		t.Fatalf("err: %s", err)
  2076  	}
  2077  
  2078  	if len(plan.Diff.RootModule().Resources) < 1 {
  2079  		t.Fatalf("bad: %#v", plan.Diff.RootModule().Resources)
  2080  	}
  2081  
  2082  	actual := strings.TrimSpace(plan.String())
  2083  	expected := strings.TrimSpace(testTerraformPlanIgnoreChangesStr)
  2084  	if actual != expected {
  2085  		t.Fatalf("bad:\n%s\n\nexpected\n\n%s", actual, expected)
  2086  	}
  2087  }