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.
This commit is contained in:
Robert Liebowitz 2017-03-07 23:09:48 -05:00 committed by Martin Atkins
parent 29b2368fa0
commit 006744bfe0
39 changed files with 273 additions and 73 deletions

View File

@ -30,7 +30,10 @@ type ApplyCommand struct {
func (c *ApplyCommand) Run(args []string) int { func (c *ApplyCommand) Run(args []string) int {
var destroyForce, refresh, autoApprove bool 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" cmdName := "apply"
if c.Destroy { if c.Destroy {

View File

@ -23,7 +23,11 @@ type ConsoleCommand struct {
} }
func (c *ConsoleCommand) Run(args []string) int { 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 := c.Meta.flagSet("console")
cmdFlags.StringVar(&c.Meta.statePath, "state", DefaultStateFilename, "path") cmdFlags.StringVar(&c.Meta.statePath, "state", DefaultStateFilename, "path")
cmdFlags.Usage = func() { c.Ui.Error(c.Help()) } cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }

View File

@ -16,7 +16,10 @@ type DebugJSON2DotCommand struct {
} }
func (c *DebugJSON2DotCommand) Run(args []string) int { 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") cmdFlags := c.Meta.flagSet("debug json2dot")
if err := cmdFlags.Parse(args); err != nil { if err := cmdFlags.Parse(args); err != nil {

View File

@ -29,7 +29,10 @@ func (c *FmtCommand) Run(args []string) int {
c.input = os.Stdin 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 := flag.NewFlagSet("fmt", flag.ContinueOnError)
cmdFlags.BoolVar(&c.opts.List, "list", true, "list") 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} 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 { if err != nil {
c.Ui.Error(fmt.Sprintf("Error running fmt: %s", err)) c.Ui.Error(fmt.Sprintf("Error running fmt: %s", err))
return 2 return 2

View File

@ -17,7 +17,10 @@ type GetCommand struct {
func (c *GetCommand) Run(args []string) int { func (c *GetCommand) Run(args []string) int {
var update bool 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 := flag.NewFlagSet("get", flag.ContinueOnError)
cmdFlags.BoolVar(&update, "update", false, "update") cmdFlags.BoolVar(&update, "update", false, "update")
@ -26,7 +29,6 @@ func (c *GetCommand) Run(args []string) int {
return 1 return 1
} }
var path string
path, err := ModulePath(cmdFlags.Args()) path, err := ModulePath(cmdFlags.Args())
if err != nil { if err != nil {
c.Ui.Error(err.Error()) c.Ui.Error(err.Error())

View File

@ -24,7 +24,10 @@ func (c *GraphCommand) Run(args []string) int {
var drawCycles bool var drawCycles bool
var graphTypeStr string 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) cmdFlags := flag.NewFlagSet("graph", flag.ContinueOnError)
c.addModuleDepthFlag(cmdFlags, &moduleDepth) c.addModuleDepthFlag(cmdFlags, &moduleDepth)

View File

@ -27,7 +27,10 @@ func (c *ImportCommand) Run(args []string) int {
} }
var configPath string 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 := c.Meta.flagSet("import")
cmdFlags.IntVar(&c.Meta.parallelism, "parallelism", 0, "parallelism") cmdFlags.IntVar(&c.Meta.parallelism, "parallelism", 0, "parallelism")

View File

@ -38,7 +38,10 @@ func (c *InitCommand) Run(args []string) int {
var flagPluginPath FlagStringSlice var flagPluginPath FlagStringSlice
var flagVerifyPlugins bool 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 := c.flagSet("init")
cmdFlags.BoolVar(&flagBackend, "backend", true, "") cmdFlags.BoolVar(&flagBackend, "backend", true, "")
cmdFlags.Var((*variables.FlagAny)(&flagConfigExtra), "backend-config", "") cmdFlags.Var((*variables.FlagAny)(&flagConfigExtra), "backend-config", "")

View File

@ -18,6 +18,7 @@ import (
"github.com/hashicorp/go-getter" "github.com/hashicorp/go-getter"
"github.com/hashicorp/terraform/backend" "github.com/hashicorp/terraform/backend"
"github.com/hashicorp/terraform/backend/local" "github.com/hashicorp/terraform/backend/local"
"github.com/hashicorp/terraform/config"
"github.com/hashicorp/terraform/helper/experiment" "github.com/hashicorp/terraform/helper/experiment"
"github.com/hashicorp/terraform/helper/variables" "github.com/hashicorp/terraform/helper/variables"
"github.com/hashicorp/terraform/helper/wrappedstreams" "github.com/hashicorp/terraform/helper/wrappedstreams"
@ -348,7 +349,7 @@ func (m *Meta) moduleStorage(root string) getter.Storage {
// slice. // slice.
// //
// vars says whether or not we support variables. // 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 // We do this so that we retain the ability to technically call
// process multiple times, even if we have no plans to do so // process multiple times, even if we have no plans to do so
if m.oldUi != nil { if m.oldUi != nil {
@ -381,24 +382,49 @@ func (m *Meta) process(args []string, vars bool) []string {
// the args... // the args...
m.autoKey = "" m.autoKey = ""
if vars { if vars {
if _, err := os.Stat(DefaultVarsFilename); err == nil { wd, err := os.Getwd()
m.autoKey = "var-file-default" if err != nil {
args = append(args, "", "") return nil, err
copy(args[2:], args[0:]) }
args[0] = "-" + m.autoKey f, err := os.Open(wd)
args[1] = DefaultVarsFilename 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 { err = nil
m.autoKey = "var-file-default" var preArgs []string
args = append(args, "", "") for err != io.EOF {
copy(args[2:], args[0:]) var fis []os.FileInfo
args[0] = "-" + m.autoKey fis, err = f.Readdir(128)
args[1] = DefaultVarsFilename + ".json" 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. // uiHook returns the UiHook to use with the context.
@ -543,3 +569,9 @@ func (m *Meta) SetWorkspace(name string) error {
} }
return nil 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")
}

View File

@ -21,7 +21,10 @@ func TestMetaColorize(t *testing.T) {
m.Color = true m.Color = true
args = []string{"foo", "bar"} args = []string{"foo", "bar"}
args2 = []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) { if !reflect.DeepEqual(args, args2) {
t.Fatalf("bad: %#v", args) t.Fatalf("bad: %#v", args)
} }
@ -33,7 +36,10 @@ func TestMetaColorize(t *testing.T) {
m = new(Meta) m = new(Meta)
args = []string{"foo", "bar"} args = []string{"foo", "bar"}
args2 = []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) { if !reflect.DeepEqual(args, args2) {
t.Fatalf("bad: %#v", args) t.Fatalf("bad: %#v", args)
} }
@ -46,7 +52,10 @@ func TestMetaColorize(t *testing.T) {
m.Color = true m.Color = true
args = []string{"foo", "-no-color", "bar"} args = []string{"foo", "-no-color", "bar"}
args2 = []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) { if !reflect.DeepEqual(args, args2) {
t.Fatalf("bad: %#v", args) t.Fatalf("bad: %#v", args)
} }
@ -152,7 +161,10 @@ func TestMetaInputMode_defaultVars(t *testing.T) {
m := new(Meta) m := new(Meta)
args := []string{} 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") fs := m.flagSet("foo")
if err := fs.Parse(args); err != nil { 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) 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])
}
}

View File

@ -16,7 +16,10 @@ type OutputCommand struct {
} }
func (c *OutputCommand) Run(args []string) int { 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 module string
var jsonOutput bool var jsonOutput bool

View File

@ -21,7 +21,10 @@ func (c *PlanCommand) Run(args []string) int {
var outPath string var outPath string
var moduleDepth int 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 := c.Meta.flagSet("plan")
cmdFlags.BoolVar(&destroy, "destroy", false, "destroy") cmdFlags.BoolVar(&destroy, "destroy", false, "destroy")

View File

@ -29,7 +29,10 @@ func (c *PushCommand) Run(args []string) int {
var archiveVCS, moduleUpload bool var archiveVCS, moduleUpload bool
var name string var name string
var overwrite []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 := c.Meta.flagSet("push")
cmdFlags.StringVar(&atlasAddress, "atlas-address", "", "") cmdFlags.StringVar(&atlasAddress, "atlas-address", "", "")
cmdFlags.StringVar(&c.Meta.statePath, "state", DefaultStateFilename, "path") cmdFlags.StringVar(&c.Meta.statePath, "state", DefaultStateFilename, "path")

View File

@ -17,7 +17,10 @@ type RefreshCommand struct {
} }
func (c *RefreshCommand) Run(args []string) int { 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 := c.Meta.flagSet("refresh")
cmdFlags.StringVar(&c.Meta.statePath, "state", DefaultStateFilename, "path") cmdFlags.StringVar(&c.Meta.statePath, "state", DefaultStateFilename, "path")

View File

@ -19,7 +19,10 @@ type ShowCommand struct {
func (c *ShowCommand) Run(args []string) int { func (c *ShowCommand) Run(args []string) int {
var moduleDepth 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) cmdFlags := flag.NewFlagSet("show", flag.ContinueOnError)
c.addModuleDepthFlag(cmdFlags, &moduleDepth) c.addModuleDepthFlag(cmdFlags, &moduleDepth)

View File

@ -16,7 +16,10 @@ type StateListCommand struct {
} }
func (c *StateListCommand) Run(args []string) int { 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 := c.Meta.flagSet("state list")
cmdFlags.StringVar(&c.Meta.statePath, "state", DefaultStateFilename, "path") cmdFlags.StringVar(&c.Meta.statePath, "state", DefaultStateFilename, "path")

View File

@ -15,7 +15,10 @@ type StateMvCommand struct {
} }
func (c *StateMvCommand) Run(args []string) int { 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 // We create two metas to track the two states
var meta1, meta2 Meta var meta1, meta2 Meta

View File

@ -16,7 +16,10 @@ type StatePullCommand struct {
} }
func (c *StatePullCommand) Run(args []string) int { 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") cmdFlags := c.Meta.flagSet("state pull")
if err := cmdFlags.Parse(args); err != nil { if err := cmdFlags.Parse(args); err != nil {

View File

@ -17,7 +17,10 @@ type StatePushCommand struct {
} }
func (c *StatePushCommand) Run(args []string) int { 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 var flagForce bool
cmdFlags := c.Meta.flagSet("state push") cmdFlags := c.Meta.flagSet("state push")

View File

@ -14,7 +14,10 @@ type StateRmCommand struct {
} }
func (c *StateRmCommand) Run(args []string) int { 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 := c.Meta.flagSet("state show")
cmdFlags.StringVar(&c.Meta.backupPath, "backup", "-", "backup") cmdFlags.StringVar(&c.Meta.backupPath, "backup", "-", "backup")

View File

@ -17,7 +17,10 @@ type StateShowCommand struct {
} }
func (c *StateShowCommand) Run(args []string) int { 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 := c.Meta.flagSet("state show")
cmdFlags.StringVar(&c.Meta.statePath, "state", DefaultStateFilename, "path") cmdFlags.StringVar(&c.Meta.statePath, "state", DefaultStateFilename, "path")

View File

@ -18,7 +18,10 @@ type TaintCommand struct {
} }
func (c *TaintCommand) Run(args []string) int { 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 allowMissing bool
var module string var module string

View File

@ -16,7 +16,10 @@ type UnlockCommand struct {
} }
func (c *UnlockCommand) Run(args []string) int { 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 force := false
cmdFlags := c.Meta.flagSet("force-unlock") cmdFlags := c.Meta.flagSet("force-unlock")

View File

@ -17,7 +17,10 @@ type UntaintCommand struct {
} }
func (c *UntaintCommand) Run(args []string) int { 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 allowMissing bool
var module string var module string

View File

@ -17,7 +17,10 @@ type ValidateCommand struct {
const defaultPath = "." const defaultPath = "."
func (c *ValidateCommand) Run(args []string) int { 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 var checkVars bool
cmdFlags := c.Meta.flagSet("validate") cmdFlags := c.Meta.flagSet("validate")

View File

@ -34,7 +34,10 @@ func (c *VersionCommand) Help() string {
func (c *VersionCommand) Run(args []string) int { func (c *VersionCommand) Run(args []string) int {
var versionString bytes.Buffer 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) fmt.Fprintf(&versionString, "Terraform v%s", c.Version)
if c.VersionPrerelease != "" { if c.VersionPrerelease != "" {

View File

@ -15,7 +15,10 @@ type WorkspaceCommand struct {
} }
func (c *WorkspaceCommand) Run(args []string) int { 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) envCommandShowWarning(c.Ui, c.LegacyName)

View File

@ -16,7 +16,10 @@ type WorkspaceDeleteCommand struct {
} }
func (c *WorkspaceDeleteCommand) Run(args []string) int { 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) envCommandShowWarning(c.Ui, c.LegacyName)

View File

@ -12,7 +12,10 @@ type WorkspaceListCommand struct {
} }
func (c *WorkspaceListCommand) Run(args []string) int { 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) envCommandShowWarning(c.Ui, c.LegacyName)

View File

@ -18,7 +18,10 @@ type WorkspaceNewCommand struct {
} }
func (c *WorkspaceNewCommand) Run(args []string) int { 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) envCommandShowWarning(c.Ui, c.LegacyName)

View File

@ -13,7 +13,10 @@ type WorkspaceSelectCommand struct {
} }
func (c *WorkspaceSelectCommand) Run(args []string) int { 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) envCommandShowWarning(c.Ui, c.LegacyName)

View File

@ -9,7 +9,10 @@ type WorkspaceShowCommand struct {
} }
func (c *WorkspaceShowCommand) Run(args []string) int { 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 := c.Meta.flagSet("workspace show")
cmdFlags.Usage = func() { c.Ui.Error(c.Help()) } cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }

View File

@ -194,7 +194,7 @@ func dirFiles(dir string) ([]string, []string, error) {
// Only care about files that are valid to load // Only care about files that are valid to load
name := fi.Name() name := fi.Name()
extValue := ext(name) extValue := ext(name)
if extValue == "" || isIgnoredFile(name) { if extValue == "" || IsIgnoredFile(name) {
continue continue
} }
@ -215,9 +215,9 @@ func dirFiles(dir string) ([]string, []string, error) {
return files, overrides, nil 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. // 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 return strings.HasPrefix(name, ".") || // Unix-like hidden files
strings.HasSuffix(name, "~") || // vim strings.HasSuffix(name, "~") || // vim
strings.HasPrefix(name, "#") && strings.HasSuffix(name, "#") // emacs strings.HasPrefix(name, "#") && strings.HasSuffix(name, "#") // emacs

View File

@ -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 * `-var-file=foo` - Set variables in the Terraform configuration from
a [variable file](/docs/configuration/variables.html#variable-files). If a [variable file](/docs/configuration/variables.html#variable-files). If
"terraform.tfvars" is present, it will be automatically loaded first. Any any files matching "*.tfvars" are present, they will be automatically loaded
files specified by `-var-file` override any values in a "terraform.tfvars". in alphabetical order. Any files specified by `-var-file` override any values
This flag can be used multiple times. set automatically from files in the working directory. This flag can be used
multiple times.

View File

@ -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 * `-var-file=foo` - Set variables in the Terraform configuration from
a [variable file](/docs/configuration/variables.html#variable-files). If a [variable file](/docs/configuration/variables.html#variable-files). If
"terraform.tfvars" is present, it will be automatically loaded first. Any any file matching "*.tfvars" are present, they will be automatically loaded
files specified by `-var-file` override any values in a "terraform.tfvars". in alphabetical order. Any files specified by `-var-file` override any values
This flag can be used multiple times. This is only useful with the `-config` set automatically from files in the working directory. This flag can be used
flag. multiple times. This is only useful with the `-config` flag.
## Provider Configuration ## Provider Configuration

View File

@ -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 * `-var-file=foo` - Set variables in the Terraform configuration from
a [variable file](/docs/configuration/variables.html#variable-files). If a [variable file](/docs/configuration/variables.html#variable-files). If
"terraform.tfvars" is present, it will be automatically loaded first. Any any files matching "*.tfvars" are present, they will be automatically loaded
files specified by `-var-file` override any values in a "terraform.tfvars". in alphabetical order. Any files specified by `-var-file` override any values
This flag can be used multiple times. set automatically from files in the working directory. This flag can be used
multiple times.
## Resource Targeting ## Resource Targeting

View File

@ -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 * `-var-file=foo` - Set variables in the Terraform configuration from
a [variable file](/docs/configuration/variables.html#variable-files). If a [variable file](/docs/configuration/variables.html#variable-files). If
"terraform.tfvars" is present, it will be automatically loaded first. Any any files matching "*.tfvars" are present, they will be automatically loaded
files specified by `-var-file` override any values in a "terraform.tfvars". in alphabetical order. Any files specified by `-var-file` override any values
This flag can be used multiple times. set automatically from files in the working directory. This flag can be used
multiple times.

View File

@ -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 Variables can be collected in files and passed all at once using the
`-var-file=foo.tfvars` flag. `-var-file=foo.tfvars` flag.
If a file named `terraform.tfvars` is present in the current directory, For all files which match `*.tfvars` present in the current directory,
Terraform automatically loads it to populate variables. If the file is named Terraform automatically loads it to populate variables. If the file is located
something else, you can pass the path to the file using the `-var-file` somewhere else, you can pass the path to the file using the `-var-file` flag.
flag.
Variables files use HCL or JSON to define variable values. Strings, lists or 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 maps may be set in the same manner as the default value in a `variable` block
@ -338,11 +337,18 @@ _bar.tfvars_
baz = "bar" 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 ```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` The result will be that `baz` will contain the value `bar` because `bar.tfvars`
has the last definition loaded. has the last definition loaded.
Definitions passed using the `-var-file` flag will always be evaluated after
those in the working directory.

View File

@ -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.