github.com/LorbusChris/terraform@v0.11.12-beta1/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    provider = provider.aws
   568    foo = 123
   569    type = aws_instance
   570  	`)
   571  	if actualStr != expectedStr {
   572  		t.Fatalf("expected: \n%s\ngot: \n%s\n", expectedStr, actualStr)
   573  	}
   574  }
   575  
   576  func TestContext2Input_varPartiallyComputed(t *testing.T) {
   577  	input := new(MockUIInput)
   578  	m := testModule(t, "input-var-partially-computed")
   579  	p := testProvider("aws")
   580  	p.ApplyFn = testApplyFn
   581  	p.DiffFn = testDiffFn
   582  	ctx := testContext2(t, &ContextOpts{
   583  		Module: m,
   584  		ProviderResolver: ResourceProviderResolverFixed(
   585  			map[string]ResourceProviderFactory{
   586  				"aws": testProviderFuncFixed(p),
   587  			},
   588  		),
   589  		Variables: map[string]interface{}{
   590  			"foo": "foovalue",
   591  		},
   592  		UIInput: input,
   593  		State: &State{
   594  			Modules: []*ModuleState{
   595  				&ModuleState{
   596  					Path: rootModulePath,
   597  					Resources: map[string]*ResourceState{
   598  						"aws_instance.foo": &ResourceState{
   599  							Type: "aws_instance",
   600  							Primary: &InstanceState{
   601  								ID: "i-abc123",
   602  								Attributes: map[string]string{
   603  									"id": "i-abc123",
   604  								},
   605  							},
   606  						},
   607  					},
   608  				},
   609  				&ModuleState{
   610  					Path: append(rootModulePath, "child"),
   611  					Resources: map[string]*ResourceState{
   612  						"aws_instance.mod": &ResourceState{
   613  							Type: "aws_instance",
   614  							Primary: &InstanceState{
   615  								ID: "i-bcd345",
   616  								Attributes: map[string]string{
   617  									"id":    "i-bcd345",
   618  									"value": "one,i-abc123",
   619  								},
   620  							},
   621  						},
   622  					},
   623  				},
   624  			},
   625  		},
   626  	})
   627  
   628  	if err := ctx.Input(InputModeStd); err != nil {
   629  		t.Fatalf("err: %s", err)
   630  	}
   631  
   632  	if _, err := ctx.Plan(); err != nil {
   633  		t.Fatalf("err: %s", err)
   634  	}
   635  }
   636  
   637  // Module variables weren't being interpolated during the Input walk.
   638  // https://github.com/hashicorp/terraform/issues/5322
   639  func TestContext2Input_interpolateVar(t *testing.T) {
   640  	input := new(MockUIInput)
   641  
   642  	m := testModule(t, "input-interpolate-var")
   643  	p := testProvider("null")
   644  	p.ApplyFn = testApplyFn
   645  	p.DiffFn = testDiffFn
   646  
   647  	ctx := testContext2(t, &ContextOpts{
   648  		Module: m,
   649  		ProviderResolver: ResourceProviderResolverFixed(
   650  			map[string]ResourceProviderFactory{
   651  				"template": testProviderFuncFixed(p),
   652  			},
   653  		),
   654  		UIInput: input,
   655  	})
   656  
   657  	if err := ctx.Input(InputModeStd); err != nil {
   658  		t.Fatalf("err: %s", err)
   659  	}
   660  }
   661  
   662  func TestContext2Input_hcl(t *testing.T) {
   663  	input := new(MockUIInput)
   664  	m := testModule(t, "input-hcl")
   665  	p := testProvider("hcl")
   666  	p.ApplyFn = testApplyFn
   667  	p.DiffFn = testDiffFn
   668  	ctx := testContext2(t, &ContextOpts{
   669  		Module: m,
   670  		ProviderResolver: ResourceProviderResolverFixed(
   671  			map[string]ResourceProviderFactory{
   672  				"hcl": testProviderFuncFixed(p),
   673  			},
   674  		),
   675  		Variables: map[string]interface{}{},
   676  		UIInput:   input,
   677  	})
   678  
   679  	input.InputReturnMap = map[string]string{
   680  		"var.listed": `["a", "b"]`,
   681  		"var.mapped": `{x = "y", w = "z"}`,
   682  	}
   683  
   684  	if err := ctx.Input(InputModeVar | InputModeVarUnset); err != nil {
   685  		t.Fatalf("err: %s", err)
   686  	}
   687  
   688  	if _, err := ctx.Plan(); err != nil {
   689  		t.Fatalf("err: %s", err)
   690  	}
   691  
   692  	state, err := ctx.Apply()
   693  	if err != nil {
   694  		t.Fatalf("err: %s", err)
   695  	}
   696  
   697  	actualStr := strings.TrimSpace(state.String())
   698  	expectedStr := strings.TrimSpace(testTerraformInputHCL)
   699  	if actualStr != expectedStr {
   700  		t.Logf("expected: \n%s", expectedStr)
   701  		t.Fatalf("bad: \n%s", actualStr)
   702  	}
   703  }
   704  
   705  // adding a list interpolation in fails to interpolate the count variable
   706  func TestContext2Input_submoduleTriggersInvalidCount(t *testing.T) {
   707  	input := new(MockUIInput)
   708  	m := testModule(t, "input-submodule-count")
   709  	p := testProvider("aws")
   710  	p.ApplyFn = testApplyFn
   711  	p.DiffFn = testDiffFn
   712  	ctx := testContext2(t, &ContextOpts{
   713  		Module: m,
   714  		ProviderResolver: ResourceProviderResolverFixed(
   715  			map[string]ResourceProviderFactory{
   716  				"aws": testProviderFuncFixed(p),
   717  			},
   718  		),
   719  		UIInput: input,
   720  	})
   721  
   722  	p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) {
   723  		return c, nil
   724  	}
   725  	p.ConfigureFn = func(c *ResourceConfig) error {
   726  		return nil
   727  	}
   728  
   729  	if err := ctx.Input(InputModeStd); err != nil {
   730  		t.Fatalf("err: %s", err)
   731  	}
   732  }
   733  
   734  // In this case, a module variable can't be resolved from a data source until
   735  // it's refreshed, but it can't be refreshed during Input.
   736  func TestContext2Input_dataSourceRequiresRefresh(t *testing.T) {
   737  	input := new(MockUIInput)
   738  	p := testProvider("null")
   739  	m := testModule(t, "input-module-data-vars")
   740  
   741  	p.ReadDataDiffFn = testDataDiffFn
   742  
   743  	state := &State{
   744  		Modules: []*ModuleState{
   745  			&ModuleState{
   746  				Path: rootModulePath,
   747  				Resources: map[string]*ResourceState{
   748  					"data.null_data_source.bar": &ResourceState{
   749  						Type: "null_data_source",
   750  						Primary: &InstanceState{
   751  							ID: "-",
   752  							Attributes: map[string]string{
   753  								"foo.#": "1",
   754  								"foo.0": "a",
   755  								// foo.1 exists in the data source, but needs to be refreshed.
   756  							},
   757  						},
   758  					},
   759  				},
   760  			},
   761  		},
   762  	}
   763  
   764  	ctx := testContext2(t, &ContextOpts{
   765  		Module: m,
   766  		ProviderResolver: ResourceProviderResolverFixed(
   767  			map[string]ResourceProviderFactory{
   768  				"null": testProviderFuncFixed(p),
   769  			},
   770  		),
   771  		State:   state,
   772  		UIInput: input,
   773  	})
   774  
   775  	if err := ctx.Input(InputModeStd); err != nil {
   776  		t.Fatalf("err: %s", err)
   777  	}
   778  
   779  	// ensure that plan works after Refresh
   780  	if _, err := ctx.Refresh(); err != nil {
   781  		t.Fatalf("err: %s", err)
   782  	}
   783  	if _, err := ctx.Plan(); err != nil {
   784  		t.Fatalf("err: %s", err)
   785  	}
   786  }