diff --git a/terraform/context.go b/terraform/context.go index e2db6e6f9..62a06f431 100644 --- a/terraform/context.go +++ b/terraform/context.go @@ -16,9 +16,12 @@ import ( type InputMode byte const ( - // InputModeVar asks for variables + // InputModeVar asks for all variables InputModeVar InputMode = 1 << iota + // InputModeVarUnset asks for variables which are not set yet + InputModeVarUnset + // InputModeProvider asks for provider variables InputModeProvider @@ -154,6 +157,14 @@ func (c *Context) Input(mode InputMode) error { } sort.Strings(names) for _, n := range names { + // If we only care about unset variables, then if the variabel + // is set, continue on. + if mode&InputModeVarUnset != 0 { + if _, ok := c.variables[n]; ok { + continue + } + } + v := m[n] switch v.Type() { case config.VariableTypeMap: @@ -365,6 +376,21 @@ func (c *Context) Validate() ([]string, []error) { return walker.ValidationWarnings, rerrs.Errors } +<<<<<<< Updated upstream +======= +// Variables will return the mapping of variables that were defined +// for this Context. If Input was called, this mapping may be different +// than what was given. +func (c *Context) Variables() map[string]string { + return c.variables +} + +// SetVariable sets a variable after a context has already been built. +func (c *Context) SetVariable(k, v string) { + c.variables[k] = v +} + +>>>>>>> Stashed changes func (c *Context) acquireRun() chan<- struct{} { c.l.Lock() defer c.l.Unlock() diff --git a/terraform/context_test.go b/terraform/context_test.go index 9050d4b96..c6dd83b94 100644 --- a/terraform/context_test.go +++ b/terraform/context_test.go @@ -2758,6 +2758,48 @@ func TestContext2Input_varOnly(t *testing.T) { } } +func TestContext2Input_varOnlyUnset(t *testing.T) { + input := new(MockUIInput) + m := testModule(t, "input-vars-unset") + p := testProvider("aws") + p.ApplyFn = testApplyFn + p.DiffFn = testDiffFn + ctx := testContext2(t, &ContextOpts{ + Module: m, + Providers: map[string]ResourceProviderFactory{ + "aws": testProviderFuncFixed(p), + }, + Variables: map[string]string{ + "foo": "foovalue", + }, + UIInput: input, + }) + + input.InputReturnMap = map[string]string{ + "var.foo": "nope", + "var.bar": "baz", + } + + if err := ctx.Input(InputModeVar | InputModeVarUnset); err != nil { + t.Fatalf("err: %s", err) + } + + if _, err := ctx.Plan(nil); err != nil { + t.Fatalf("err: %s", err) + } + + state, err := ctx.Apply() + if err != nil { + t.Fatalf("err: %s", err) + } + + actualStr := strings.TrimSpace(state.String()) + expectedStr := strings.TrimSpace(testTerraformInputVarOnlyUnsetStr) + if actualStr != expectedStr { + t.Fatalf("bad: \n%s", actualStr) + } +} + func TestContext2Apply(t *testing.T) { m := testModule(t, "apply-good") p := testProvider("aws") diff --git a/terraform/terraform_test.go b/terraform/terraform_test.go index 94664791f..b3c0f9529 100644 --- a/terraform/terraform_test.go +++ b/terraform/terraform_test.go @@ -150,6 +150,14 @@ aws_instance.foo: type = aws_instance ` +const testTerraformInputVarOnlyUnsetStr = ` +aws_instance.foo: + ID = foo + bar = baz + foo = foovalue + type = aws_instance +` + const testTerraformInputVarsStr = ` aws_instance.bar: ID = foo diff --git a/terraform/test-fixtures/input-vars-unset/main.tf b/terraform/test-fixtures/input-vars-unset/main.tf new file mode 100644 index 000000000..28cf230e6 --- /dev/null +++ b/terraform/test-fixtures/input-vars-unset/main.tf @@ -0,0 +1,7 @@ +variable "foo" {} +variable "bar" {} + +resource "aws_instance" "foo" { + foo = "${var.foo}" + bar = "${var.bar}" +}