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