From 1248b147acf55d7f7eaa1a06b6fb89d760d1e334 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 1 Nov 2016 19:16:43 -0700 Subject: [PATCH] command/meta: always ask for unset variable input Fixes #7975 This changes the InputMode for the CLI to always be: InputModeProvider | InputModeVar | InputModeVarUnset Which means: * Ask for provider variables * Ask for user variables _that are not already set_ The change is the latter point. Before, we'd only ask for variables if zero were given. This forces the user to either have no variables set via the CLI, env vars, tfvars or ALL variables, but no in between. As reported in #7975, this isn't expected behavior. The new change makes is so that unset variables are always asked for. Users can retain the previous behavior by setting `-input=false`. This would ensure that variables set by external sources cover all cases. --- command/apply_test.go | 41 +++++++++++++++++++ command/meta.go | 6 +-- command/meta_test.go | 6 ++- .../test-fixtures/apply-input-partial/main.tf | 5 +++ terraform/context.go | 3 +- 5 files changed, 55 insertions(+), 6 deletions(-) create mode 100644 command/test-fixtures/apply-input-partial/main.tf diff --git a/command/apply_test.go b/command/apply_test.go index 150c6d014a..31f60fb55c 100644 --- a/command/apply_test.go +++ b/command/apply_test.go @@ -407,6 +407,47 @@ func TestApply_input(t *testing.T) { } } +// When only a partial set of the variables are set, Terraform +// should still ask for the unset ones by default (with -input=true) +func TestApply_inputPartial(t *testing.T) { + // Disable test mode so input would be asked + test = false + defer func() { test = true }() + + // Set some default reader/writers for the inputs + defaultInputReader = bytes.NewBufferString("one\ntwo\n") + defaultInputWriter = new(bytes.Buffer) + + statePath := testTempFile(t) + + p := testProvider() + ui := new(cli.MockUi) + c := &ApplyCommand{ + Meta: Meta{ + ContextOpts: testCtxConfig(p), + Ui: ui, + }, + } + + args := []string{ + "-state", statePath, + "-var", "foo=foovalue", + testFixturePath("apply-input-partial"), + } + if code := c.Run(args); code != 0 { + t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) + } + + expected := strings.TrimSpace(` + +Outputs: + +bar = one +foo = foovalue + `) + testStateOutput(t, statePath, expected) +} + func TestApply_noArgs(t *testing.T) { cwd, err := os.Getwd() if err != nil { diff --git a/command/meta.go b/command/meta.go index 92f25db1ea..541f96144b 100644 --- a/command/meta.go +++ b/command/meta.go @@ -221,10 +221,8 @@ func (m *Meta) InputMode() terraform.InputMode { var mode terraform.InputMode mode |= terraform.InputModeProvider - if len(m.variables) == 0 { - mode |= terraform.InputModeVar - mode |= terraform.InputModeVarUnset - } + mode |= terraform.InputModeVar + mode |= terraform.InputModeVarUnset return mode } diff --git a/command/meta_test.go b/command/meta_test.go index 781c664dc3..5dde0f1ffc 100644 --- a/command/meta_test.go +++ b/command/meta_test.go @@ -175,7 +175,11 @@ func TestMetaInputMode_vars(t *testing.T) { t.Fatalf("err: %s", err) } - if m.InputMode()&terraform.InputModeVar != 0 { + if m.InputMode()&terraform.InputModeVar == 0 { + t.Fatalf("bad: %#v", m.InputMode()) + } + + if m.InputMode()&terraform.InputModeVarUnset == 0 { t.Fatalf("bad: %#v", m.InputMode()) } } diff --git a/command/test-fixtures/apply-input-partial/main.tf b/command/test-fixtures/apply-input-partial/main.tf new file mode 100644 index 0000000000..8c80dd09cb --- /dev/null +++ b/command/test-fixtures/apply-input-partial/main.tf @@ -0,0 +1,5 @@ +variable "foo" {} +variable "bar" {} + +output "foo" { value = "${var.foo}" } +output "bar" { value = "${var.bar}" } diff --git a/terraform/context.go b/terraform/context.go index 80bdf2d509..987469bb7d 100644 --- a/terraform/context.go +++ b/terraform/context.go @@ -22,7 +22,8 @@ const ( // InputModeVar asks for all variables InputModeVar InputMode = 1 << iota - // InputModeVarUnset asks for variables which are not set yet + // InputModeVarUnset asks for variables which are not set yet. + // InputModeVar must be set for this to have an effect. InputModeVarUnset // InputModeProvider asks for provider variables