github.com/trawler/terraform@v0.10.8-0.20171106022149-4b1c7a1d9b48/terraform/context_input_test.go (about)

     1  package terraform
     2  
     3  import (
     4  	"errors"
     5  	"reflect"
     6  	"strings"
     7  	"sync"
     8  	"testing"
     9  )
    10  
    11  func TestContext2Input(t *testing.T) {
    12  	input := new(MockUIInput)
    13  	m := testModule(t, "input-vars")
    14  	p := testProvider("aws")
    15  	p.ApplyFn = testApplyFn
    16  	p.DiffFn = testDiffFn
    17  	ctx := testContext2(t, &ContextOpts{
    18  		Module: m,
    19  		ProviderResolver: ResourceProviderResolverFixed(
    20  			map[string]ResourceProviderFactory{
    21  				"aws": testProviderFuncFixed(p),
    22  			},
    23  		),
    24  		Variables: map[string]interface{}{
    25  			"foo": "us-west-2",
    26  			"amis": []map[string]interface{}{
    27  				map[string]interface{}{
    28  					"us-east-1": "override",
    29  				},
    30  			},
    31  		},
    32  		UIInput: input,
    33  	})
    34  
    35  	input.InputReturnMap = map[string]string{
    36  		"var.foo": "us-east-1",
    37  	}
    38  
    39  	if err := ctx.Input(InputModeStd); err != nil {
    40  		t.Fatalf("err: %s", err)
    41  	}
    42  
    43  	if _, err := ctx.Plan(); err != nil {
    44  		t.Fatalf("err: %s", err)
    45  	}
    46  
    47  	state, err := ctx.Apply()
    48  	if err != nil {
    49  		t.Fatalf("err: %s", err)
    50  	}
    51  
    52  	actual := strings.TrimSpace(state.String())
    53  	expected := strings.TrimSpace(testTerraformInputVarsStr)
    54  	if actual != expected {
    55  		t.Fatalf("expected:\n%s\ngot:\n%s", expected, actual)
    56  	}
    57  }
    58  
    59  func TestContext2Input_moduleComputedOutputElement(t *testing.T) {
    60  	m := testModule(t, "input-module-computed-output-element")
    61  	p := testProvider("aws")
    62  	p.ApplyFn = testApplyFn
    63  	p.DiffFn = testDiffFn
    64  	ctx := testContext2(t, &ContextOpts{
    65  		Module: m,
    66  		ProviderResolver: ResourceProviderResolverFixed(
    67  			map[string]ResourceProviderFactory{
    68  				"aws": testProviderFuncFixed(p),
    69  			},
    70  		),
    71  	})
    72  
    73  	p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) {
    74  		return c, nil
    75  	}
    76  
    77  	if err := ctx.Input(InputModeStd); err != nil {
    78  		t.Fatalf("err: %s", err)
    79  	}
    80  }
    81  
    82  func TestContext2Input_badVarDefault(t *testing.T) {
    83  	m := testModule(t, "input-bad-var-default")
    84  	p := testProvider("aws")
    85  	p.ApplyFn = testApplyFn
    86  	p.DiffFn = testDiffFn
    87  	ctx := testContext2(t, &ContextOpts{
    88  		Module: m,
    89  		ProviderResolver: ResourceProviderResolverFixed(
    90  			map[string]ResourceProviderFactory{
    91  				"aws": testProviderFuncFixed(p),
    92  			},
    93  		),
    94  	})
    95  
    96  	p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) {
    97  		c.Config["foo"] = "bar"
    98  		return c, nil
    99  	}
   100  
   101  	if err := ctx.Input(InputModeStd); err != nil {
   102  		t.Fatalf("err: %s", err)
   103  	}
   104  }
   105  
   106  func TestContext2Input_provider(t *testing.T) {
   107  	m := testModule(t, "input-provider")
   108  	p := testProvider("aws")
   109  	p.ApplyFn = testApplyFn
   110  	p.DiffFn = testDiffFn
   111  	ctx := testContext2(t, &ContextOpts{
   112  		Module: m,
   113  		ProviderResolver: ResourceProviderResolverFixed(
   114  			map[string]ResourceProviderFactory{
   115  				"aws": testProviderFuncFixed(p),
   116  			},
   117  		),
   118  	})
   119  
   120  	var actual interface{}
   121  	p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) {
   122  		c.Config["foo"] = "bar"
   123  		return c, nil
   124  	}
   125  	p.ConfigureFn = func(c *ResourceConfig) error {
   126  		actual = c.Config["foo"]
   127  		return nil
   128  	}
   129  	p.ValidateFn = func(c *ResourceConfig) ([]string, []error) {
   130  		return nil, c.CheckSet([]string{"foo"})
   131  	}
   132  
   133  	if err := ctx.Input(InputModeStd); err != nil {
   134  		t.Fatalf("err: %s", err)
   135  	}
   136  
   137  	if _, err := ctx.Plan(); err != nil {
   138  		t.Fatalf("err: %s", err)
   139  	}
   140  
   141  	if _, err := ctx.Apply(); err != nil {
   142  		t.Fatalf("err: %s", err)
   143  	}
   144  
   145  	if !reflect.DeepEqual(actual, "bar") {
   146  		t.Fatalf("bad: %#v", actual)
   147  	}
   148  }
   149  
   150  func TestContext2Input_providerMulti(t *testing.T) {
   151  	m := testModule(t, "input-provider-multi")
   152  	p := testProvider("aws")
   153  	p.ApplyFn = testApplyFn
   154  	p.DiffFn = testDiffFn
   155  	ctx := testContext2(t, &ContextOpts{
   156  		Module: m,
   157  		ProviderResolver: ResourceProviderResolverFixed(
   158  			map[string]ResourceProviderFactory{
   159  				"aws": testProviderFuncFixed(p),
   160  			},
   161  		),
   162  	})
   163  
   164  	var actual []interface{}
   165  	var lock sync.Mutex
   166  	p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) {
   167  		c.Config["foo"] = "bar"
   168  		return c, nil
   169  	}
   170  	p.ConfigureFn = func(c *ResourceConfig) error {
   171  		lock.Lock()
   172  		defer lock.Unlock()
   173  		actual = append(actual, c.Config["foo"])
   174  		return nil
   175  	}
   176  	p.ValidateFn = func(c *ResourceConfig) ([]string, []error) {
   177  		return nil, c.CheckSet([]string{"foo"})
   178  	}
   179  
   180  	if err := ctx.Input(InputModeStd); err != nil {
   181  		t.Fatalf("err: %s", err)
   182  	}
   183  
   184  	if _, err := ctx.Plan(); err != nil {
   185  		t.Fatalf("err: %s", err)
   186  	}
   187  
   188  	if _, err := ctx.Apply(); err != nil {
   189  		t.Fatalf("err: %s", err)
   190  	}
   191  
   192  	expected := []interface{}{"bar", "bar"}
   193  	if !reflect.DeepEqual(actual, expected) {
   194  		t.Fatalf("bad: %#v", actual)
   195  	}
   196  }
   197  
   198  func TestContext2Input_providerOnce(t *testing.T) {
   199  	m := testModule(t, "input-provider-once")
   200  	p := testProvider("aws")
   201  	p.ApplyFn = testApplyFn
   202  	p.DiffFn = testDiffFn
   203  	ctx := testContext2(t, &ContextOpts{
   204  		Module: m,
   205  		ProviderResolver: ResourceProviderResolverFixed(
   206  			map[string]ResourceProviderFactory{
   207  				"aws": testProviderFuncFixed(p),
   208  			},
   209  		),
   210  	})
   211  
   212  	count := 0
   213  	p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) {
   214  		count++
   215  		_, set := c.Config["from_input"]
   216  
   217  		if count == 1 {
   218  			if set {
   219  				return nil, errors.New("from_input should not be set")
   220  			}
   221  			c.Config["from_input"] = "x"
   222  		}
   223  
   224  		if count > 1 && !set {
   225  			return nil, errors.New("from_input should be set")
   226  		}
   227  
   228  		return c, nil
   229  	}
   230  
   231  	if err := ctx.Input(InputModeStd); err != nil {
   232  		t.Fatalf("err: %s", err)
   233  	}
   234  }
   235  
   236  func TestContext2Input_providerId(t *testing.T) {
   237  	input := new(MockUIInput)
   238  	m := testModule(t, "input-provider")
   239  	p := testProvider("aws")
   240  	p.ApplyFn = testApplyFn
   241  	p.DiffFn = testDiffFn
   242  	ctx := testContext2(t, &ContextOpts{
   243  		Module: m,
   244  		ProviderResolver: ResourceProviderResolverFixed(
   245  			map[string]ResourceProviderFactory{
   246  				"aws": testProviderFuncFixed(p),
   247  			},
   248  		),
   249  		UIInput: input,
   250  	})
   251  
   252  	var actual interface{}
   253  	p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) {
   254  		v, err := i.Input(&InputOpts{Id: "foo"})
   255  		if err != nil {
   256  			return nil, err
   257  		}
   258  
   259  		c.Config["foo"] = v
   260  		return c, nil
   261  	}
   262  	p.ConfigureFn = func(c *ResourceConfig) error {
   263  		actual = c.Config["foo"]
   264  		return nil
   265  	}
   266  
   267  	input.InputReturnMap = map[string]string{
   268  		"provider.aws.foo": "bar",
   269  	}
   270  
   271  	if err := ctx.Input(InputModeStd); err != nil {
   272  		t.Fatalf("err: %s", err)
   273  	}
   274  
   275  	if _, err := ctx.Plan(); err != nil {
   276  		t.Fatalf("err: %s", err)
   277  	}
   278  
   279  	if _, err := ctx.Apply(); err != nil {
   280  		t.Fatalf("err: %s", err)
   281  	}
   282  
   283  	if !reflect.DeepEqual(actual, "bar") {
   284  		t.Fatalf("bad: %#v", actual)
   285  	}
   286  }
   287  
   288  func TestContext2Input_providerOnly(t *testing.T) {
   289  	input := new(MockUIInput)
   290  	m := testModule(t, "input-provider-vars")
   291  	p := testProvider("aws")
   292  	p.ApplyFn = testApplyFn
   293  	p.DiffFn = testDiffFn
   294  	ctx := testContext2(t, &ContextOpts{
   295  		Module: m,
   296  		ProviderResolver: ResourceProviderResolverFixed(
   297  			map[string]ResourceProviderFactory{
   298  				"aws": testProviderFuncFixed(p),
   299  			},
   300  		),
   301  		Variables: map[string]interface{}{
   302  			"foo": "us-west-2",
   303  		},
   304  		UIInput: input,
   305  	})
   306  
   307  	input.InputReturnMap = map[string]string{
   308  		"var.foo": "us-east-1",
   309  	}
   310  
   311  	var actual interface{}
   312  	p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) {
   313  		c.Config["foo"] = "bar"
   314  		return c, nil
   315  	}
   316  	p.ConfigureFn = func(c *ResourceConfig) error {
   317  		actual = c.Config["foo"]
   318  		return nil
   319  	}
   320  
   321  	if err := ctx.Input(InputModeProvider); err != nil {
   322  		t.Fatalf("err: %s", err)
   323  	}
   324  
   325  	if _, err := ctx.Plan(); err != nil {
   326  		t.Fatalf("err: %s", err)
   327  	}
   328  
   329  	state, err := ctx.Apply()
   330  	if err != nil {
   331  		t.Fatalf("err: %s", err)
   332  	}
   333  
   334  	if !reflect.DeepEqual(actual, "bar") {
   335  		t.Fatalf("bad: %#v", actual)
   336  	}
   337  
   338  	actualStr := strings.TrimSpace(state.String())
   339  	expectedStr := strings.TrimSpace(testTerraformInputProviderOnlyStr)
   340  	if actualStr != expectedStr {
   341  		t.Fatalf("bad: \n%s", actualStr)
   342  	}
   343  }
   344  
   345  func TestContext2Input_providerVars(t *testing.T) {
   346  	input := new(MockUIInput)
   347  	m := testModule(t, "input-provider-with-vars")
   348  	p := testProvider("aws")
   349  	p.ApplyFn = testApplyFn
   350  	p.DiffFn = testDiffFn
   351  	ctx := testContext2(t, &ContextOpts{
   352  		Module: m,
   353  		ProviderResolver: ResourceProviderResolverFixed(
   354  			map[string]ResourceProviderFactory{
   355  				"aws": testProviderFuncFixed(p),
   356  			},
   357  		),
   358  		Variables: map[string]interface{}{
   359  			"foo": "bar",
   360  		},
   361  		UIInput: input,
   362  	})
   363  
   364  	input.InputReturnMap = map[string]string{
   365  		"var.foo": "bar",
   366  	}
   367  
   368  	var actual interface{}
   369  	p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) {
   370  		c.Config["bar"] = "baz"
   371  		return c, nil
   372  	}
   373  	p.ConfigureFn = func(c *ResourceConfig) error {
   374  		actual, _ = c.Get("foo")
   375  		return nil
   376  	}
   377  
   378  	if err := ctx.Input(InputModeStd); err != nil {
   379  		t.Fatalf("err: %s", err)
   380  	}
   381  
   382  	if _, err := ctx.Plan(); err != nil {
   383  		t.Fatalf("err: %s", err)
   384  	}
   385  
   386  	if _, err := ctx.Apply(); err != nil {
   387  		t.Fatalf("err: %s", err)
   388  	}
   389  
   390  	if !reflect.DeepEqual(actual, "bar") {
   391  		t.Fatalf("bad: %#v", actual)
   392  	}
   393  }
   394  
   395  func TestContext2Input_providerVarsModuleInherit(t *testing.T) {
   396  	input := new(MockUIInput)
   397  	m := testModule(t, "input-provider-with-vars-and-module")
   398  	p := testProvider("aws")
   399  	p.ApplyFn = testApplyFn
   400  	p.DiffFn = testDiffFn
   401  	ctx := testContext2(t, &ContextOpts{
   402  		Module: m,
   403  		ProviderResolver: ResourceProviderResolverFixed(
   404  			map[string]ResourceProviderFactory{
   405  				"aws": testProviderFuncFixed(p),
   406  			},
   407  		),
   408  		UIInput: input,
   409  	})
   410  
   411  	p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) {
   412  		if errs := c.CheckSet([]string{"access_key"}); len(errs) > 0 {
   413  			return c, errs[0]
   414  		}
   415  		return c, nil
   416  	}
   417  	p.ConfigureFn = func(c *ResourceConfig) error {
   418  		return nil
   419  	}
   420  
   421  	if err := ctx.Input(InputModeStd); err != nil {
   422  		t.Fatalf("err: %s", err)
   423  	}
   424  }
   425  
   426  func TestContext2Input_varOnly(t *testing.T) {
   427  	input := new(MockUIInput)
   428  	m := testModule(t, "input-provider-vars")
   429  	p := testProvider("aws")
   430  	p.ApplyFn = testApplyFn
   431  	p.DiffFn = testDiffFn
   432  	ctx := testContext2(t, &ContextOpts{
   433  		Module: m,
   434  		ProviderResolver: ResourceProviderResolverFixed(
   435  			map[string]ResourceProviderFactory{
   436  				"aws": testProviderFuncFixed(p),
   437  			},
   438  		),
   439  		Variables: map[string]interface{}{
   440  			"foo": "us-west-2",
   441  		},
   442  		UIInput: input,
   443  	})
   444  
   445  	input.InputReturnMap = map[string]string{
   446  		"var.foo": "us-east-1",
   447  	}
   448  
   449  	var actual interface{}
   450  	p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) {
   451  		c.Raw["foo"] = "bar"
   452  		return c, nil
   453  	}
   454  	p.ConfigureFn = func(c *ResourceConfig) error {
   455  		actual = c.Raw["foo"]
   456  		return nil
   457  	}
   458  
   459  	if err := ctx.Input(InputModeVar); err != nil {
   460  		t.Fatalf("err: %s", err)
   461  	}
   462  
   463  	if _, err := ctx.Plan(); err != nil {
   464  		t.Fatalf("err: %s", err)
   465  	}
   466  
   467  	state, err := ctx.Apply()
   468  	if err != nil {
   469  		t.Fatalf("err: %s", err)
   470  	}
   471  
   472  	if reflect.DeepEqual(actual, "bar") {
   473  		t.Fatalf("bad: %#v", actual)
   474  	}
   475  
   476  	actualStr := strings.TrimSpace(state.String())
   477  	expectedStr := strings.TrimSpace(testTerraformInputVarOnlyStr)
   478  	if actualStr != expectedStr {
   479  		t.Fatalf("bad: \n%s", actualStr)
   480  	}
   481  }
   482  
   483  func TestContext2Input_varOnlyUnset(t *testing.T) {
   484  	input := new(MockUIInput)
   485  	m := testModule(t, "input-vars-unset")
   486  	p := testProvider("aws")
   487  	p.ApplyFn = testApplyFn
   488  	p.DiffFn = testDiffFn
   489  	ctx := testContext2(t, &ContextOpts{
   490  		Module: m,
   491  		ProviderResolver: ResourceProviderResolverFixed(
   492  			map[string]ResourceProviderFactory{
   493  				"aws": testProviderFuncFixed(p),
   494  			},
   495  		),
   496  		Variables: map[string]interface{}{
   497  			"foo": "foovalue",
   498  		},
   499  		UIInput: input,
   500  	})
   501  
   502  	input.InputReturnMap = map[string]string{
   503  		"var.foo": "nope",
   504  		"var.bar": "baz",
   505  	}
   506  
   507  	if err := ctx.Input(InputModeVar | InputModeVarUnset); err != nil {
   508  		t.Fatalf("err: %s", err)
   509  	}
   510  
   511  	if _, err := ctx.Plan(); err != nil {
   512  		t.Fatalf("err: %s", err)
   513  	}
   514  
   515  	state, err := ctx.Apply()
   516  	if err != nil {
   517  		t.Fatalf("err: %s", err)
   518  	}
   519  
   520  	actualStr := strings.TrimSpace(state.String())
   521  	expectedStr := strings.TrimSpace(testTerraformInputVarOnlyUnsetStr)
   522  	if actualStr != expectedStr {
   523  		t.Fatalf("bad: \n%s", actualStr)
   524  	}
   525  }
   526  
   527  func TestContext2Input_varWithDefault(t *testing.T) {
   528  	input := new(MockUIInput)
   529  	m := testModule(t, "input-var-default")
   530  	p := testProvider("aws")
   531  	p.ApplyFn = testApplyFn
   532  	p.DiffFn = testDiffFn
   533  	ctx := testContext2(t, &ContextOpts{
   534  		Module: m,
   535  		ProviderResolver: ResourceProviderResolverFixed(
   536  			map[string]ResourceProviderFactory{
   537  				"aws": testProviderFuncFixed(p),
   538  			},
   539  		),
   540  		Variables: map[string]interface{}{},
   541  		UIInput:   input,
   542  	})
   543  
   544  	input.InputFn = func(opts *InputOpts) (string, error) {
   545  		t.Fatalf(
   546  			"Input should never be called because variable has a default: %#v", opts)
   547  		return "", nil
   548  	}
   549  
   550  	if err := ctx.Input(InputModeVar | InputModeVarUnset); err != nil {
   551  		t.Fatalf("err: %s", err)
   552  	}
   553  
   554  	if _, err := ctx.Plan(); err != nil {
   555  		t.Fatalf("err: %s", err)
   556  	}
   557  
   558  	state, err := ctx.Apply()
   559  	if err != nil {
   560  		t.Fatalf("err: %s", err)
   561  	}
   562  
   563  	actualStr := strings.TrimSpace(state.String())
   564  	expectedStr := strings.TrimSpace(`
   565  aws_instance.foo:
   566    ID = foo
   567    foo = 123
   568    type = aws_instance
   569  	`)
   570  	if actualStr != expectedStr {
   571  		t.Fatalf("expected: \n%s\ngot: \n%s\n", expectedStr, actualStr)
   572  	}
   573  }
   574  
   575  func TestContext2Input_varPartiallyComputed(t *testing.T) {
   576  	input := new(MockUIInput)
   577  	m := testModule(t, "input-var-partially-computed")
   578  	p := testProvider("aws")
   579  	p.ApplyFn = testApplyFn
   580  	p.DiffFn = testDiffFn
   581  	ctx := testContext2(t, &ContextOpts{
   582  		Module: m,
   583  		ProviderResolver: ResourceProviderResolverFixed(
   584  			map[string]ResourceProviderFactory{
   585  				"aws": testProviderFuncFixed(p),
   586  			},
   587  		),
   588  		Variables: map[string]interface{}{
   589  			"foo": "foovalue",
   590  		},
   591  		UIInput: input,
   592  		State: &State{
   593  			Modules: []*ModuleState{
   594  				&ModuleState{
   595  					Path: rootModulePath,
   596  					Resources: map[string]*ResourceState{
   597  						"aws_instance.foo": &ResourceState{
   598  							Type: "aws_instance",
   599  							Primary: &InstanceState{
   600  								ID: "i-abc123",
   601  								Attributes: map[string]string{
   602  									"id": "i-abc123",
   603  								},
   604  							},
   605  						},
   606  					},
   607  				},
   608  				&ModuleState{
   609  					Path: append(rootModulePath, "child"),
   610  					Resources: map[string]*ResourceState{
   611  						"aws_instance.mod": &ResourceState{
   612  							Type: "aws_instance",
   613  							Primary: &InstanceState{
   614  								ID: "i-bcd345",
   615  								Attributes: map[string]string{
   616  									"id":    "i-bcd345",
   617  									"value": "one,i-abc123",
   618  								},
   619  							},
   620  						},
   621  					},
   622  				},
   623  			},
   624  		},
   625  	})
   626  
   627  	if err := ctx.Input(InputModeStd); err != nil {
   628  		t.Fatalf("err: %s", err)
   629  	}
   630  
   631  	if _, err := ctx.Plan(); err != nil {
   632  		t.Fatalf("err: %s", err)
   633  	}
   634  }
   635  
   636  // Module variables weren't being interpolated during the Input walk.
   637  // https://github.com/hashicorp/terraform/issues/5322
   638  func TestContext2Input_interpolateVar(t *testing.T) {
   639  	input := new(MockUIInput)
   640  
   641  	m := testModule(t, "input-interpolate-var")
   642  	p := testProvider("null")
   643  	p.ApplyFn = testApplyFn
   644  	p.DiffFn = testDiffFn
   645  
   646  	ctx := testContext2(t, &ContextOpts{
   647  		Module: m,
   648  		ProviderResolver: ResourceProviderResolverFixed(
   649  			map[string]ResourceProviderFactory{
   650  				"template": testProviderFuncFixed(p),
   651  			},
   652  		),
   653  		UIInput: input,
   654  	})
   655  
   656  	if err := ctx.Input(InputModeStd); err != nil {
   657  		t.Fatalf("err: %s", err)
   658  	}
   659  }
   660  
   661  func TestContext2Input_hcl(t *testing.T) {
   662  	input := new(MockUIInput)
   663  	m := testModule(t, "input-hcl")
   664  	p := testProvider("hcl")
   665  	p.ApplyFn = testApplyFn
   666  	p.DiffFn = testDiffFn
   667  	ctx := testContext2(t, &ContextOpts{
   668  		Module: m,
   669  		ProviderResolver: ResourceProviderResolverFixed(
   670  			map[string]ResourceProviderFactory{
   671  				"hcl": testProviderFuncFixed(p),
   672  			},
   673  		),
   674  		Variables: map[string]interface{}{},
   675  		UIInput:   input,
   676  	})
   677  
   678  	input.InputReturnMap = map[string]string{
   679  		"var.listed": `["a", "b"]`,
   680  		"var.mapped": `{x = "y", w = "z"}`,
   681  	}
   682  
   683  	if err := ctx.Input(InputModeVar | InputModeVarUnset); err != nil {
   684  		t.Fatalf("err: %s", err)
   685  	}
   686  
   687  	if _, err := ctx.Plan(); err != nil {
   688  		t.Fatalf("err: %s", err)
   689  	}
   690  
   691  	state, err := ctx.Apply()
   692  	if err != nil {
   693  		t.Fatalf("err: %s", err)
   694  	}
   695  
   696  	actualStr := strings.TrimSpace(state.String())
   697  	expectedStr := strings.TrimSpace(testTerraformInputHCL)
   698  	if actualStr != expectedStr {
   699  		t.Logf("expected: \n%s", expectedStr)
   700  		t.Fatalf("bad: \n%s", actualStr)
   701  	}
   702  }
   703  
   704  // adding a list interpolation in fails to interpolate the count variable
   705  func TestContext2Input_submoduleTriggersInvalidCount(t *testing.T) {
   706  	input := new(MockUIInput)
   707  	m := testModule(t, "input-submodule-count")
   708  	p := testProvider("aws")
   709  	p.ApplyFn = testApplyFn
   710  	p.DiffFn = testDiffFn
   711  	ctx := testContext2(t, &ContextOpts{
   712  		Module: m,
   713  		ProviderResolver: ResourceProviderResolverFixed(
   714  			map[string]ResourceProviderFactory{
   715  				"aws": testProviderFuncFixed(p),
   716  			},
   717  		),
   718  		UIInput: input,
   719  	})
   720  
   721  	p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) {
   722  		return c, nil
   723  	}
   724  	p.ConfigureFn = func(c *ResourceConfig) error {
   725  		return nil
   726  	}
   727  
   728  	if err := ctx.Input(InputModeStd); err != nil {
   729  		t.Fatalf("err: %s", err)
   730  	}
   731  }
   732  
   733  // In this case, a module variable can't be resolved from a data source until
   734  // it's refreshed, but it can't be refreshed during Input.
   735  func TestContext2Input_dataSourceRequiresRefresh(t *testing.T) {
   736  	input := new(MockUIInput)
   737  	p := testProvider("null")
   738  	m := testModule(t, "input-module-data-vars")
   739  
   740  	p.ReadDataDiffFn = testDataDiffFn
   741  
   742  	state := &State{
   743  		Modules: []*ModuleState{
   744  			&ModuleState{
   745  				Path: rootModulePath,
   746  				Resources: map[string]*ResourceState{
   747  					"data.null_data_source.bar": &ResourceState{
   748  						Type: "null_data_source",
   749  						Primary: &InstanceState{
   750  							ID: "-",
   751  							Attributes: map[string]string{
   752  								"foo.#": "1",
   753  								"foo.0": "a",
   754  								// foo.1 exists in the data source, but needs to be refreshed.
   755  							},
   756  						},
   757  					},
   758  				},
   759  			},
   760  		},
   761  	}
   762  
   763  	ctx := testContext2(t, &ContextOpts{
   764  		Module: m,
   765  		ProviderResolver: ResourceProviderResolverFixed(
   766  			map[string]ResourceProviderFactory{
   767  				"null": testProviderFuncFixed(p),
   768  			},
   769  		),
   770  		State:   state,
   771  		UIInput: input,
   772  	})
   773  
   774  	if err := ctx.Input(InputModeStd); err != nil {
   775  		t.Fatalf("err: %s", err)
   776  	}
   777  
   778  	// ensure that plan works after Refresh
   779  	if _, err := ctx.Refresh(); err != nil {
   780  		t.Fatalf("err: %s", err)
   781  	}
   782  	if _, err := ctx.Plan(); err != nil {
   783  		t.Fatalf("err: %s", err)
   784  	}
   785  }