github.com/erriapo/terraform@v0.6.12-0.20160203182612-0340ea72354f/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  func TestContext2Plan_moduleProviderInherit(t *testing.T) {
   372  	var l sync.Mutex
   373  	var calls []string
   374  
   375  	m := testModule(t, "plan-module-provider-inherit")
   376  	ctx := testContext2(t, &ContextOpts{
   377  		Module: m,
   378  		Providers: map[string]ResourceProviderFactory{
   379  			"aws": func() (ResourceProvider, error) {
   380  				l.Lock()
   381  				defer l.Unlock()
   382  
   383  				p := testProvider("aws")
   384  				p.ConfigureFn = func(c *ResourceConfig) error {
   385  					if v, ok := c.Get("from"); !ok || v.(string) != "root" {
   386  						return fmt.Errorf("bad")
   387  					}
   388  
   389  					return nil
   390  				}
   391  				p.DiffFn = func(
   392  					info *InstanceInfo,
   393  					state *InstanceState,
   394  					c *ResourceConfig) (*InstanceDiff, error) {
   395  					v, _ := c.Get("from")
   396  					calls = append(calls, v.(string))
   397  					return testDiffFn(info, state, c)
   398  				}
   399  				return p, nil
   400  			},
   401  		},
   402  	})
   403  
   404  	_, err := ctx.Plan()
   405  	if err != nil {
   406  		t.Fatalf("err: %s", err)
   407  	}
   408  
   409  	actual := calls
   410  	sort.Strings(actual)
   411  	expected := []string{"child", "root"}
   412  	if !reflect.DeepEqual(actual, expected) {
   413  		t.Fatalf("bad: %#v", actual)
   414  	}
   415  }
   416  
   417  func TestContext2Plan_moduleProviderDefaults(t *testing.T) {
   418  	var l sync.Mutex
   419  	var calls []string
   420  	toCount := 0
   421  
   422  	m := testModule(t, "plan-module-provider-defaults")
   423  	ctx := testContext2(t, &ContextOpts{
   424  		Module: m,
   425  		Providers: map[string]ResourceProviderFactory{
   426  			"aws": func() (ResourceProvider, error) {
   427  				l.Lock()
   428  				defer l.Unlock()
   429  
   430  				p := testProvider("aws")
   431  				p.ConfigureFn = func(c *ResourceConfig) error {
   432  					if v, ok := c.Get("from"); !ok || v.(string) != "root" {
   433  						return fmt.Errorf("bad")
   434  					}
   435  					if v, ok := c.Get("to"); ok && v.(string) == "child" {
   436  						toCount++
   437  					}
   438  
   439  					return nil
   440  				}
   441  				p.DiffFn = func(
   442  					info *InstanceInfo,
   443  					state *InstanceState,
   444  					c *ResourceConfig) (*InstanceDiff, error) {
   445  					v, _ := c.Get("from")
   446  					calls = append(calls, v.(string))
   447  					return testDiffFn(info, state, c)
   448  				}
   449  				return p, nil
   450  			},
   451  		},
   452  	})
   453  
   454  	_, err := ctx.Plan()
   455  	if err != nil {
   456  		t.Fatalf("err: %s", err)
   457  	}
   458  
   459  	if toCount != 1 {
   460  		t.Fatalf(
   461  			"provider in child didn't set proper config\n\n"+
   462  				"toCount: %d", toCount)
   463  	}
   464  
   465  	actual := calls
   466  	sort.Strings(actual)
   467  	expected := []string{"child", "root"}
   468  	if !reflect.DeepEqual(actual, expected) {
   469  		t.Fatalf("bad: %#v", actual)
   470  	}
   471  }
   472  
   473  func TestContext2Plan_moduleProviderDefaultsVar(t *testing.T) {
   474  	var l sync.Mutex
   475  	var calls []string
   476  
   477  	m := testModule(t, "plan-module-provider-defaults-var")
   478  	ctx := testContext2(t, &ContextOpts{
   479  		Module: m,
   480  		Providers: map[string]ResourceProviderFactory{
   481  			"aws": func() (ResourceProvider, error) {
   482  				l.Lock()
   483  				defer l.Unlock()
   484  
   485  				p := testProvider("aws")
   486  				p.ConfigureFn = func(c *ResourceConfig) error {
   487  					var buf bytes.Buffer
   488  					if v, ok := c.Get("from"); ok {
   489  						buf.WriteString(v.(string) + "\n")
   490  					}
   491  					if v, ok := c.Get("to"); ok {
   492  						buf.WriteString(v.(string) + "\n")
   493  					}
   494  
   495  					calls = append(calls, buf.String())
   496  					return nil
   497  				}
   498  				p.DiffFn = testDiffFn
   499  				return p, nil
   500  			},
   501  		},
   502  		Variables: map[string]string{
   503  			"foo": "root",
   504  		},
   505  	})
   506  
   507  	_, err := ctx.Plan()
   508  	if err != nil {
   509  		t.Fatalf("err: %s", err)
   510  	}
   511  
   512  	expected := []string{
   513  		"root\n",
   514  		"root\nchild\n",
   515  	}
   516  	if !reflect.DeepEqual(calls, expected) {
   517  		t.Fatalf("BAD: %#v", calls)
   518  	}
   519  }
   520  
   521  func TestContext2Plan_moduleVar(t *testing.T) {
   522  	m := testModule(t, "plan-module-var")
   523  	p := testProvider("aws")
   524  	p.DiffFn = testDiffFn
   525  	ctx := testContext2(t, &ContextOpts{
   526  		Module: m,
   527  		Providers: map[string]ResourceProviderFactory{
   528  			"aws": testProviderFuncFixed(p),
   529  		},
   530  	})
   531  
   532  	plan, err := ctx.Plan()
   533  	if err != nil {
   534  		t.Fatalf("err: %s", err)
   535  	}
   536  
   537  	actual := strings.TrimSpace(plan.String())
   538  	expected := strings.TrimSpace(testTerraformPlanModuleVarStr)
   539  	if actual != expected {
   540  		t.Fatalf("bad:\n%s", actual)
   541  	}
   542  }
   543  
   544  func TestContext2Plan_moduleVarComputed(t *testing.T) {
   545  	m := testModule(t, "plan-module-var-computed")
   546  	p := testProvider("aws")
   547  	p.DiffFn = testDiffFn
   548  	ctx := testContext2(t, &ContextOpts{
   549  		Module: m,
   550  		Providers: map[string]ResourceProviderFactory{
   551  			"aws": testProviderFuncFixed(p),
   552  		},
   553  	})
   554  
   555  	plan, err := ctx.Plan()
   556  	if err != nil {
   557  		t.Fatalf("err: %s", err)
   558  	}
   559  
   560  	actual := strings.TrimSpace(plan.String())
   561  	expected := strings.TrimSpace(testTerraformPlanModuleVarComputedStr)
   562  	if actual != expected {
   563  		t.Fatalf("bad:\n%s", actual)
   564  	}
   565  }
   566  
   567  func TestContext2Plan_nil(t *testing.T) {
   568  	m := testModule(t, "plan-nil")
   569  	p := testProvider("aws")
   570  	p.DiffFn = testDiffFn
   571  	ctx := testContext2(t, &ContextOpts{
   572  		Module: m,
   573  		Providers: map[string]ResourceProviderFactory{
   574  			"aws": testProviderFuncFixed(p),
   575  		},
   576  		State: &State{
   577  			Modules: []*ModuleState{
   578  				&ModuleState{
   579  					Path: rootModulePath,
   580  					Resources: map[string]*ResourceState{
   581  						"aws_instance.foo": &ResourceState{
   582  							Type: "aws_instance",
   583  							Primary: &InstanceState{
   584  								ID: "bar",
   585  							},
   586  						},
   587  					},
   588  				},
   589  			},
   590  		},
   591  	})
   592  
   593  	plan, err := ctx.Plan()
   594  	if err != nil {
   595  		t.Fatalf("err: %s", err)
   596  	}
   597  	if len(plan.Diff.RootModule().Resources) != 0 {
   598  		t.Fatalf("bad: %#v", plan.Diff.RootModule().Resources)
   599  	}
   600  }
   601  
   602  func TestContext2Plan_preventDestroy_bad(t *testing.T) {
   603  	m := testModule(t, "plan-prevent-destroy-bad")
   604  	p := testProvider("aws")
   605  	p.DiffFn = testDiffFn
   606  	ctx := testContext2(t, &ContextOpts{
   607  		Module: m,
   608  		Providers: map[string]ResourceProviderFactory{
   609  			"aws": testProviderFuncFixed(p),
   610  		},
   611  		State: &State{
   612  			Modules: []*ModuleState{
   613  				&ModuleState{
   614  					Path: rootModulePath,
   615  					Resources: map[string]*ResourceState{
   616  						"aws_instance.foo": &ResourceState{
   617  							Type: "aws_instance",
   618  							Primary: &InstanceState{
   619  								ID: "i-abc123",
   620  							},
   621  						},
   622  					},
   623  				},
   624  			},
   625  		},
   626  	})
   627  
   628  	plan, err := ctx.Plan()
   629  
   630  	expectedErr := "aws_instance.foo: the plan would destroy"
   631  	if !strings.Contains(fmt.Sprintf("%s", err), expectedErr) {
   632  		t.Fatalf("expected err would contain %q\nerr: %s\nplan: %s",
   633  			expectedErr, err, plan)
   634  	}
   635  }
   636  
   637  func TestContext2Plan_preventDestroy_good(t *testing.T) {
   638  	m := testModule(t, "plan-prevent-destroy-good")
   639  	p := testProvider("aws")
   640  	p.DiffFn = testDiffFn
   641  	ctx := testContext2(t, &ContextOpts{
   642  		Module: m,
   643  		Providers: map[string]ResourceProviderFactory{
   644  			"aws": testProviderFuncFixed(p),
   645  		},
   646  		State: &State{
   647  			Modules: []*ModuleState{
   648  				&ModuleState{
   649  					Path: rootModulePath,
   650  					Resources: map[string]*ResourceState{
   651  						"aws_instance.foo": &ResourceState{
   652  							Type: "aws_instance",
   653  							Primary: &InstanceState{
   654  								ID: "i-abc123",
   655  							},
   656  						},
   657  					},
   658  				},
   659  			},
   660  		},
   661  	})
   662  
   663  	plan, err := ctx.Plan()
   664  	if err != nil {
   665  		t.Fatalf("err: %s", err)
   666  	}
   667  	if !plan.Diff.Empty() {
   668  		t.Fatalf("Expected empty plan, got %s", plan.String())
   669  	}
   670  }
   671  
   672  func TestContext2Plan_preventDestroy_destroyPlan(t *testing.T) {
   673  	m := testModule(t, "plan-prevent-destroy-good")
   674  	p := testProvider("aws")
   675  	p.DiffFn = testDiffFn
   676  	ctx := testContext2(t, &ContextOpts{
   677  		Module: m,
   678  		Providers: map[string]ResourceProviderFactory{
   679  			"aws": testProviderFuncFixed(p),
   680  		},
   681  		State: &State{
   682  			Modules: []*ModuleState{
   683  				&ModuleState{
   684  					Path: rootModulePath,
   685  					Resources: map[string]*ResourceState{
   686  						"aws_instance.foo": &ResourceState{
   687  							Type: "aws_instance",
   688  							Primary: &InstanceState{
   689  								ID: "i-abc123",
   690  							},
   691  						},
   692  					},
   693  				},
   694  			},
   695  		},
   696  		Destroy: true,
   697  	})
   698  
   699  	plan, err := ctx.Plan()
   700  
   701  	expectedErr := "aws_instance.foo: the plan would destroy"
   702  	if !strings.Contains(fmt.Sprintf("%s", err), expectedErr) {
   703  		t.Fatalf("expected err would contain %q\nerr: %s\nplan: %s",
   704  			expectedErr, err, plan)
   705  	}
   706  }
   707  
   708  func TestContext2Plan_computed(t *testing.T) {
   709  	m := testModule(t, "plan-computed")
   710  	p := testProvider("aws")
   711  	p.DiffFn = testDiffFn
   712  	ctx := testContext2(t, &ContextOpts{
   713  		Module: m,
   714  		Providers: map[string]ResourceProviderFactory{
   715  			"aws": testProviderFuncFixed(p),
   716  		},
   717  	})
   718  
   719  	plan, err := ctx.Plan()
   720  	if err != nil {
   721  		t.Fatalf("err: %s", err)
   722  	}
   723  
   724  	actual := strings.TrimSpace(plan.String())
   725  	expected := strings.TrimSpace(testTerraformPlanComputedStr)
   726  	if actual != expected {
   727  		t.Fatalf("bad:\n%s", actual)
   728  	}
   729  }
   730  
   731  func TestContext2Plan_computedList(t *testing.T) {
   732  	m := testModule(t, "plan-computed-list")
   733  	p := testProvider("aws")
   734  	p.DiffFn = testDiffFn
   735  	ctx := testContext2(t, &ContextOpts{
   736  		Module: m,
   737  		Providers: map[string]ResourceProviderFactory{
   738  			"aws": testProviderFuncFixed(p),
   739  		},
   740  	})
   741  
   742  	plan, err := ctx.Plan()
   743  	if err != nil {
   744  		t.Fatalf("err: %s", err)
   745  	}
   746  
   747  	actual := strings.TrimSpace(plan.String())
   748  	expected := strings.TrimSpace(testTerraformPlanComputedListStr)
   749  	if actual != expected {
   750  		t.Fatalf("bad:\n%s", actual)
   751  	}
   752  }
   753  
   754  func TestContext2Plan_count(t *testing.T) {
   755  	m := testModule(t, "plan-count")
   756  	p := testProvider("aws")
   757  	p.DiffFn = testDiffFn
   758  	ctx := testContext2(t, &ContextOpts{
   759  		Module: m,
   760  		Providers: map[string]ResourceProviderFactory{
   761  			"aws": testProviderFuncFixed(p),
   762  		},
   763  	})
   764  
   765  	plan, err := ctx.Plan()
   766  	if err != nil {
   767  		t.Fatalf("err: %s", err)
   768  	}
   769  
   770  	if len(plan.Diff.RootModule().Resources) < 6 {
   771  		t.Fatalf("bad: %#v", plan.Diff.RootModule().Resources)
   772  	}
   773  
   774  	actual := strings.TrimSpace(plan.String())
   775  	expected := strings.TrimSpace(testTerraformPlanCountStr)
   776  	if actual != expected {
   777  		t.Fatalf("bad:\n%s", actual)
   778  	}
   779  }
   780  
   781  func TestContext2Plan_countComputed(t *testing.T) {
   782  	m := testModule(t, "plan-count-computed")
   783  	p := testProvider("aws")
   784  	p.DiffFn = testDiffFn
   785  	ctx := testContext2(t, &ContextOpts{
   786  		Module: m,
   787  		Providers: map[string]ResourceProviderFactory{
   788  			"aws": testProviderFuncFixed(p),
   789  		},
   790  	})
   791  
   792  	_, err := ctx.Plan()
   793  	if err == nil {
   794  		t.Fatal("should error")
   795  	}
   796  }
   797  
   798  func TestContext2Plan_countIndex(t *testing.T) {
   799  	m := testModule(t, "plan-count-index")
   800  	p := testProvider("aws")
   801  	p.DiffFn = testDiffFn
   802  	ctx := testContext2(t, &ContextOpts{
   803  		Module: m,
   804  		Providers: map[string]ResourceProviderFactory{
   805  			"aws": testProviderFuncFixed(p),
   806  		},
   807  	})
   808  
   809  	plan, err := ctx.Plan()
   810  	if err != nil {
   811  		t.Fatalf("err: %s", err)
   812  	}
   813  
   814  	actual := strings.TrimSpace(plan.String())
   815  	expected := strings.TrimSpace(testTerraformPlanCountIndexStr)
   816  	if actual != expected {
   817  		t.Fatalf("bad:\n%s", actual)
   818  	}
   819  }
   820  
   821  func TestContext2Plan_countIndexZero(t *testing.T) {
   822  	m := testModule(t, "plan-count-index-zero")
   823  	p := testProvider("aws")
   824  	p.DiffFn = testDiffFn
   825  	ctx := testContext2(t, &ContextOpts{
   826  		Module: m,
   827  		Providers: map[string]ResourceProviderFactory{
   828  			"aws": testProviderFuncFixed(p),
   829  		},
   830  	})
   831  
   832  	plan, err := ctx.Plan()
   833  	if err != nil {
   834  		t.Fatalf("err: %s", err)
   835  	}
   836  
   837  	actual := strings.TrimSpace(plan.String())
   838  	expected := strings.TrimSpace(testTerraformPlanCountIndexZeroStr)
   839  	if actual != expected {
   840  		t.Fatalf("bad:\n%s", actual)
   841  	}
   842  }
   843  
   844  func TestContext2Plan_countVar(t *testing.T) {
   845  	m := testModule(t, "plan-count-var")
   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  		Variables: map[string]string{
   854  			"count": "3",
   855  		},
   856  	})
   857  
   858  	plan, err := ctx.Plan()
   859  	if err != nil {
   860  		t.Fatalf("err: %s", err)
   861  	}
   862  
   863  	actual := strings.TrimSpace(plan.String())
   864  	expected := strings.TrimSpace(testTerraformPlanCountVarStr)
   865  	if actual != expected {
   866  		t.Fatalf("bad:\n%s", actual)
   867  	}
   868  }
   869  
   870  func TestContext2Plan_countZero(t *testing.T) {
   871  	m := testModule(t, "plan-count-zero")
   872  	p := testProvider("aws")
   873  	p.DiffFn = testDiffFn
   874  	ctx := testContext2(t, &ContextOpts{
   875  		Module: m,
   876  		Providers: map[string]ResourceProviderFactory{
   877  			"aws": testProviderFuncFixed(p),
   878  		},
   879  	})
   880  
   881  	plan, err := ctx.Plan()
   882  	if err != nil {
   883  		t.Fatalf("err: %s", err)
   884  	}
   885  
   886  	actual := strings.TrimSpace(plan.String())
   887  	expected := strings.TrimSpace(testTerraformPlanCountZeroStr)
   888  	if actual != expected {
   889  		t.Fatalf("bad:\n%s", actual)
   890  	}
   891  }
   892  
   893  func TestContext2Plan_countOneIndex(t *testing.T) {
   894  	m := testModule(t, "plan-count-one-index")
   895  	p := testProvider("aws")
   896  	p.DiffFn = testDiffFn
   897  	ctx := testContext2(t, &ContextOpts{
   898  		Module: m,
   899  		Providers: map[string]ResourceProviderFactory{
   900  			"aws": testProviderFuncFixed(p),
   901  		},
   902  	})
   903  
   904  	plan, err := ctx.Plan()
   905  	if err != nil {
   906  		t.Fatalf("err: %s", err)
   907  	}
   908  
   909  	actual := strings.TrimSpace(plan.String())
   910  	expected := strings.TrimSpace(testTerraformPlanCountOneIndexStr)
   911  	if actual != expected {
   912  		t.Fatalf("bad:\n%s", actual)
   913  	}
   914  }
   915  
   916  func TestContext2Plan_countDecreaseToOne(t *testing.T) {
   917  	m := testModule(t, "plan-count-dec")
   918  	p := testProvider("aws")
   919  	p.DiffFn = testDiffFn
   920  	s := &State{
   921  		Modules: []*ModuleState{
   922  			&ModuleState{
   923  				Path: rootModulePath,
   924  				Resources: map[string]*ResourceState{
   925  					"aws_instance.foo.0": &ResourceState{
   926  						Type: "aws_instance",
   927  						Primary: &InstanceState{
   928  							ID: "bar",
   929  							Attributes: map[string]string{
   930  								"foo":  "foo",
   931  								"type": "aws_instance",
   932  							},
   933  						},
   934  					},
   935  					"aws_instance.foo.1": &ResourceState{
   936  						Type: "aws_instance",
   937  						Primary: &InstanceState{
   938  							ID: "bar",
   939  						},
   940  					},
   941  					"aws_instance.foo.2": &ResourceState{
   942  						Type: "aws_instance",
   943  						Primary: &InstanceState{
   944  							ID: "bar",
   945  						},
   946  					},
   947  				},
   948  			},
   949  		},
   950  	}
   951  	ctx := testContext2(t, &ContextOpts{
   952  		Module: m,
   953  		Providers: map[string]ResourceProviderFactory{
   954  			"aws": testProviderFuncFixed(p),
   955  		},
   956  		State: s,
   957  	})
   958  
   959  	plan, err := ctx.Plan()
   960  	if err != nil {
   961  		t.Fatalf("err: %s", err)
   962  	}
   963  
   964  	actual := strings.TrimSpace(plan.String())
   965  	expected := strings.TrimSpace(testTerraformPlanCountDecreaseStr)
   966  	if actual != expected {
   967  		t.Fatalf("bad:\n%s", actual)
   968  	}
   969  }
   970  
   971  func TestContext2Plan_countIncreaseFromNotSet(t *testing.T) {
   972  	m := testModule(t, "plan-count-inc")
   973  	p := testProvider("aws")
   974  	p.DiffFn = testDiffFn
   975  	s := &State{
   976  		Modules: []*ModuleState{
   977  			&ModuleState{
   978  				Path: rootModulePath,
   979  				Resources: map[string]*ResourceState{
   980  					"aws_instance.foo": &ResourceState{
   981  						Type: "aws_instance",
   982  						Primary: &InstanceState{
   983  							ID: "bar",
   984  							Attributes: map[string]string{
   985  								"foo":  "foo",
   986  								"type": "aws_instance",
   987  							},
   988  						},
   989  					},
   990  				},
   991  			},
   992  		},
   993  	}
   994  	ctx := testContext2(t, &ContextOpts{
   995  		Module: m,
   996  		Providers: map[string]ResourceProviderFactory{
   997  			"aws": testProviderFuncFixed(p),
   998  		},
   999  		State: s,
  1000  	})
  1001  
  1002  	plan, err := ctx.Plan()
  1003  	if err != nil {
  1004  		t.Fatalf("err: %s", err)
  1005  	}
  1006  
  1007  	actual := strings.TrimSpace(plan.String())
  1008  	expected := strings.TrimSpace(testTerraformPlanCountIncreaseStr)
  1009  	if actual != expected {
  1010  		t.Fatalf("bad:\n%s", actual)
  1011  	}
  1012  }
  1013  
  1014  func TestContext2Plan_countIncreaseFromOne(t *testing.T) {
  1015  	m := testModule(t, "plan-count-inc")
  1016  	p := testProvider("aws")
  1017  	p.DiffFn = testDiffFn
  1018  	s := &State{
  1019  		Modules: []*ModuleState{
  1020  			&ModuleState{
  1021  				Path: rootModulePath,
  1022  				Resources: map[string]*ResourceState{
  1023  					"aws_instance.foo.0": &ResourceState{
  1024  						Type: "aws_instance",
  1025  						Primary: &InstanceState{
  1026  							ID: "bar",
  1027  							Attributes: map[string]string{
  1028  								"foo":  "foo",
  1029  								"type": "aws_instance",
  1030  							},
  1031  						},
  1032  					},
  1033  				},
  1034  			},
  1035  		},
  1036  	}
  1037  	ctx := testContext2(t, &ContextOpts{
  1038  		Module: m,
  1039  		Providers: map[string]ResourceProviderFactory{
  1040  			"aws": testProviderFuncFixed(p),
  1041  		},
  1042  		State: s,
  1043  	})
  1044  
  1045  	plan, err := ctx.Plan()
  1046  	if err != nil {
  1047  		t.Fatalf("err: %s", err)
  1048  	}
  1049  
  1050  	actual := strings.TrimSpace(plan.String())
  1051  	expected := strings.TrimSpace(testTerraformPlanCountIncreaseFromOneStr)
  1052  	if actual != expected {
  1053  		t.Fatalf("bad:\n%s", actual)
  1054  	}
  1055  }
  1056  
  1057  // https://github.com/PeoplePerHour/terraform/pull/11
  1058  //
  1059  // This tests a case where both a "resource" and "resource.0" are in
  1060  // the state file, which apparently is a reasonable backwards compatibility
  1061  // concern found in the above 3rd party repo.
  1062  func TestContext2Plan_countIncreaseFromOneCorrupted(t *testing.T) {
  1063  	m := testModule(t, "plan-count-inc")
  1064  	p := testProvider("aws")
  1065  	p.DiffFn = testDiffFn
  1066  	s := &State{
  1067  		Modules: []*ModuleState{
  1068  			&ModuleState{
  1069  				Path: rootModulePath,
  1070  				Resources: map[string]*ResourceState{
  1071  					"aws_instance.foo": &ResourceState{
  1072  						Type: "aws_instance",
  1073  						Primary: &InstanceState{
  1074  							ID: "bar",
  1075  							Attributes: map[string]string{
  1076  								"foo":  "foo",
  1077  								"type": "aws_instance",
  1078  							},
  1079  						},
  1080  					},
  1081  					"aws_instance.foo.0": &ResourceState{
  1082  						Type: "aws_instance",
  1083  						Primary: &InstanceState{
  1084  							ID: "bar",
  1085  							Attributes: map[string]string{
  1086  								"foo":  "foo",
  1087  								"type": "aws_instance",
  1088  							},
  1089  						},
  1090  					},
  1091  				},
  1092  			},
  1093  		},
  1094  	}
  1095  	ctx := testContext2(t, &ContextOpts{
  1096  		Module: m,
  1097  		Providers: map[string]ResourceProviderFactory{
  1098  			"aws": testProviderFuncFixed(p),
  1099  		},
  1100  		State: s,
  1101  	})
  1102  
  1103  	plan, err := ctx.Plan()
  1104  	if err != nil {
  1105  		t.Fatalf("err: %s", err)
  1106  	}
  1107  
  1108  	actual := strings.TrimSpace(plan.String())
  1109  	expected := strings.TrimSpace(testTerraformPlanCountIncreaseFromOneCorruptedStr)
  1110  	if actual != expected {
  1111  		t.Fatalf("bad:\n%s", actual)
  1112  	}
  1113  }
  1114  
  1115  func TestContext2Plan_destroy(t *testing.T) {
  1116  	m := testModule(t, "plan-destroy")
  1117  	p := testProvider("aws")
  1118  	p.DiffFn = testDiffFn
  1119  	s := &State{
  1120  		Modules: []*ModuleState{
  1121  			&ModuleState{
  1122  				Path: rootModulePath,
  1123  				Resources: map[string]*ResourceState{
  1124  					"aws_instance.one": &ResourceState{
  1125  						Type: "aws_instance",
  1126  						Primary: &InstanceState{
  1127  							ID: "bar",
  1128  						},
  1129  					},
  1130  					"aws_instance.two": &ResourceState{
  1131  						Type: "aws_instance",
  1132  						Primary: &InstanceState{
  1133  							ID: "baz",
  1134  						},
  1135  					},
  1136  				},
  1137  			},
  1138  		},
  1139  	}
  1140  	ctx := testContext2(t, &ContextOpts{
  1141  		Module: m,
  1142  		Providers: map[string]ResourceProviderFactory{
  1143  			"aws": testProviderFuncFixed(p),
  1144  		},
  1145  		State:   s,
  1146  		Destroy: true,
  1147  	})
  1148  
  1149  	plan, err := ctx.Plan()
  1150  	if err != nil {
  1151  		t.Fatalf("err: %s", err)
  1152  	}
  1153  
  1154  	if len(plan.Diff.RootModule().Resources) != 2 {
  1155  		t.Fatalf("bad: %#v", plan.Diff.RootModule().Resources)
  1156  	}
  1157  
  1158  	actual := strings.TrimSpace(plan.String())
  1159  	expected := strings.TrimSpace(testTerraformPlanDestroyStr)
  1160  	if actual != expected {
  1161  		t.Fatalf("bad:\n%s", actual)
  1162  	}
  1163  }
  1164  
  1165  func TestContext2Plan_moduleDestroy(t *testing.T) {
  1166  	m := testModule(t, "plan-module-destroy")
  1167  	p := testProvider("aws")
  1168  	p.DiffFn = testDiffFn
  1169  	s := &State{
  1170  		Modules: []*ModuleState{
  1171  			&ModuleState{
  1172  				Path: rootModulePath,
  1173  				Resources: map[string]*ResourceState{
  1174  					"aws_instance.foo": &ResourceState{
  1175  						Type: "aws_instance",
  1176  						Primary: &InstanceState{
  1177  							ID: "bar",
  1178  						},
  1179  					},
  1180  				},
  1181  			},
  1182  			&ModuleState{
  1183  				Path: []string{"root", "child"},
  1184  				Resources: map[string]*ResourceState{
  1185  					"aws_instance.foo": &ResourceState{
  1186  						Type: "aws_instance",
  1187  						Primary: &InstanceState{
  1188  							ID: "bar",
  1189  						},
  1190  					},
  1191  				},
  1192  			},
  1193  		},
  1194  	}
  1195  	ctx := testContext2(t, &ContextOpts{
  1196  		Module: m,
  1197  		Providers: map[string]ResourceProviderFactory{
  1198  			"aws": testProviderFuncFixed(p),
  1199  		},
  1200  		State:   s,
  1201  		Destroy: true,
  1202  	})
  1203  
  1204  	plan, err := ctx.Plan()
  1205  	if err != nil {
  1206  		t.Fatalf("err: %s", err)
  1207  	}
  1208  
  1209  	actual := strings.TrimSpace(plan.String())
  1210  	expected := strings.TrimSpace(testTerraformPlanModuleDestroyStr)
  1211  	if actual != expected {
  1212  		t.Fatalf("bad:\n%s", actual)
  1213  	}
  1214  }
  1215  
  1216  // GH-1835
  1217  func TestContext2Plan_moduleDestroyCycle(t *testing.T) {
  1218  	m := testModule(t, "plan-module-destroy-gh-1835")
  1219  	p := testProvider("aws")
  1220  	p.DiffFn = testDiffFn
  1221  	s := &State{
  1222  		Modules: []*ModuleState{
  1223  			&ModuleState{
  1224  				Path: []string{"root", "a_module"},
  1225  				Resources: map[string]*ResourceState{
  1226  					"aws_instance.a": &ResourceState{
  1227  						Type: "aws_instance",
  1228  						Primary: &InstanceState{
  1229  							ID: "a",
  1230  						},
  1231  					},
  1232  				},
  1233  			},
  1234  			&ModuleState{
  1235  				Path: []string{"root", "b_module"},
  1236  				Resources: map[string]*ResourceState{
  1237  					"aws_instance.b": &ResourceState{
  1238  						Type: "aws_instance",
  1239  						Primary: &InstanceState{
  1240  							ID: "b",
  1241  						},
  1242  					},
  1243  				},
  1244  			},
  1245  		},
  1246  	}
  1247  	ctx := testContext2(t, &ContextOpts{
  1248  		Module: m,
  1249  		Providers: map[string]ResourceProviderFactory{
  1250  			"aws": testProviderFuncFixed(p),
  1251  		},
  1252  		State:   s,
  1253  		Destroy: true,
  1254  	})
  1255  
  1256  	plan, err := ctx.Plan()
  1257  	if err != nil {
  1258  		t.Fatalf("err: %s", err)
  1259  	}
  1260  
  1261  	actual := strings.TrimSpace(plan.String())
  1262  	expected := strings.TrimSpace(testTerraformPlanModuleDestroyCycleStr)
  1263  	if actual != expected {
  1264  		t.Fatalf("bad:\n%s", actual)
  1265  	}
  1266  }
  1267  
  1268  func TestContext2Plan_moduleDestroyMultivar(t *testing.T) {
  1269  	m := testModule(t, "plan-module-destroy-multivar")
  1270  	p := testProvider("aws")
  1271  	p.DiffFn = testDiffFn
  1272  	s := &State{
  1273  		Modules: []*ModuleState{
  1274  			&ModuleState{
  1275  				Path:      rootModulePath,
  1276  				Resources: map[string]*ResourceState{},
  1277  			},
  1278  			&ModuleState{
  1279  				Path: []string{"root", "child"},
  1280  				Resources: map[string]*ResourceState{
  1281  					"aws_instance.foo.0": &ResourceState{
  1282  						Type: "aws_instance",
  1283  						Primary: &InstanceState{
  1284  							ID: "bar0",
  1285  						},
  1286  					},
  1287  					"aws_instance.foo.1": &ResourceState{
  1288  						Type: "aws_instance",
  1289  						Primary: &InstanceState{
  1290  							ID: "bar1",
  1291  						},
  1292  					},
  1293  				},
  1294  			},
  1295  		},
  1296  	}
  1297  	ctx := testContext2(t, &ContextOpts{
  1298  		Module: m,
  1299  		Providers: map[string]ResourceProviderFactory{
  1300  			"aws": testProviderFuncFixed(p),
  1301  		},
  1302  		State:   s,
  1303  		Destroy: true,
  1304  	})
  1305  
  1306  	plan, err := ctx.Plan()
  1307  	if err != nil {
  1308  		t.Fatalf("err: %s", err)
  1309  	}
  1310  
  1311  	actual := strings.TrimSpace(plan.String())
  1312  	expected := strings.TrimSpace(testTerraformPlanModuleDestroyMultivarStr)
  1313  	if actual != expected {
  1314  		t.Fatalf("bad:\n%s", actual)
  1315  	}
  1316  }
  1317  
  1318  func TestContext2Plan_pathVar(t *testing.T) {
  1319  	cwd, err := os.Getwd()
  1320  	if err != nil {
  1321  		t.Fatalf("err: %s", err)
  1322  	}
  1323  
  1324  	m := testModule(t, "plan-path-var")
  1325  	p := testProvider("aws")
  1326  	p.DiffFn = testDiffFn
  1327  	ctx := testContext2(t, &ContextOpts{
  1328  		Module: m,
  1329  		Providers: map[string]ResourceProviderFactory{
  1330  			"aws": testProviderFuncFixed(p),
  1331  		},
  1332  	})
  1333  
  1334  	plan, err := ctx.Plan()
  1335  	if err != nil {
  1336  		t.Fatalf("err: %s", err)
  1337  	}
  1338  
  1339  	actual := strings.TrimSpace(plan.String())
  1340  	expected := strings.TrimSpace(testTerraformPlanPathVarStr)
  1341  
  1342  	// Warning: this ordering REALLY matters for this test. The
  1343  	// order is: cwd, module, root.
  1344  	expected = fmt.Sprintf(
  1345  		expected,
  1346  		cwd,
  1347  		m.Config().Dir,
  1348  		m.Config().Dir)
  1349  
  1350  	if actual != expected {
  1351  		t.Fatalf("bad:\n%s\n\nexpected:\n\n%s", actual, expected)
  1352  	}
  1353  }
  1354  
  1355  func TestContext2Plan_diffVar(t *testing.T) {
  1356  	m := testModule(t, "plan-diffvar")
  1357  	p := testProvider("aws")
  1358  	s := &State{
  1359  		Modules: []*ModuleState{
  1360  			&ModuleState{
  1361  				Path: rootModulePath,
  1362  				Resources: map[string]*ResourceState{
  1363  					"aws_instance.foo": &ResourceState{
  1364  						Primary: &InstanceState{
  1365  							ID: "bar",
  1366  							Attributes: map[string]string{
  1367  								"num": "2",
  1368  							},
  1369  						},
  1370  					},
  1371  				},
  1372  			},
  1373  		},
  1374  	}
  1375  	ctx := testContext2(t, &ContextOpts{
  1376  		Module: m,
  1377  		Providers: map[string]ResourceProviderFactory{
  1378  			"aws": testProviderFuncFixed(p),
  1379  		},
  1380  		State: s,
  1381  	})
  1382  
  1383  	p.DiffFn = func(
  1384  		info *InstanceInfo,
  1385  		s *InstanceState,
  1386  		c *ResourceConfig) (*InstanceDiff, error) {
  1387  		if s.ID != "bar" {
  1388  			return testDiffFn(info, s, c)
  1389  		}
  1390  
  1391  		return &InstanceDiff{
  1392  			Attributes: map[string]*ResourceAttrDiff{
  1393  				"num": &ResourceAttrDiff{
  1394  					Old: "2",
  1395  					New: "3",
  1396  				},
  1397  			},
  1398  		}, nil
  1399  	}
  1400  
  1401  	plan, err := ctx.Plan()
  1402  	if err != nil {
  1403  		t.Fatalf("err: %s", err)
  1404  	}
  1405  
  1406  	actual := strings.TrimSpace(plan.String())
  1407  	expected := strings.TrimSpace(testTerraformPlanDiffVarStr)
  1408  	if actual != expected {
  1409  		t.Fatalf("actual:\n%s\n\nexpected:\n%s", actual, expected)
  1410  	}
  1411  }
  1412  
  1413  func TestContext2Plan_hook(t *testing.T) {
  1414  	m := testModule(t, "plan-good")
  1415  	h := new(MockHook)
  1416  	p := testProvider("aws")
  1417  	p.DiffFn = testDiffFn
  1418  	ctx := testContext2(t, &ContextOpts{
  1419  		Module: m,
  1420  		Hooks:  []Hook{h},
  1421  		Providers: map[string]ResourceProviderFactory{
  1422  			"aws": testProviderFuncFixed(p),
  1423  		},
  1424  	})
  1425  
  1426  	_, err := ctx.Plan()
  1427  	if err != nil {
  1428  		t.Fatalf("err: %s", err)
  1429  	}
  1430  
  1431  	if !h.PreDiffCalled {
  1432  		t.Fatal("should be called")
  1433  	}
  1434  	if !h.PostDiffCalled {
  1435  		t.Fatal("should be called")
  1436  	}
  1437  }
  1438  
  1439  func TestContext2Plan_orphan(t *testing.T) {
  1440  	m := testModule(t, "plan-orphan")
  1441  	p := testProvider("aws")
  1442  	p.DiffFn = testDiffFn
  1443  	s := &State{
  1444  		Modules: []*ModuleState{
  1445  			&ModuleState{
  1446  				Path: rootModulePath,
  1447  				Resources: map[string]*ResourceState{
  1448  					"aws_instance.baz": &ResourceState{
  1449  						Type: "aws_instance",
  1450  						Primary: &InstanceState{
  1451  							ID: "bar",
  1452  						},
  1453  					},
  1454  				},
  1455  			},
  1456  		},
  1457  	}
  1458  	ctx := testContext2(t, &ContextOpts{
  1459  		Module: m,
  1460  		Providers: map[string]ResourceProviderFactory{
  1461  			"aws": testProviderFuncFixed(p),
  1462  		},
  1463  		State: s,
  1464  	})
  1465  
  1466  	plan, err := ctx.Plan()
  1467  	if err != nil {
  1468  		t.Fatalf("err: %s", err)
  1469  	}
  1470  
  1471  	actual := strings.TrimSpace(plan.String())
  1472  	expected := strings.TrimSpace(testTerraformPlanOrphanStr)
  1473  	if actual != expected {
  1474  		t.Fatalf("bad:\n%s", actual)
  1475  	}
  1476  }
  1477  
  1478  func TestContext2Plan_state(t *testing.T) {
  1479  	m := testModule(t, "plan-good")
  1480  	p := testProvider("aws")
  1481  	p.DiffFn = testDiffFn
  1482  	s := &State{
  1483  		Modules: []*ModuleState{
  1484  			&ModuleState{
  1485  				Path: rootModulePath,
  1486  				Resources: map[string]*ResourceState{
  1487  					"aws_instance.foo": &ResourceState{
  1488  						Primary: &InstanceState{
  1489  							ID: "bar",
  1490  						},
  1491  					},
  1492  				},
  1493  			},
  1494  		},
  1495  	}
  1496  	ctx := testContext2(t, &ContextOpts{
  1497  		Module: m,
  1498  		Providers: map[string]ResourceProviderFactory{
  1499  			"aws": testProviderFuncFixed(p),
  1500  		},
  1501  		State: s,
  1502  	})
  1503  
  1504  	plan, err := ctx.Plan()
  1505  	if err != nil {
  1506  		t.Fatalf("err: %s", err)
  1507  	}
  1508  
  1509  	if len(plan.Diff.RootModule().Resources) < 2 {
  1510  		t.Fatalf("bad: %#v", plan.Diff.RootModule().Resources)
  1511  	}
  1512  
  1513  	actual := strings.TrimSpace(plan.String())
  1514  	expected := strings.TrimSpace(testTerraformPlanStateStr)
  1515  	if actual != expected {
  1516  		t.Fatalf("bad:\n%s\n\nexpected:\n\n%s", actual, expected)
  1517  	}
  1518  }
  1519  
  1520  func TestContext2Plan_taint(t *testing.T) {
  1521  	m := testModule(t, "plan-taint")
  1522  	p := testProvider("aws")
  1523  	p.DiffFn = testDiffFn
  1524  	s := &State{
  1525  		Modules: []*ModuleState{
  1526  			&ModuleState{
  1527  				Path: rootModulePath,
  1528  				Resources: map[string]*ResourceState{
  1529  					"aws_instance.foo": &ResourceState{
  1530  						Type: "aws_instance",
  1531  						Primary: &InstanceState{
  1532  							ID:         "bar",
  1533  							Attributes: map[string]string{"num": "2"},
  1534  						},
  1535  					},
  1536  					"aws_instance.bar": &ResourceState{
  1537  						Type: "aws_instance",
  1538  						Tainted: []*InstanceState{
  1539  							&InstanceState{
  1540  								ID: "baz",
  1541  							},
  1542  						},
  1543  					},
  1544  				},
  1545  			},
  1546  		},
  1547  	}
  1548  	ctx := testContext2(t, &ContextOpts{
  1549  		Module: m,
  1550  		Providers: map[string]ResourceProviderFactory{
  1551  			"aws": testProviderFuncFixed(p),
  1552  		},
  1553  		State: s,
  1554  	})
  1555  
  1556  	plan, err := ctx.Plan()
  1557  	if err != nil {
  1558  		t.Fatalf("err: %s", err)
  1559  	}
  1560  
  1561  	actual := strings.TrimSpace(plan.String())
  1562  	expected := strings.TrimSpace(testTerraformPlanTaintStr)
  1563  	if actual != expected {
  1564  		t.Fatalf("bad:\n%s", actual)
  1565  	}
  1566  }
  1567  
  1568  func TestContext2Plan_multiple_taint(t *testing.T) {
  1569  	m := testModule(t, "plan-taint")
  1570  	p := testProvider("aws")
  1571  	p.DiffFn = testDiffFn
  1572  	s := &State{
  1573  		Modules: []*ModuleState{
  1574  			&ModuleState{
  1575  				Path: rootModulePath,
  1576  				Resources: map[string]*ResourceState{
  1577  					"aws_instance.foo": &ResourceState{
  1578  						Type: "aws_instance",
  1579  						Primary: &InstanceState{
  1580  							ID:         "bar",
  1581  							Attributes: map[string]string{"num": "2"},
  1582  						},
  1583  					},
  1584  					"aws_instance.bar": &ResourceState{
  1585  						Type: "aws_instance",
  1586  						Tainted: []*InstanceState{
  1587  							&InstanceState{
  1588  								ID: "baz",
  1589  							},
  1590  							&InstanceState{
  1591  								ID: "zip",
  1592  							},
  1593  						},
  1594  					},
  1595  				},
  1596  			},
  1597  		},
  1598  	}
  1599  	ctx := testContext2(t, &ContextOpts{
  1600  		Module: m,
  1601  		Providers: map[string]ResourceProviderFactory{
  1602  			"aws": testProviderFuncFixed(p),
  1603  		},
  1604  		State: s,
  1605  	})
  1606  
  1607  	plan, err := ctx.Plan()
  1608  	if err != nil {
  1609  		t.Fatalf("err: %s", err)
  1610  	}
  1611  
  1612  	actual := strings.TrimSpace(plan.String())
  1613  	expected := strings.TrimSpace(testTerraformPlanMultipleTaintStr)
  1614  	if actual != expected {
  1615  		t.Fatalf("bad:\n%s", actual)
  1616  	}
  1617  }
  1618  
  1619  func TestContext2Plan_targeted(t *testing.T) {
  1620  	m := testModule(t, "plan-targeted")
  1621  	p := testProvider("aws")
  1622  	p.DiffFn = testDiffFn
  1623  	ctx := testContext2(t, &ContextOpts{
  1624  		Module: m,
  1625  		Providers: map[string]ResourceProviderFactory{
  1626  			"aws": testProviderFuncFixed(p),
  1627  		},
  1628  		Targets: []string{"aws_instance.foo"},
  1629  	})
  1630  
  1631  	plan, err := ctx.Plan()
  1632  	if err != nil {
  1633  		t.Fatalf("err: %s", err)
  1634  	}
  1635  
  1636  	actual := strings.TrimSpace(plan.String())
  1637  	expected := strings.TrimSpace(`
  1638  DIFF:
  1639  
  1640  CREATE: aws_instance.foo
  1641    num:  "" => "2"
  1642    type: "" => "aws_instance"
  1643  
  1644  STATE:
  1645  
  1646  <no state>
  1647  	`)
  1648  	if actual != expected {
  1649  		t.Fatalf("expected:\n%s\n\ngot:\n%s", expected, actual)
  1650  	}
  1651  }
  1652  
  1653  func TestContext2Plan_targetedOrphan(t *testing.T) {
  1654  	m := testModule(t, "plan-targeted-orphan")
  1655  	p := testProvider("aws")
  1656  	p.DiffFn = testDiffFn
  1657  	ctx := testContext2(t, &ContextOpts{
  1658  		Module: m,
  1659  		Providers: map[string]ResourceProviderFactory{
  1660  			"aws": testProviderFuncFixed(p),
  1661  		},
  1662  		State: &State{
  1663  			Modules: []*ModuleState{
  1664  				&ModuleState{
  1665  					Path: rootModulePath,
  1666  					Resources: map[string]*ResourceState{
  1667  						"aws_instance.orphan": &ResourceState{
  1668  							Type: "aws_instance",
  1669  							Primary: &InstanceState{
  1670  								ID: "i-789xyz",
  1671  							},
  1672  						},
  1673  						"aws_instance.nottargeted": &ResourceState{
  1674  							Type: "aws_instance",
  1675  							Primary: &InstanceState{
  1676  								ID: "i-abc123",
  1677  							},
  1678  						},
  1679  					},
  1680  				},
  1681  			},
  1682  		},
  1683  		Destroy: true,
  1684  		Targets: []string{"aws_instance.orphan"},
  1685  	})
  1686  
  1687  	plan, err := ctx.Plan()
  1688  	if err != nil {
  1689  		t.Fatalf("err: %s", err)
  1690  	}
  1691  
  1692  	actual := strings.TrimSpace(plan.String())
  1693  	expected := strings.TrimSpace(`DIFF:
  1694  
  1695  DESTROY: aws_instance.orphan
  1696  
  1697  STATE:
  1698  
  1699  aws_instance.nottargeted:
  1700    ID = i-abc123
  1701  aws_instance.orphan:
  1702    ID = i-789xyz
  1703  `)
  1704  	if actual != expected {
  1705  		t.Fatalf("expected:\n%s\n\ngot:\n%s", expected, actual)
  1706  	}
  1707  }
  1708  
  1709  // https://github.com/hashicorp/terraform/issues/2538
  1710  func TestContext2Plan_targetedModuleOrphan(t *testing.T) {
  1711  	m := testModule(t, "plan-targeted-module-orphan")
  1712  	p := testProvider("aws")
  1713  	p.DiffFn = testDiffFn
  1714  	ctx := testContext2(t, &ContextOpts{
  1715  		Module: m,
  1716  		Providers: map[string]ResourceProviderFactory{
  1717  			"aws": testProviderFuncFixed(p),
  1718  		},
  1719  		State: &State{
  1720  			Modules: []*ModuleState{
  1721  				&ModuleState{
  1722  					Path: []string{"root", "child"},
  1723  					Resources: map[string]*ResourceState{
  1724  						"aws_instance.orphan": &ResourceState{
  1725  							Type: "aws_instance",
  1726  							Primary: &InstanceState{
  1727  								ID: "i-789xyz",
  1728  							},
  1729  						},
  1730  						"aws_instance.nottargeted": &ResourceState{
  1731  							Type: "aws_instance",
  1732  							Primary: &InstanceState{
  1733  								ID: "i-abc123",
  1734  							},
  1735  						},
  1736  					},
  1737  				},
  1738  			},
  1739  		},
  1740  		Destroy: true,
  1741  		Targets: []string{"module.child.aws_instance.orphan"},
  1742  	})
  1743  
  1744  	plan, err := ctx.Plan()
  1745  	if err != nil {
  1746  		t.Fatalf("err: %s", err)
  1747  	}
  1748  
  1749  	actual := strings.TrimSpace(plan.String())
  1750  	expected := strings.TrimSpace(`DIFF:
  1751  
  1752  module.child:
  1753    DESTROY: aws_instance.orphan
  1754  
  1755  STATE:
  1756  
  1757  module.child:
  1758    aws_instance.nottargeted:
  1759      ID = i-abc123
  1760    aws_instance.orphan:
  1761      ID = i-789xyz
  1762  `)
  1763  	if actual != expected {
  1764  		t.Fatalf("expected:\n%s\n\ngot:\n%s", expected, actual)
  1765  	}
  1766  }
  1767  
  1768  // https://github.com/hashicorp/terraform/issues/4515
  1769  func TestContext2Plan_targetedOverTen(t *testing.T) {
  1770  	m := testModule(t, "plan-targeted-over-ten")
  1771  	p := testProvider("aws")
  1772  	p.DiffFn = testDiffFn
  1773  
  1774  	resources := make(map[string]*ResourceState)
  1775  	var expectedState []string
  1776  	for i := 0; i < 13; i++ {
  1777  		key := fmt.Sprintf("aws_instance.foo.%d", i)
  1778  		id := fmt.Sprintf("i-abc%d", i)
  1779  		resources[key] = &ResourceState{
  1780  			Type:    "aws_instance",
  1781  			Primary: &InstanceState{ID: id},
  1782  		}
  1783  		expectedState = append(expectedState,
  1784  			fmt.Sprintf("%s:\n  ID = %s\n", key, id))
  1785  	}
  1786  	ctx := testContext2(t, &ContextOpts{
  1787  		Module: m,
  1788  		Providers: map[string]ResourceProviderFactory{
  1789  			"aws": testProviderFuncFixed(p),
  1790  		},
  1791  		State: &State{
  1792  			Modules: []*ModuleState{
  1793  				&ModuleState{
  1794  					Path:      rootModulePath,
  1795  					Resources: resources,
  1796  				},
  1797  			},
  1798  		},
  1799  		Targets: []string{"aws_instance.foo[1]"},
  1800  	})
  1801  
  1802  	plan, err := ctx.Plan()
  1803  	if err != nil {
  1804  		t.Fatalf("err: %s", err)
  1805  	}
  1806  
  1807  	actual := strings.TrimSpace(plan.String())
  1808  	sort.Strings(expectedState)
  1809  	expected := strings.TrimSpace(`
  1810  DIFF:
  1811  
  1812  
  1813  
  1814  STATE:
  1815  
  1816  aws_instance.foo.0:
  1817    ID = i-abc0
  1818  aws_instance.foo.1:
  1819    ID = i-abc1
  1820  aws_instance.foo.10:
  1821    ID = i-abc10
  1822  aws_instance.foo.11:
  1823    ID = i-abc11
  1824  aws_instance.foo.12:
  1825    ID = i-abc12
  1826  aws_instance.foo.2:
  1827    ID = i-abc2
  1828  aws_instance.foo.3:
  1829    ID = i-abc3
  1830  aws_instance.foo.4:
  1831    ID = i-abc4
  1832  aws_instance.foo.5:
  1833    ID = i-abc5
  1834  aws_instance.foo.6:
  1835    ID = i-abc6
  1836  aws_instance.foo.7:
  1837    ID = i-abc7
  1838  aws_instance.foo.8:
  1839    ID = i-abc8
  1840  aws_instance.foo.9:
  1841    ID = i-abc9
  1842  	`)
  1843  	if actual != expected {
  1844  		t.Fatalf("expected:\n%s\n\ngot:\n%s", expected, actual)
  1845  	}
  1846  }
  1847  
  1848  func TestContext2Plan_provider(t *testing.T) {
  1849  	m := testModule(t, "plan-provider")
  1850  	p := testProvider("aws")
  1851  	p.DiffFn = testDiffFn
  1852  
  1853  	var value interface{}
  1854  	p.ConfigureFn = func(c *ResourceConfig) error {
  1855  		value, _ = c.Get("foo")
  1856  		return nil
  1857  	}
  1858  
  1859  	ctx := testContext2(t, &ContextOpts{
  1860  		Module: m,
  1861  		Providers: map[string]ResourceProviderFactory{
  1862  			"aws": testProviderFuncFixed(p),
  1863  		},
  1864  		Variables: map[string]string{
  1865  			"foo": "bar",
  1866  		},
  1867  	})
  1868  
  1869  	if _, err := ctx.Plan(); err != nil {
  1870  		t.Fatalf("err: %s", err)
  1871  	}
  1872  
  1873  	if value != "bar" {
  1874  		t.Fatalf("bad: %#v", value)
  1875  	}
  1876  }
  1877  
  1878  func TestContext2Plan_varListErr(t *testing.T) {
  1879  	m := testModule(t, "plan-var-list-err")
  1880  	p := testProvider("aws")
  1881  	ctx := testContext2(t, &ContextOpts{
  1882  		Module: m,
  1883  		Providers: map[string]ResourceProviderFactory{
  1884  			"aws": testProviderFuncFixed(p),
  1885  		},
  1886  	})
  1887  
  1888  	_, err := ctx.Plan()
  1889  	if err == nil {
  1890  		t.Fatal("should error")
  1891  	}
  1892  }
  1893  
  1894  func TestContext2Plan_ignoreChanges(t *testing.T) {
  1895  	m := testModule(t, "plan-ignore-changes")
  1896  	p := testProvider("aws")
  1897  	p.DiffFn = testDiffFn
  1898  	s := &State{
  1899  		Modules: []*ModuleState{
  1900  			&ModuleState{
  1901  				Path: rootModulePath,
  1902  				Resources: map[string]*ResourceState{
  1903  					"aws_instance.foo": &ResourceState{
  1904  						Primary: &InstanceState{
  1905  							ID:         "bar",
  1906  							Attributes: map[string]string{"ami": "ami-abcd1234"},
  1907  						},
  1908  					},
  1909  				},
  1910  			},
  1911  		},
  1912  	}
  1913  	ctx := testContext2(t, &ContextOpts{
  1914  		Module: m,
  1915  		Providers: map[string]ResourceProviderFactory{
  1916  			"aws": testProviderFuncFixed(p),
  1917  		},
  1918  		Variables: map[string]string{
  1919  			"foo": "ami-1234abcd",
  1920  		},
  1921  		State: s,
  1922  	})
  1923  
  1924  	plan, err := ctx.Plan()
  1925  	if err != nil {
  1926  		t.Fatalf("err: %s", err)
  1927  	}
  1928  
  1929  	if len(plan.Diff.RootModule().Resources) < 1 {
  1930  		t.Fatalf("bad: %#v", plan.Diff.RootModule().Resources)
  1931  	}
  1932  
  1933  	actual := strings.TrimSpace(plan.String())
  1934  	expected := strings.TrimSpace(testTerraformPlanIgnoreChangesStr)
  1935  	if actual != expected {
  1936  		t.Fatalf("bad:\n%s\n\nexpected\n\n%s", actual, expected)
  1937  	}
  1938  }