github.com/memsql/terraform@v0.7.0-rc2.0.20160706152241-21e2173e0a32/terraform/context_input_test.go (about)

     1  package terraform
     2  
     3  import (
     4  	"reflect"
     5  	"strings"
     6  	"sync"
     7  	"testing"
     8  )
     9  
    10  func TestContext2Input(t *testing.T) {
    11  	input := new(MockUIInput)
    12  	m := testModule(t, "input-vars")
    13  	p := testProvider("aws")
    14  	p.ApplyFn = testApplyFn
    15  	p.DiffFn = testDiffFn
    16  	ctx := testContext2(t, &ContextOpts{
    17  		Module: m,
    18  		Providers: map[string]ResourceProviderFactory{
    19  			"aws": testProviderFuncFixed(p),
    20  		},
    21  		Variables: map[string]string{
    22  			"foo":            "us-west-2",
    23  			"amis.us-east-1": "override",
    24  		},
    25  		UIInput: input,
    26  	})
    27  
    28  	input.InputReturnMap = map[string]string{
    29  		"var.foo": "us-east-1",
    30  	}
    31  
    32  	if err := ctx.Input(InputModeStd); err != nil {
    33  		t.Fatalf("err: %s", err)
    34  	}
    35  
    36  	if _, err := ctx.Plan(); err != nil {
    37  		t.Fatalf("err: %s", err)
    38  	}
    39  
    40  	state, err := ctx.Apply()
    41  	if err != nil {
    42  		t.Fatalf("err: %s", err)
    43  	}
    44  
    45  	actual := strings.TrimSpace(state.String())
    46  	expected := strings.TrimSpace(testTerraformInputVarsStr)
    47  	if actual != expected {
    48  		t.Fatalf("expected:\n%s\ngot:\n%s", expected, actual)
    49  	}
    50  }
    51  
    52  func TestContext2Input_moduleComputedOutputElement(t *testing.T) {
    53  	m := testModule(t, "input-module-computed-output-element")
    54  	p := testProvider("aws")
    55  	p.ApplyFn = testApplyFn
    56  	p.DiffFn = testDiffFn
    57  	ctx := testContext2(t, &ContextOpts{
    58  		Module: m,
    59  		Providers: map[string]ResourceProviderFactory{
    60  			"aws": testProviderFuncFixed(p),
    61  		},
    62  	})
    63  
    64  	p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) {
    65  		return c, nil
    66  	}
    67  
    68  	if err := ctx.Input(InputModeStd); err != nil {
    69  		t.Fatalf("err: %s", err)
    70  	}
    71  }
    72  
    73  func TestContext2Input_badVarDefault(t *testing.T) {
    74  	m := testModule(t, "input-bad-var-default")
    75  	p := testProvider("aws")
    76  	p.ApplyFn = testApplyFn
    77  	p.DiffFn = testDiffFn
    78  	ctx := testContext2(t, &ContextOpts{
    79  		Module: m,
    80  		Providers: map[string]ResourceProviderFactory{
    81  			"aws": testProviderFuncFixed(p),
    82  		},
    83  	})
    84  
    85  	p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) {
    86  		c.Config["foo"] = "bar"
    87  		return c, nil
    88  	}
    89  
    90  	if err := ctx.Input(InputModeStd); err != nil {
    91  		t.Fatalf("err: %s", err)
    92  	}
    93  }
    94  
    95  func TestContext2Input_provider(t *testing.T) {
    96  	m := testModule(t, "input-provider")
    97  	p := testProvider("aws")
    98  	p.ApplyFn = testApplyFn
    99  	p.DiffFn = testDiffFn
   100  	ctx := testContext2(t, &ContextOpts{
   101  		Module: m,
   102  		Providers: map[string]ResourceProviderFactory{
   103  			"aws": testProviderFuncFixed(p),
   104  		},
   105  	})
   106  
   107  	var actual interface{}
   108  	p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) {
   109  		c.Config["foo"] = "bar"
   110  		return c, nil
   111  	}
   112  	p.ConfigureFn = func(c *ResourceConfig) error {
   113  		actual = c.Config["foo"]
   114  		return nil
   115  	}
   116  	p.ValidateFn = func(c *ResourceConfig) ([]string, []error) {
   117  		return nil, c.CheckSet([]string{"foo"})
   118  	}
   119  
   120  	if err := ctx.Input(InputModeStd); err != nil {
   121  		t.Fatalf("err: %s", err)
   122  	}
   123  
   124  	if _, err := ctx.Plan(); err != nil {
   125  		t.Fatalf("err: %s", err)
   126  	}
   127  
   128  	if _, err := ctx.Apply(); err != nil {
   129  		t.Fatalf("err: %s", err)
   130  	}
   131  
   132  	if !reflect.DeepEqual(actual, "bar") {
   133  		t.Fatalf("bad: %#v", actual)
   134  	}
   135  }
   136  
   137  func TestContext2Input_providerMulti(t *testing.T) {
   138  	m := testModule(t, "input-provider-multi")
   139  	p := testProvider("aws")
   140  	p.ApplyFn = testApplyFn
   141  	p.DiffFn = testDiffFn
   142  	ctx := testContext2(t, &ContextOpts{
   143  		Module: m,
   144  		Providers: map[string]ResourceProviderFactory{
   145  			"aws": testProviderFuncFixed(p),
   146  		},
   147  	})
   148  
   149  	var actual []interface{}
   150  	var lock sync.Mutex
   151  	p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) {
   152  		c.Config["foo"] = "bar"
   153  		return c, nil
   154  	}
   155  	p.ConfigureFn = func(c *ResourceConfig) error {
   156  		lock.Lock()
   157  		defer lock.Unlock()
   158  		actual = append(actual, c.Config["foo"])
   159  		return nil
   160  	}
   161  	p.ValidateFn = func(c *ResourceConfig) ([]string, []error) {
   162  		return nil, c.CheckSet([]string{"foo"})
   163  	}
   164  
   165  	if err := ctx.Input(InputModeStd); err != nil {
   166  		t.Fatalf("err: %s", err)
   167  	}
   168  
   169  	if _, err := ctx.Plan(); err != nil {
   170  		t.Fatalf("err: %s", err)
   171  	}
   172  
   173  	if _, err := ctx.Apply(); err != nil {
   174  		t.Fatalf("err: %s", err)
   175  	}
   176  
   177  	expected := []interface{}{"bar", "bar"}
   178  	if !reflect.DeepEqual(actual, expected) {
   179  		t.Fatalf("bad: %#v", actual)
   180  	}
   181  }
   182  
   183  func TestContext2Input_providerOnce(t *testing.T) {
   184  	m := testModule(t, "input-provider-once")
   185  	p := testProvider("aws")
   186  	p.ApplyFn = testApplyFn
   187  	p.DiffFn = testDiffFn
   188  	ctx := testContext2(t, &ContextOpts{
   189  		Module: m,
   190  		Providers: map[string]ResourceProviderFactory{
   191  			"aws": testProviderFuncFixed(p),
   192  		},
   193  	})
   194  
   195  	count := 0
   196  	p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) {
   197  		count++
   198  		return nil, nil
   199  	}
   200  
   201  	if err := ctx.Input(InputModeStd); err != nil {
   202  		t.Fatalf("err: %s", err)
   203  	}
   204  
   205  	if count != 1 {
   206  		t.Fatalf("should only be called once: %d", count)
   207  	}
   208  }
   209  
   210  func TestContext2Input_providerId(t *testing.T) {
   211  	input := new(MockUIInput)
   212  	m := testModule(t, "input-provider")
   213  	p := testProvider("aws")
   214  	p.ApplyFn = testApplyFn
   215  	p.DiffFn = testDiffFn
   216  	ctx := testContext2(t, &ContextOpts{
   217  		Module: m,
   218  		Providers: map[string]ResourceProviderFactory{
   219  			"aws": testProviderFuncFixed(p),
   220  		},
   221  		UIInput: input,
   222  	})
   223  
   224  	var actual interface{}
   225  	p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) {
   226  		v, err := i.Input(&InputOpts{Id: "foo"})
   227  		if err != nil {
   228  			return nil, err
   229  		}
   230  
   231  		c.Config["foo"] = v
   232  		return c, nil
   233  	}
   234  	p.ConfigureFn = func(c *ResourceConfig) error {
   235  		actual = c.Config["foo"]
   236  		return nil
   237  	}
   238  
   239  	input.InputReturnMap = map[string]string{
   240  		"provider.aws.foo": "bar",
   241  	}
   242  
   243  	if err := ctx.Input(InputModeStd); err != nil {
   244  		t.Fatalf("err: %s", err)
   245  	}
   246  
   247  	if _, err := ctx.Plan(); err != nil {
   248  		t.Fatalf("err: %s", err)
   249  	}
   250  
   251  	if _, err := ctx.Apply(); err != nil {
   252  		t.Fatalf("err: %s", err)
   253  	}
   254  
   255  	if !reflect.DeepEqual(actual, "bar") {
   256  		t.Fatalf("bad: %#v", actual)
   257  	}
   258  }
   259  
   260  func TestContext2Input_providerOnly(t *testing.T) {
   261  	input := new(MockUIInput)
   262  	m := testModule(t, "input-provider-vars")
   263  	p := testProvider("aws")
   264  	p.ApplyFn = testApplyFn
   265  	p.DiffFn = testDiffFn
   266  	ctx := testContext2(t, &ContextOpts{
   267  		Module: m,
   268  		Providers: map[string]ResourceProviderFactory{
   269  			"aws": testProviderFuncFixed(p),
   270  		},
   271  		Variables: map[string]string{
   272  			"foo": "us-west-2",
   273  		},
   274  		UIInput: input,
   275  	})
   276  
   277  	input.InputReturnMap = map[string]string{
   278  		"var.foo": "us-east-1",
   279  	}
   280  
   281  	var actual interface{}
   282  	p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) {
   283  		c.Config["foo"] = "bar"
   284  		return c, nil
   285  	}
   286  	p.ConfigureFn = func(c *ResourceConfig) error {
   287  		actual = c.Config["foo"]
   288  		return nil
   289  	}
   290  
   291  	if err := ctx.Input(InputModeProvider); err != nil {
   292  		t.Fatalf("err: %s", err)
   293  	}
   294  
   295  	if _, err := ctx.Plan(); err != nil {
   296  		t.Fatalf("err: %s", err)
   297  	}
   298  
   299  	state, err := ctx.Apply()
   300  	if err != nil {
   301  		t.Fatalf("err: %s", err)
   302  	}
   303  
   304  	if !reflect.DeepEqual(actual, "bar") {
   305  		t.Fatalf("bad: %#v", actual)
   306  	}
   307  
   308  	actualStr := strings.TrimSpace(state.String())
   309  	expectedStr := strings.TrimSpace(testTerraformInputProviderOnlyStr)
   310  	if actualStr != expectedStr {
   311  		t.Fatalf("bad: \n%s", actualStr)
   312  	}
   313  }
   314  
   315  func TestContext2Input_providerVars(t *testing.T) {
   316  	input := new(MockUIInput)
   317  	m := testModule(t, "input-provider-with-vars")
   318  	p := testProvider("aws")
   319  	p.ApplyFn = testApplyFn
   320  	p.DiffFn = testDiffFn
   321  	ctx := testContext2(t, &ContextOpts{
   322  		Module: m,
   323  		Providers: map[string]ResourceProviderFactory{
   324  			"aws": testProviderFuncFixed(p),
   325  		},
   326  		Variables: map[string]string{
   327  			"foo": "bar",
   328  		},
   329  		UIInput: input,
   330  	})
   331  
   332  	input.InputReturnMap = map[string]string{
   333  		"var.foo": "bar",
   334  	}
   335  
   336  	var actual interface{}
   337  	p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) {
   338  		c.Config["bar"] = "baz"
   339  		return c, nil
   340  	}
   341  	p.ConfigureFn = func(c *ResourceConfig) error {
   342  		actual, _ = c.Get("foo")
   343  		return nil
   344  	}
   345  
   346  	if err := ctx.Input(InputModeStd); err != nil {
   347  		t.Fatalf("err: %s", err)
   348  	}
   349  
   350  	if _, err := ctx.Plan(); err != nil {
   351  		t.Fatalf("err: %s", err)
   352  	}
   353  
   354  	if _, err := ctx.Apply(); err != nil {
   355  		t.Fatalf("err: %s", err)
   356  	}
   357  
   358  	if !reflect.DeepEqual(actual, "bar") {
   359  		t.Fatalf("bad: %#v", actual)
   360  	}
   361  }
   362  
   363  func TestContext2Input_providerVarsModuleInherit(t *testing.T) {
   364  	input := new(MockUIInput)
   365  	m := testModule(t, "input-provider-with-vars-and-module")
   366  	p := testProvider("aws")
   367  	p.ApplyFn = testApplyFn
   368  	p.DiffFn = testDiffFn
   369  	ctx := testContext2(t, &ContextOpts{
   370  		Module: m,
   371  		Providers: map[string]ResourceProviderFactory{
   372  			"aws": testProviderFuncFixed(p),
   373  		},
   374  		UIInput: input,
   375  	})
   376  
   377  	p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) {
   378  		if errs := c.CheckSet([]string{"access_key"}); len(errs) > 0 {
   379  			return c, errs[0]
   380  		}
   381  		return c, nil
   382  	}
   383  	p.ConfigureFn = func(c *ResourceConfig) error {
   384  		return nil
   385  	}
   386  
   387  	if err := ctx.Input(InputModeStd); err != nil {
   388  		t.Fatalf("err: %s", err)
   389  	}
   390  }
   391  
   392  func TestContext2Input_varOnly(t *testing.T) {
   393  	input := new(MockUIInput)
   394  	m := testModule(t, "input-provider-vars")
   395  	p := testProvider("aws")
   396  	p.ApplyFn = testApplyFn
   397  	p.DiffFn = testDiffFn
   398  	ctx := testContext2(t, &ContextOpts{
   399  		Module: m,
   400  		Providers: map[string]ResourceProviderFactory{
   401  			"aws": testProviderFuncFixed(p),
   402  		},
   403  		Variables: map[string]string{
   404  			"foo": "us-west-2",
   405  		},
   406  		UIInput: input,
   407  	})
   408  
   409  	input.InputReturnMap = map[string]string{
   410  		"var.foo": "us-east-1",
   411  	}
   412  
   413  	var actual interface{}
   414  	p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) {
   415  		c.Raw["foo"] = "bar"
   416  		return c, nil
   417  	}
   418  	p.ConfigureFn = func(c *ResourceConfig) error {
   419  		actual = c.Raw["foo"]
   420  		return nil
   421  	}
   422  
   423  	if err := ctx.Input(InputModeVar); err != nil {
   424  		t.Fatalf("err: %s", err)
   425  	}
   426  
   427  	if _, err := ctx.Plan(); err != nil {
   428  		t.Fatalf("err: %s", err)
   429  	}
   430  
   431  	state, err := ctx.Apply()
   432  	if err != nil {
   433  		t.Fatalf("err: %s", err)
   434  	}
   435  
   436  	if reflect.DeepEqual(actual, "bar") {
   437  		t.Fatalf("bad: %#v", actual)
   438  	}
   439  
   440  	actualStr := strings.TrimSpace(state.String())
   441  	expectedStr := strings.TrimSpace(testTerraformInputVarOnlyStr)
   442  	if actualStr != expectedStr {
   443  		t.Fatalf("bad: \n%s", actualStr)
   444  	}
   445  }
   446  
   447  func TestContext2Input_varOnlyUnset(t *testing.T) {
   448  	input := new(MockUIInput)
   449  	m := testModule(t, "input-vars-unset")
   450  	p := testProvider("aws")
   451  	p.ApplyFn = testApplyFn
   452  	p.DiffFn = testDiffFn
   453  	ctx := testContext2(t, &ContextOpts{
   454  		Module: m,
   455  		Providers: map[string]ResourceProviderFactory{
   456  			"aws": testProviderFuncFixed(p),
   457  		},
   458  		Variables: map[string]string{
   459  			"foo": "foovalue",
   460  		},
   461  		UIInput: input,
   462  	})
   463  
   464  	input.InputReturnMap = map[string]string{
   465  		"var.foo": "nope",
   466  		"var.bar": "baz",
   467  	}
   468  
   469  	if err := ctx.Input(InputModeVar | InputModeVarUnset); err != nil {
   470  		t.Fatalf("err: %s", err)
   471  	}
   472  
   473  	if _, err := ctx.Plan(); err != nil {
   474  		t.Fatalf("err: %s", err)
   475  	}
   476  
   477  	state, err := ctx.Apply()
   478  	if err != nil {
   479  		t.Fatalf("err: %s", err)
   480  	}
   481  
   482  	actualStr := strings.TrimSpace(state.String())
   483  	expectedStr := strings.TrimSpace(testTerraformInputVarOnlyUnsetStr)
   484  	if actualStr != expectedStr {
   485  		t.Fatalf("bad: \n%s", actualStr)
   486  	}
   487  }
   488  
   489  func TestContext2Input_varWithDefault(t *testing.T) {
   490  	input := new(MockUIInput)
   491  	m := testModule(t, "input-var-default")
   492  	p := testProvider("aws")
   493  	p.ApplyFn = testApplyFn
   494  	p.DiffFn = testDiffFn
   495  	ctx := testContext2(t, &ContextOpts{
   496  		Module: m,
   497  		Providers: map[string]ResourceProviderFactory{
   498  			"aws": testProviderFuncFixed(p),
   499  		},
   500  		Variables: map[string]string{},
   501  		UIInput:   input,
   502  	})
   503  
   504  	input.InputFn = func(opts *InputOpts) (string, error) {
   505  		t.Fatalf(
   506  			"Input should never be called because variable has a default: %#v", opts)
   507  		return "", nil
   508  	}
   509  
   510  	if err := ctx.Input(InputModeVar | InputModeVarUnset); err != nil {
   511  		t.Fatalf("err: %s", err)
   512  	}
   513  
   514  	if _, err := ctx.Plan(); err != nil {
   515  		t.Fatalf("err: %s", err)
   516  	}
   517  
   518  	state, err := ctx.Apply()
   519  	if err != nil {
   520  		t.Fatalf("err: %s", err)
   521  	}
   522  
   523  	actualStr := strings.TrimSpace(state.String())
   524  	expectedStr := strings.TrimSpace(`
   525  aws_instance.foo:
   526    ID = foo
   527    foo = 123
   528    type = aws_instance
   529  	`)
   530  	if actualStr != expectedStr {
   531  		t.Fatalf("expected: \n%s\ngot: \n%s\n", expectedStr, actualStr)
   532  	}
   533  }
   534  
   535  func TestContext2Input_varPartiallyComputed(t *testing.T) {
   536  	input := new(MockUIInput)
   537  	m := testModule(t, "input-var-partially-computed")
   538  	p := testProvider("aws")
   539  	p.ApplyFn = testApplyFn
   540  	p.DiffFn = testDiffFn
   541  	ctx := testContext2(t, &ContextOpts{
   542  		Module: m,
   543  		Providers: map[string]ResourceProviderFactory{
   544  			"aws": testProviderFuncFixed(p),
   545  		},
   546  		Variables: map[string]string{
   547  			"foo": "foovalue",
   548  		},
   549  		UIInput: input,
   550  		State: &State{
   551  			Modules: []*ModuleState{
   552  				&ModuleState{
   553  					Path: rootModulePath,
   554  					Resources: map[string]*ResourceState{
   555  						"aws_instance.foo": &ResourceState{
   556  							Type: "aws_instance",
   557  							Primary: &InstanceState{
   558  								ID: "i-abc123",
   559  								Attributes: map[string]string{
   560  									"id": "i-abc123",
   561  								},
   562  							},
   563  						},
   564  					},
   565  				},
   566  				&ModuleState{
   567  					Path: append(rootModulePath, "child"),
   568  					Resources: map[string]*ResourceState{
   569  						"aws_instance.mod": &ResourceState{
   570  							Type: "aws_instance",
   571  							Primary: &InstanceState{
   572  								ID: "i-bcd345",
   573  								Attributes: map[string]string{
   574  									"id":    "i-bcd345",
   575  									"value": "one,i-abc123",
   576  								},
   577  							},
   578  						},
   579  					},
   580  				},
   581  			},
   582  		},
   583  	})
   584  
   585  	if err := ctx.Input(InputModeStd); err != nil {
   586  		t.Fatalf("err: %s", err)
   587  	}
   588  
   589  	if _, err := ctx.Plan(); err != nil {
   590  		t.Fatalf("err: %s", err)
   591  	}
   592  }
   593  
   594  // Module variables weren't being interpolated during the Input walk.
   595  // https://github.com/hashicorp/terraform/issues/5322
   596  func TestContext2Input_interpolateVar(t *testing.T) {
   597  	input := new(MockUIInput)
   598  
   599  	m := testModule(t, "input-interpolate-var")
   600  	p := testProvider("null")
   601  	p.ApplyFn = testApplyFn
   602  	p.DiffFn = testDiffFn
   603  
   604  	ctx := testContext2(t, &ContextOpts{
   605  		Module: m,
   606  		Providers: map[string]ResourceProviderFactory{
   607  			"template": testProviderFuncFixed(p),
   608  		},
   609  		UIInput: input,
   610  	})
   611  
   612  	if err := ctx.Input(InputModeStd); err != nil {
   613  		t.Fatalf("err: %s", err)
   614  	}
   615  }