diff --git a/command/output.go b/command/output.go index 2e3c1bee0..9e99cce5f 100644 --- a/command/output.go +++ b/command/output.go @@ -15,9 +15,12 @@ type OutputCommand struct { func (c *OutputCommand) Run(args []string) int { args = c.Meta.process(args, false) + var module string cmdFlags := flag.NewFlagSet("output", flag.ContinueOnError) cmdFlags.StringVar(&c.Meta.statePath, "state", DefaultStateFilename, "path") + cmdFlags.StringVar(&module, "module", "", "module") cmdFlags.Usage = func() { c.Ui.Error(c.Help()) } + if err := cmdFlags.Parse(args); err != nil { return 1 } @@ -38,15 +41,34 @@ func (c *OutputCommand) Run(args []string) int { return 1 } + if module == "" { + module = "root" + } else { + module = "root." + module + } + + // Get the proper module we want to get outputs for + modPath := strings.Split(module, ".") + state := stateStore.State() - if state.Empty() || len(state.RootModule().Outputs) == 0 { + mod := state.ModuleByPath(modPath) + + if mod == nil { + c.Ui.Error(fmt.Sprintf( + "The module %s could not be found. There is nothing to taint.", + module)) + return 1 + } + + if state.Empty() || len(mod.Outputs) == 0 { c.Ui.Error(fmt.Sprintf( "The state file has no outputs defined. Define an output\n" + "in your configuration with the `output` directive and re-run\n" + "`terraform apply` for it to become available.")) return 1 } - v, ok := state.RootModule().Outputs[name] + + v, ok := mod.Outputs[name] if !ok { c.Ui.Error(fmt.Sprintf( "The output variable requested could not be found in the state\n" + diff --git a/command/output_test.go b/command/output_test.go index d3444c389..f84642269 100644 --- a/command/output_test.go +++ b/command/output_test.go @@ -47,6 +47,83 @@ func TestOutput(t *testing.T) { } } +func TestModuleOutput(t *testing.T) { + originalState := &terraform.State{ + Modules: []*terraform.ModuleState{ + &terraform.ModuleState{ + Path: []string{"root"}, + Outputs: map[string]string{ + "foo": "bar", + }, + }, + &terraform.ModuleState{ + Path: []string{"root", "my_module"}, + Outputs: map[string]string{ + "blah": "tastatur", + }, + }, + }, + } + + statePath := testStateFile(t, originalState) + + ui := new(cli.MockUi) + c := &OutputCommand{ + Meta: Meta{ + ContextOpts: testCtxConfig(testProvider()), + Ui: ui, + }, + } + + args := []string{ + "-state", statePath, + "-module", "my_module", + "blah", + } + + if code := c.Run(args); code != 0 { + t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) + } + + actual := strings.TrimSpace(ui.OutputWriter.String()) + if actual != "tastatur" { + t.Fatalf("bad: %#v", actual) + } +} + +func TestMissingModuleOutput(t *testing.T) { + originalState := &terraform.State{ + Modules: []*terraform.ModuleState{ + &terraform.ModuleState{ + Path: []string{"root"}, + Outputs: map[string]string{ + "foo": "bar", + }, + }, + }, + } + + statePath := testStateFile(t, originalState) + + ui := new(cli.MockUi) + c := &OutputCommand{ + Meta: Meta{ + ContextOpts: testCtxConfig(testProvider()), + Ui: ui, + }, + } + + args := []string{ + "-state", statePath, + "-module", "not_existing_module", + "blah", + } + + if code := c.Run(args); code != 1 { + t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) + } +} + func TestOutput_badVar(t *testing.T) { originalState := &terraform.State{ Modules: []*terraform.ModuleState{