From 006744bfe0b69dc96a3043711a7880e072e171d4 Mon Sep 17 00:00:00 2001 From: Robert Liebowitz Date: Tue, 7 Mar 2017 23:09:48 -0500 Subject: [PATCH] Use all tfvars files in working directory As a side effect, several commands that previously did not have a failure state can now fail during meta-parameter processing. --- command/apply.go | 5 +- command/console.go | 6 +- command/debug_json2dot.go | 5 +- command/fmt.go | 7 +- command/get.go | 6 +- command/graph.go | 5 +- command/import.go | 5 +- command/init.go | 5 +- command/meta.go | 60 +++++++++++---- command/meta_test.go | 77 +++++++++++++++++++- command/output.go | 5 +- command/plan.go | 5 +- command/push.go | 5 +- command/refresh.go | 5 +- command/show.go | 5 +- command/state_list.go | 5 +- command/state_mv.go | 5 +- command/state_pull.go | 5 +- command/state_push.go | 5 +- command/state_rm.go | 5 +- command/state_show.go | 5 +- command/taint.go | 5 +- command/unlock.go | 5 +- command/untaint.go | 5 +- command/validate.go | 5 +- command/version.go | 5 +- command/workspace_command.go | 5 +- command/workspace_delete.go | 5 +- command/workspace_list.go | 5 +- command/workspace_new.go | 5 +- command/workspace_select.go | 5 +- command/workspace_show.go | 5 +- config/loader.go | 6 +- website/docs/commands/apply.html.markdown | 7 +- website/docs/commands/import.html.md | 8 +- website/docs/commands/plan.html.markdown | 7 +- website/docs/commands/refresh.html.markdown | 7 +- website/docs/configuration/variables.html.md | 18 +++-- website/upgrade-guides/0-7.html.markdown | 2 +- 39 files changed, 273 insertions(+), 73 deletions(-) diff --git a/command/apply.go b/command/apply.go index c1214e182..3f61243b7 100644 --- a/command/apply.go +++ b/command/apply.go @@ -30,7 +30,10 @@ type ApplyCommand struct { func (c *ApplyCommand) Run(args []string) int { var destroyForce, refresh, autoApprove bool - args = c.Meta.process(args, true) + args, err := c.Meta.process(args, true) + if err != nil { + return 1 + } cmdName := "apply" if c.Destroy { diff --git a/command/console.go b/command/console.go index cd73ffe49..b5c37861c 100644 --- a/command/console.go +++ b/command/console.go @@ -23,7 +23,11 @@ type ConsoleCommand struct { } func (c *ConsoleCommand) Run(args []string) int { - args = c.Meta.process(args, true) + args, err := c.Meta.process(args, true) + if err != nil { + return 1 + } + cmdFlags := c.Meta.flagSet("console") cmdFlags.StringVar(&c.Meta.statePath, "state", DefaultStateFilename, "path") cmdFlags.Usage = func() { c.Ui.Error(c.Help()) } diff --git a/command/debug_json2dot.go b/command/debug_json2dot.go index f6ed214b0..64361bcf1 100644 --- a/command/debug_json2dot.go +++ b/command/debug_json2dot.go @@ -16,7 +16,10 @@ type DebugJSON2DotCommand struct { } func (c *DebugJSON2DotCommand) Run(args []string) int { - args = c.Meta.process(args, true) + args, err := c.Meta.process(args, true) + if err != nil { + return 1 + } cmdFlags := c.Meta.flagSet("debug json2dot") if err := cmdFlags.Parse(args); err != nil { diff --git a/command/fmt.go b/command/fmt.go index 0b06d7b50..9352cdabf 100644 --- a/command/fmt.go +++ b/command/fmt.go @@ -29,7 +29,10 @@ func (c *FmtCommand) Run(args []string) int { c.input = os.Stdin } - args = c.Meta.process(args, false) + args, err := c.Meta.process(args, false) + if err != nil { + return 1 + } cmdFlags := flag.NewFlagSet("fmt", flag.ContinueOnError) cmdFlags.BoolVar(&c.opts.List, "list", true, "list") @@ -59,7 +62,7 @@ func (c *FmtCommand) Run(args []string) int { } output := &cli.UiWriter{Ui: c.Ui} - err := fmtcmd.Run(dirs, []string{fileExtension}, c.input, output, c.opts) + err = fmtcmd.Run(dirs, []string{fileExtension}, c.input, output, c.opts) if err != nil { c.Ui.Error(fmt.Sprintf("Error running fmt: %s", err)) return 2 diff --git a/command/get.go b/command/get.go index 982484f9b..d51ae39b3 100644 --- a/command/get.go +++ b/command/get.go @@ -17,7 +17,10 @@ type GetCommand struct { func (c *GetCommand) Run(args []string) int { var update bool - args = c.Meta.process(args, false) + args, err := c.Meta.process(args, false) + if err != nil { + return 1 + } cmdFlags := flag.NewFlagSet("get", flag.ContinueOnError) cmdFlags.BoolVar(&update, "update", false, "update") @@ -26,7 +29,6 @@ func (c *GetCommand) Run(args []string) int { return 1 } - var path string path, err := ModulePath(cmdFlags.Args()) if err != nil { c.Ui.Error(err.Error()) diff --git a/command/graph.go b/command/graph.go index befe5b329..cd65a682a 100644 --- a/command/graph.go +++ b/command/graph.go @@ -24,7 +24,10 @@ func (c *GraphCommand) Run(args []string) int { var drawCycles bool var graphTypeStr string - args = c.Meta.process(args, false) + args, err := c.Meta.process(args, false) + if err != nil { + return 1 + } cmdFlags := flag.NewFlagSet("graph", flag.ContinueOnError) c.addModuleDepthFlag(cmdFlags, &moduleDepth) diff --git a/command/import.go b/command/import.go index ddb416d59..46728fdb9 100644 --- a/command/import.go +++ b/command/import.go @@ -27,7 +27,10 @@ func (c *ImportCommand) Run(args []string) int { } var configPath string - args = c.Meta.process(args, true) + args, err = c.Meta.process(args, true) + if err != nil { + return 1 + } cmdFlags := c.Meta.flagSet("import") cmdFlags.IntVar(&c.Meta.parallelism, "parallelism", 0, "parallelism") diff --git a/command/init.go b/command/init.go index ffc8de03b..7c070f9df 100644 --- a/command/init.go +++ b/command/init.go @@ -38,7 +38,10 @@ func (c *InitCommand) Run(args []string) int { var flagPluginPath FlagStringSlice var flagVerifyPlugins bool - args = c.Meta.process(args, false) + args, err := c.Meta.process(args, false) + if err != nil { + return 1 + } cmdFlags := c.flagSet("init") cmdFlags.BoolVar(&flagBackend, "backend", true, "") cmdFlags.Var((*variables.FlagAny)(&flagConfigExtra), "backend-config", "") diff --git a/command/meta.go b/command/meta.go index 84177ceef..be57951ef 100644 --- a/command/meta.go +++ b/command/meta.go @@ -18,6 +18,7 @@ import ( "github.com/hashicorp/go-getter" "github.com/hashicorp/terraform/backend" "github.com/hashicorp/terraform/backend/local" + "github.com/hashicorp/terraform/config" "github.com/hashicorp/terraform/helper/experiment" "github.com/hashicorp/terraform/helper/variables" "github.com/hashicorp/terraform/helper/wrappedstreams" @@ -348,7 +349,7 @@ func (m *Meta) moduleStorage(root string) getter.Storage { // slice. // // vars says whether or not we support variables. -func (m *Meta) process(args []string, vars bool) []string { +func (m *Meta) process(args []string, vars bool) ([]string, error) { // We do this so that we retain the ability to technically call // process multiple times, even if we have no plans to do so if m.oldUi != nil { @@ -381,24 +382,49 @@ func (m *Meta) process(args []string, vars bool) []string { // the args... m.autoKey = "" if vars { - if _, err := os.Stat(DefaultVarsFilename); err == nil { - m.autoKey = "var-file-default" - args = append(args, "", "") - copy(args[2:], args[0:]) - args[0] = "-" + m.autoKey - args[1] = DefaultVarsFilename + wd, err := os.Getwd() + if err != nil { + return nil, err + } + f, err := os.Open(wd) + if err != nil { + return nil, err + } + defer f.Close() + + fi, err := f.Stat() + if err != nil { + return nil, err + } + if !fi.IsDir() { + return nil, err } - if _, err := os.Stat(DefaultVarsFilename + ".json"); err == nil { - m.autoKey = "var-file-default" - args = append(args, "", "") - copy(args[2:], args[0:]) - args[0] = "-" + m.autoKey - args[1] = DefaultVarsFilename + ".json" + err = nil + var preArgs []string + for err != io.EOF { + var fis []os.FileInfo + fis, err = f.Readdir(128) + if err != nil && err != io.EOF { + return nil, err + } + + for _, fi := range fis { + name := fi.Name() + // Ignore directories, non-var-files, and ignored files + if fi.IsDir() || !isVarFile(name) || config.IsIgnoredFile(name) { + continue + } + + m.autoKey = "var-file-default" + preArgs = append(preArgs, "-"+m.autoKey, name) + } } + + args = append(preArgs, args...) } - return args + return args, nil } // uiHook returns the UiHook to use with the context. @@ -543,3 +569,9 @@ func (m *Meta) SetWorkspace(name string) error { } return nil } + +// isVarFile determines if the file ends with .tfvars or .tfvars.json +func isVarFile(path string) bool { + return strings.HasSuffix(path, ".tfvars") || + strings.HasSuffix(path, ".tfvars.json") +} diff --git a/command/meta_test.go b/command/meta_test.go index db8403318..77f78ebee 100644 --- a/command/meta_test.go +++ b/command/meta_test.go @@ -21,7 +21,10 @@ func TestMetaColorize(t *testing.T) { m.Color = true args = []string{"foo", "bar"} args2 = []string{"foo", "bar"} - args = m.process(args, false) + args, err := m.process(args, false) + if err != nil { + t.Fatalf("err: %s", err) + } if !reflect.DeepEqual(args, args2) { t.Fatalf("bad: %#v", args) } @@ -33,7 +36,10 @@ func TestMetaColorize(t *testing.T) { m = new(Meta) args = []string{"foo", "bar"} args2 = []string{"foo", "bar"} - args = m.process(args, false) + args, err = m.process(args, false) + if err != nil { + t.Fatalf("err: %s", err) + } if !reflect.DeepEqual(args, args2) { t.Fatalf("bad: %#v", args) } @@ -46,7 +52,10 @@ func TestMetaColorize(t *testing.T) { m.Color = true args = []string{"foo", "-no-color", "bar"} args2 = []string{"foo", "bar"} - args = m.process(args, false) + args, err = m.process(args, false) + if err != nil { + t.Fatalf("err: %s", err) + } if !reflect.DeepEqual(args, args2) { t.Fatalf("bad: %#v", args) } @@ -152,7 +161,10 @@ func TestMetaInputMode_defaultVars(t *testing.T) { m := new(Meta) args := []string{} - args = m.process(args, true) + args, err = m.process(args, false) + if err != nil { + t.Fatalf("err: %s", err) + } fs := m.flagSet("foo") if err := fs.Parse(args); err != nil { @@ -307,3 +319,60 @@ func TestMeta_Env(t *testing.T) { t.Fatalf("expected env %q, got env %q", backend.DefaultStateName, env) } } + +func TestMeta_process(t *testing.T) { + test = false + defer func() { test = true }() + + // Create a temporary directory for our cwd + d := tempDir(t) + if err := os.MkdirAll(d, 0755); err != nil { + t.Fatalf("err: %s", err) + } + cwd, err := os.Getwd() + if err != nil { + t.Fatalf("err: %s", err) + } + if err := os.Chdir(d); err != nil { + t.Fatalf("err: %s", err) + } + defer os.Chdir(cwd) + + // Create two vars files + file1 := "file1.tfvars" + err = ioutil.WriteFile( + filepath.Join(d, file1), + []byte(""), + 0644) + if err != nil { + t.Fatalf("err: %s", err) + } + file2 := "file2.tfvars" + err = ioutil.WriteFile( + filepath.Join(d, file2), + []byte(""), + 0644) + if err != nil { + t.Fatalf("err: %s", err) + } + + m := new(Meta) + args := []string{} + args, err = m.process(args, true) + if err != nil { + t.Fatalf("err: %s", err) + } + + if args[0] != "-var-file-default" { + t.Fatalf("expected %q, got %q", "-var-file-default", args[0]) + } + if args[1] != file1 { + t.Fatalf("expected %q, got %q", file1, args[1]) + } + if args[2] != "-var-file-default" { + t.Fatalf("expected %q, got %q", "-var-file-default", args[0]) + } + if args[3] != file2 { + t.Fatalf("expected %q, got %q", file2, args[3]) + } +} diff --git a/command/output.go b/command/output.go index b098b4cb0..8677858da 100644 --- a/command/output.go +++ b/command/output.go @@ -16,7 +16,10 @@ type OutputCommand struct { } func (c *OutputCommand) Run(args []string) int { - args = c.Meta.process(args, false) + args, err := c.Meta.process(args, false) + if err != nil { + return 1 + } var module string var jsonOutput bool diff --git a/command/plan.go b/command/plan.go index 1edc179e5..8e27ff923 100644 --- a/command/plan.go +++ b/command/plan.go @@ -21,7 +21,10 @@ func (c *PlanCommand) Run(args []string) int { var outPath string var moduleDepth int - args = c.Meta.process(args, true) + args, err := c.Meta.process(args, true) + if err != nil { + return 1 + } cmdFlags := c.Meta.flagSet("plan") cmdFlags.BoolVar(&destroy, "destroy", false, "destroy") diff --git a/command/push.go b/command/push.go index 1c206aef5..79ae613b4 100644 --- a/command/push.go +++ b/command/push.go @@ -29,7 +29,10 @@ func (c *PushCommand) Run(args []string) int { var archiveVCS, moduleUpload bool var name string var overwrite []string - args = c.Meta.process(args, true) + args, err := c.Meta.process(args, true) + if err != nil { + return 1 + } cmdFlags := c.Meta.flagSet("push") cmdFlags.StringVar(&atlasAddress, "atlas-address", "", "") cmdFlags.StringVar(&c.Meta.statePath, "state", DefaultStateFilename, "path") diff --git a/command/refresh.go b/command/refresh.go index 7ffa9d890..e90279fdc 100644 --- a/command/refresh.go +++ b/command/refresh.go @@ -17,7 +17,10 @@ type RefreshCommand struct { } func (c *RefreshCommand) Run(args []string) int { - args = c.Meta.process(args, true) + args, err := c.Meta.process(args, true) + if err != nil { + return 1 + } cmdFlags := c.Meta.flagSet("refresh") cmdFlags.StringVar(&c.Meta.statePath, "state", DefaultStateFilename, "path") diff --git a/command/show.go b/command/show.go index 43e600616..254644863 100644 --- a/command/show.go +++ b/command/show.go @@ -19,7 +19,10 @@ type ShowCommand struct { func (c *ShowCommand) Run(args []string) int { var moduleDepth int - args = c.Meta.process(args, false) + args, err := c.Meta.process(args, false) + if err != nil { + return 1 + } cmdFlags := flag.NewFlagSet("show", flag.ContinueOnError) c.addModuleDepthFlag(cmdFlags, &moduleDepth) diff --git a/command/state_list.go b/command/state_list.go index b9063554f..211f5b3d0 100644 --- a/command/state_list.go +++ b/command/state_list.go @@ -16,7 +16,10 @@ type StateListCommand struct { } func (c *StateListCommand) Run(args []string) int { - args = c.Meta.process(args, true) + args, err := c.Meta.process(args, true) + if err != nil { + return 1 + } cmdFlags := c.Meta.flagSet("state list") cmdFlags.StringVar(&c.Meta.statePath, "state", DefaultStateFilename, "path") diff --git a/command/state_mv.go b/command/state_mv.go index 71e934af4..5c51f2da7 100644 --- a/command/state_mv.go +++ b/command/state_mv.go @@ -15,7 +15,10 @@ type StateMvCommand struct { } func (c *StateMvCommand) Run(args []string) int { - args = c.Meta.process(args, true) + args, err := c.Meta.process(args, true) + if err != nil { + return 1 + } // We create two metas to track the two states var meta1, meta2 Meta diff --git a/command/state_pull.go b/command/state_pull.go index fbad296ff..c010d2a5e 100644 --- a/command/state_pull.go +++ b/command/state_pull.go @@ -16,7 +16,10 @@ type StatePullCommand struct { } func (c *StatePullCommand) Run(args []string) int { - args = c.Meta.process(args, true) + args, err := c.Meta.process(args, true) + if err != nil { + return 1 + } cmdFlags := c.Meta.flagSet("state pull") if err := cmdFlags.Parse(args); err != nil { diff --git a/command/state_push.go b/command/state_push.go index 7dfb7ad21..5b7d76978 100644 --- a/command/state_push.go +++ b/command/state_push.go @@ -17,7 +17,10 @@ type StatePushCommand struct { } func (c *StatePushCommand) Run(args []string) int { - args = c.Meta.process(args, true) + args, err := c.Meta.process(args, true) + if err != nil { + return 1 + } var flagForce bool cmdFlags := c.Meta.flagSet("state push") diff --git a/command/state_rm.go b/command/state_rm.go index f116731c8..40dc87050 100644 --- a/command/state_rm.go +++ b/command/state_rm.go @@ -14,7 +14,10 @@ type StateRmCommand struct { } func (c *StateRmCommand) Run(args []string) int { - args = c.Meta.process(args, true) + args, err := c.Meta.process(args, true) + if err != nil { + return 1 + } cmdFlags := c.Meta.flagSet("state show") cmdFlags.StringVar(&c.Meta.backupPath, "backup", "-", "backup") diff --git a/command/state_show.go b/command/state_show.go index 18d60a5de..d44d0c07e 100644 --- a/command/state_show.go +++ b/command/state_show.go @@ -17,7 +17,10 @@ type StateShowCommand struct { } func (c *StateShowCommand) Run(args []string) int { - args = c.Meta.process(args, true) + args, err := c.Meta.process(args, true) + if err != nil { + return 1 + } cmdFlags := c.Meta.flagSet("state show") cmdFlags.StringVar(&c.Meta.statePath, "state", DefaultStateFilename, "path") diff --git a/command/taint.go b/command/taint.go index fa3dfa72e..626f88a46 100644 --- a/command/taint.go +++ b/command/taint.go @@ -18,7 +18,10 @@ type TaintCommand struct { } func (c *TaintCommand) Run(args []string) int { - args = c.Meta.process(args, false) + args, err := c.Meta.process(args, false) + if err != nil { + return 1 + } var allowMissing bool var module string diff --git a/command/unlock.go b/command/unlock.go index 088c3d02c..4ac504972 100644 --- a/command/unlock.go +++ b/command/unlock.go @@ -16,7 +16,10 @@ type UnlockCommand struct { } func (c *UnlockCommand) Run(args []string) int { - args = c.Meta.process(args, false) + args, err := c.Meta.process(args, false) + if err != nil { + return 1 + } force := false cmdFlags := c.Meta.flagSet("force-unlock") diff --git a/command/untaint.go b/command/untaint.go index f0a07d1dc..1eca20277 100644 --- a/command/untaint.go +++ b/command/untaint.go @@ -17,7 +17,10 @@ type UntaintCommand struct { } func (c *UntaintCommand) Run(args []string) int { - args = c.Meta.process(args, false) + args, err := c.Meta.process(args, false) + if err != nil { + return 1 + } var allowMissing bool var module string diff --git a/command/validate.go b/command/validate.go index c4be168af..04ae2dddb 100644 --- a/command/validate.go +++ b/command/validate.go @@ -17,7 +17,10 @@ type ValidateCommand struct { const defaultPath = "." func (c *ValidateCommand) Run(args []string) int { - args = c.Meta.process(args, true) + args, err := c.Meta.process(args, false) + if err != nil { + return 1 + } var checkVars bool cmdFlags := c.Meta.flagSet("validate") diff --git a/command/version.go b/command/version.go index d4c3a2f89..f727667f6 100644 --- a/command/version.go +++ b/command/version.go @@ -34,7 +34,10 @@ func (c *VersionCommand) Help() string { func (c *VersionCommand) Run(args []string) int { var versionString bytes.Buffer - args = c.Meta.process(args, false) + args, err := c.Meta.process(args, false) + if err != nil { + return 1 + } fmt.Fprintf(&versionString, "Terraform v%s", c.Version) if c.VersionPrerelease != "" { diff --git a/command/workspace_command.go b/command/workspace_command.go index eda8cbe06..e74d3797f 100644 --- a/command/workspace_command.go +++ b/command/workspace_command.go @@ -15,7 +15,10 @@ type WorkspaceCommand struct { } func (c *WorkspaceCommand) Run(args []string) int { - args = c.Meta.process(args, true) + args, err := c.Meta.process(args, true) + if err != nil { + return 1 + } envCommandShowWarning(c.Ui, c.LegacyName) diff --git a/command/workspace_delete.go b/command/workspace_delete.go index 4d2a87343..cb96fba5e 100644 --- a/command/workspace_delete.go +++ b/command/workspace_delete.go @@ -16,7 +16,10 @@ type WorkspaceDeleteCommand struct { } func (c *WorkspaceDeleteCommand) Run(args []string) int { - args = c.Meta.process(args, true) + args, err := c.Meta.process(args, true) + if err != nil { + return 1 + } envCommandShowWarning(c.Ui, c.LegacyName) diff --git a/command/workspace_list.go b/command/workspace_list.go index 8f1190ff0..bd00246eb 100644 --- a/command/workspace_list.go +++ b/command/workspace_list.go @@ -12,7 +12,10 @@ type WorkspaceListCommand struct { } func (c *WorkspaceListCommand) Run(args []string) int { - args = c.Meta.process(args, true) + args, err := c.Meta.process(args, true) + if err != nil { + return 1 + } envCommandShowWarning(c.Ui, c.LegacyName) diff --git a/command/workspace_new.go b/command/workspace_new.go index d50c70e0c..53a873030 100644 --- a/command/workspace_new.go +++ b/command/workspace_new.go @@ -18,7 +18,10 @@ type WorkspaceNewCommand struct { } func (c *WorkspaceNewCommand) Run(args []string) int { - args = c.Meta.process(args, true) + args, err := c.Meta.process(args, true) + if err != nil { + return 1 + } envCommandShowWarning(c.Ui, c.LegacyName) diff --git a/command/workspace_select.go b/command/workspace_select.go index b1acea084..a80c7f68b 100644 --- a/command/workspace_select.go +++ b/command/workspace_select.go @@ -13,7 +13,10 @@ type WorkspaceSelectCommand struct { } func (c *WorkspaceSelectCommand) Run(args []string) int { - args = c.Meta.process(args, true) + args, err := c.Meta.process(args, true) + if err != nil { + return 1 + } envCommandShowWarning(c.Ui, c.LegacyName) diff --git a/command/workspace_show.go b/command/workspace_show.go index df478cb57..0e4d0159b 100644 --- a/command/workspace_show.go +++ b/command/workspace_show.go @@ -9,7 +9,10 @@ type WorkspaceShowCommand struct { } func (c *WorkspaceShowCommand) Run(args []string) int { - args = c.Meta.process(args, true) + args, err := c.Meta.process(args, true) + if err != nil { + return 1 + } cmdFlags := c.Meta.flagSet("workspace show") cmdFlags.Usage = func() { c.Ui.Error(c.Help()) } diff --git a/config/loader.go b/config/loader.go index 0bfa89c25..5dd7d4689 100644 --- a/config/loader.go +++ b/config/loader.go @@ -194,7 +194,7 @@ func dirFiles(dir string) ([]string, []string, error) { // Only care about files that are valid to load name := fi.Name() extValue := ext(name) - if extValue == "" || isIgnoredFile(name) { + if extValue == "" || IsIgnoredFile(name) { continue } @@ -215,9 +215,9 @@ func dirFiles(dir string) ([]string, []string, error) { return files, overrides, nil } -// isIgnoredFile returns true or false depending on whether the +// IsIgnoredFile returns true or false depending on whether the // provided file name is a file that should be ignored. -func isIgnoredFile(name string) bool { +func IsIgnoredFile(name string) bool { return strings.HasPrefix(name, ".") || // Unix-like hidden files strings.HasSuffix(name, "~") || // vim strings.HasPrefix(name, "#") && strings.HasSuffix(name, "#") // emacs diff --git a/website/docs/commands/apply.html.markdown b/website/docs/commands/apply.html.markdown index 085a1444c..ff5b9d142 100644 --- a/website/docs/commands/apply.html.markdown +++ b/website/docs/commands/apply.html.markdown @@ -68,6 +68,7 @@ The command-line flags are all optional. The list of available flags are: * `-var-file=foo` - Set variables in the Terraform configuration from a [variable file](/docs/configuration/variables.html#variable-files). If - "terraform.tfvars" is present, it will be automatically loaded first. Any - files specified by `-var-file` override any values in a "terraform.tfvars". - This flag can be used multiple times. + any files matching "*.tfvars" are present, they will be automatically loaded + in alphabetical order. Any files specified by `-var-file` override any values + set automatically from files in the working directory. This flag can be used + multiple times. diff --git a/website/docs/commands/import.html.md b/website/docs/commands/import.html.md index d22b85313..8c65a7495 100644 --- a/website/docs/commands/import.html.md +++ b/website/docs/commands/import.html.md @@ -67,10 +67,10 @@ The command-line flags are all optional. The list of available flags are: * `-var-file=foo` - Set variables in the Terraform configuration from a [variable file](/docs/configuration/variables.html#variable-files). If - "terraform.tfvars" is present, it will be automatically loaded first. Any - files specified by `-var-file` override any values in a "terraform.tfvars". - This flag can be used multiple times. This is only useful with the `-config` - flag. + any file matching "*.tfvars" are present, they will be automatically loaded + in alphabetical order. Any files specified by `-var-file` override any values + set automatically from files in the working directory. This flag can be used + multiple times. This is only useful with the `-config` flag. ## Provider Configuration diff --git a/website/docs/commands/plan.html.markdown b/website/docs/commands/plan.html.markdown index de4f91594..98f01cc03 100644 --- a/website/docs/commands/plan.html.markdown +++ b/website/docs/commands/plan.html.markdown @@ -73,9 +73,10 @@ The command-line flags are all optional. The list of available flags are: * `-var-file=foo` - Set variables in the Terraform configuration from a [variable file](/docs/configuration/variables.html#variable-files). If - "terraform.tfvars" is present, it will be automatically loaded first. Any - files specified by `-var-file` override any values in a "terraform.tfvars". - This flag can be used multiple times. + any files matching "*.tfvars" are present, they will be automatically loaded + in alphabetical order. Any files specified by `-var-file` override any values + set automatically from files in the working directory. This flag can be used + multiple times. ## Resource Targeting diff --git a/website/docs/commands/refresh.html.markdown b/website/docs/commands/refresh.html.markdown index a44f07e48..bf92b6901 100644 --- a/website/docs/commands/refresh.html.markdown +++ b/website/docs/commands/refresh.html.markdown @@ -56,6 +56,7 @@ The command-line flags are all optional. The list of available flags are: * `-var-file=foo` - Set variables in the Terraform configuration from a [variable file](/docs/configuration/variables.html#variable-files). If - "terraform.tfvars" is present, it will be automatically loaded first. Any - files specified by `-var-file` override any values in a "terraform.tfvars". - This flag can be used multiple times. + any files matching "*.tfvars" are present, they will be automatically loaded + in alphabetical order. Any files specified by `-var-file` override any values + set automatically from files in the working directory. This flag can be used + multiple times. diff --git a/website/docs/configuration/variables.html.md b/website/docs/configuration/variables.html.md index 4bddb1122..5fbe02c70 100644 --- a/website/docs/configuration/variables.html.md +++ b/website/docs/configuration/variables.html.md @@ -256,10 +256,9 @@ $ TF_VAR_somemap='{foo = "bar", baz = "qux"}' terraform plan Variables can be collected in files and passed all at once using the `-var-file=foo.tfvars` flag. -If a file named `terraform.tfvars` is present in the current directory, -Terraform automatically loads it to populate variables. If the file is named -something else, you can pass the path to the file using the `-var-file` -flag. +For all files which match `*.tfvars` present in the current directory, +Terraform automatically loads it to populate variables. If the file is located +somewhere else, you can pass the path to the file using the `-var-file` flag. Variables files use HCL or JSON to define variable values. Strings, lists or maps may be set in the same manner as the default value in a `variable` block @@ -338,11 +337,18 @@ _bar.tfvars_ baz = "bar" ``` -When they are passed in the following order: +When they are read directly from the working directory, the files are evaluated +in alphabetical order. The result will be that baz contains the value `foo` +because `foo.tfvars` has the last definition loaded. + +When they are passed manually in the following order: ```shell -$ terraform apply -var-file=foo.tfvars -var-file=bar.tfvars +$ terraform apply -var-file=path/to/foo.tfvars -var-file=path/to/bar.tfvars ``` The result will be that `baz` will contain the value `bar` because `bar.tfvars` has the last definition loaded. + +Definitions passed using the `-var-file` flag will always be evaluated after +those in the working directory. diff --git a/website/upgrade-guides/0-7.html.markdown b/website/upgrade-guides/0-7.html.markdown index 066980ce1..90faa40a8 100644 --- a/website/upgrade-guides/0-7.html.markdown +++ b/website/upgrade-guides/0-7.html.markdown @@ -233,4 +233,4 @@ This will give the map the effective value: } ``` -It's also possible to override the values in a variables file, either in `terraform.tfvars` or specified using the `-var-file` flag. +It's also possible to override the values in a variables file, either in any `*.tfvars` file or specified using the `-var-file` flag.