diff --git a/command/graph.go b/command/graph.go index 97473f5ce..802c3c805 100644 --- a/command/graph.go +++ b/command/graph.go @@ -23,7 +23,7 @@ func (c *GraphCommand) Run(args []string) int { args = c.Meta.process(args, false) cmdFlags := flag.NewFlagSet("graph", flag.ContinueOnError) - cmdFlags.IntVar(&moduleDepth, "module-depth", 0, "module-depth") + c.addModuleDepthFlag(cmdFlags, &moduleDepth) cmdFlags.BoolVar(&verbose, "verbose", false, "verbose") cmdFlags.BoolVar(&drawCycles, "draw-cycles", false, "draw-cycles") cmdFlags.Usage = func() { c.Ui.Error(c.Help()) } diff --git a/command/meta.go b/command/meta.go index e3d5de794..7237a8d61 100644 --- a/command/meta.go +++ b/command/meta.go @@ -399,6 +399,20 @@ func (m *Meta) uiHook() *UiHook { } } +const ( + // The name of the environment variable that can be used to set module depth. + ModuleDepthEnvVar = "TF_MODULE_DEPTH" +) + +func (m *Meta) addModuleDepthFlag(flags *flag.FlagSet, moduleDepth *int) { + flags.IntVar(moduleDepth, "module-depth", 0, "module-depth") + if envVar := os.Getenv(ModuleDepthEnvVar); envVar != "" { + if md, err := strconv.Atoi(envVar); err == nil { + *moduleDepth = md + } + } +} + // contextOpts are the options used to load a context from a command. type contextOpts struct { // Path to the directory where the root module is. diff --git a/command/meta_test.go b/command/meta_test.go index 6df29002b..bb3b34107 100644 --- a/command/meta_test.go +++ b/command/meta_test.go @@ -1,6 +1,7 @@ package command import ( + "flag" "io/ioutil" "os" "path/filepath" @@ -215,3 +216,55 @@ func TestMeta_initStatePaths(t *testing.T) { t.Fatalf("bad: %#v", m) } } + +func TestMeta_addModuleDepthFlag(t *testing.T) { + old := os.Getenv(ModuleDepthEnvVar) + defer os.Setenv(ModuleDepthEnvVar, old) + + cases := map[string]struct { + EnvVar string + Args []string + Expected int + }{ + "env var sets value when no flag present": { + EnvVar: "4", + Args: []string{}, + Expected: 4, + }, + "flag overrides envvar": { + EnvVar: "4", + Args: []string{"-module-depth=-1"}, + Expected: -1, + }, + "negative envvar works": { + EnvVar: "-1", + Args: []string{}, + Expected: -1, + }, + "invalid envvar is ignored": { + EnvVar: "-#", + Args: []string{}, + Expected: 0, + }, + "empty envvar is okay too": { + EnvVar: "", + Args: []string{}, + Expected: 0, + }, + } + + for tn, tc := range cases { + m := new(Meta) + var moduleDepth int + flags := flag.NewFlagSet("test", flag.ContinueOnError) + os.Setenv(ModuleDepthEnvVar, tc.EnvVar) + m.addModuleDepthFlag(flags, &moduleDepth) + err := flags.Parse(tc.Args) + if err != nil { + t.Fatalf("%s: err: %#v", tn, err) + } + if moduleDepth != tc.Expected { + t.Fatalf("%s: expected: %#v, got: %#v", tn, tc.Expected, moduleDepth) + } + } +} diff --git a/command/plan.go b/command/plan.go index f23e1bb6e..083373c3a 100644 --- a/command/plan.go +++ b/command/plan.go @@ -25,7 +25,7 @@ func (c *PlanCommand) Run(args []string) int { cmdFlags := c.Meta.flagSet("plan") cmdFlags.BoolVar(&destroy, "destroy", false, "destroy") cmdFlags.BoolVar(&refresh, "refresh", true, "refresh") - cmdFlags.IntVar(&moduleDepth, "module-depth", 0, "module-depth") + c.addModuleDepthFlag(cmdFlags, &moduleDepth) cmdFlags.StringVar(&outPath, "out", "", "path") cmdFlags.StringVar(&c.Meta.statePath, "state", DefaultStateFilename, "path") cmdFlags.StringVar(&c.Meta.backupPath, "backup", "", "path") diff --git a/command/show.go b/command/show.go index c4e095a42..cf7b6cfa6 100644 --- a/command/show.go +++ b/command/show.go @@ -22,7 +22,7 @@ func (c *ShowCommand) Run(args []string) int { args = c.Meta.process(args, false) cmdFlags := flag.NewFlagSet("show", flag.ContinueOnError) - cmdFlags.IntVar(&moduleDepth, "module-depth", 0, "module-depth") + c.addModuleDepthFlag(cmdFlags, &moduleDepth) cmdFlags.Usage = func() { c.Ui.Error(c.Help()) } if err := cmdFlags.Parse(args); err != nil { return 1