Merge pull request #2102 from Fodoj/add-module-outputs
Add module outputs
This commit is contained in:
commit
e91705ac96
|
@ -15,9 +15,12 @@ type OutputCommand struct {
|
||||||
func (c *OutputCommand) Run(args []string) int {
|
func (c *OutputCommand) Run(args []string) int {
|
||||||
args = c.Meta.process(args, false)
|
args = c.Meta.process(args, false)
|
||||||
|
|
||||||
|
var module string
|
||||||
cmdFlags := flag.NewFlagSet("output", flag.ContinueOnError)
|
cmdFlags := flag.NewFlagSet("output", flag.ContinueOnError)
|
||||||
cmdFlags.StringVar(&c.Meta.statePath, "state", DefaultStateFilename, "path")
|
cmdFlags.StringVar(&c.Meta.statePath, "state", DefaultStateFilename, "path")
|
||||||
|
cmdFlags.StringVar(&module, "module", "", "module")
|
||||||
cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }
|
cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }
|
||||||
|
|
||||||
if err := cmdFlags.Parse(args); err != nil {
|
if err := cmdFlags.Parse(args); err != nil {
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
@ -38,15 +41,34 @@ func (c *OutputCommand) Run(args []string) int {
|
||||||
return 1
|
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()
|
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(
|
c.Ui.Error(fmt.Sprintf(
|
||||||
"The state file has no outputs defined. Define an output\n" +
|
"The state file has no outputs defined. Define an output\n" +
|
||||||
"in your configuration with the `output` directive and re-run\n" +
|
"in your configuration with the `output` directive and re-run\n" +
|
||||||
"`terraform apply` for it to become available."))
|
"`terraform apply` for it to become available."))
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
v, ok := state.RootModule().Outputs[name]
|
|
||||||
|
v, ok := mod.Outputs[name]
|
||||||
if !ok {
|
if !ok {
|
||||||
c.Ui.Error(fmt.Sprintf(
|
c.Ui.Error(fmt.Sprintf(
|
||||||
"The output variable requested could not be found in the state\n" +
|
"The output variable requested could not be found in the state\n" +
|
||||||
|
|
|
@ -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) {
|
func TestOutput_badVar(t *testing.T) {
|
||||||
originalState := &terraform.State{
|
originalState := &terraform.State{
|
||||||
Modules: []*terraform.ModuleState{
|
Modules: []*terraform.ModuleState{
|
||||||
|
|
|
@ -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:
|
The command-line flags are all optional. The list of available flags are:
|
||||||
|
|
||||||
* `-state=path` - Path to the state file. Defaults to "terraform.tfstate".
|
* `-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.
|
||||||
|
|
Loading…
Reference in New Issue