From b05e36a6e378008adf2c435942651e269fd9c586 Mon Sep 17 00:00:00 2001 From: Kirill Shirinkin Date: Wed, 27 May 2015 16:46:12 +0200 Subject: [PATCH 1/2] Add module outputs --- command/output.go | 26 ++++++++++++-- command/output_test.go | 77 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+), 2 deletions(-) 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{ From b945d1ee0ba3fbb132f323324697b38b2aade3eb Mon Sep 17 00:00:00 2001 From: Kirill Shirinkin Date: Wed, 27 May 2015 17:11:31 +0200 Subject: [PATCH 2/2] Update docs --- website/source/docs/commands/output.html.markdown | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/website/source/docs/commands/output.html.markdown b/website/source/docs/commands/output.html.markdown index ac1ab5a23..f1a70394e 100644 --- a/website/source/docs/commands/output.html.markdown +++ b/website/source/docs/commands/output.html.markdown @@ -21,4 +21,8 @@ current directory for the state file to query. The command-line flags are all optional. The list of available flags are: * `-state=path` - Path to the state file. Defaults to "terraform.tfstate". - +* `-module=module_name` - The module path which has needed output. + By default this is the root path. Other modules can be specified by + a period-separated list. Example: "foo" would reference the module + "foo" but "foo.bar" would reference the "bar" module in the "foo" + module.