command: state output is well formatted for modules
This commit is contained in:
parent
30dcacf29f
commit
e5e51d7b17
|
@ -10,26 +10,70 @@ import (
|
||||||
"github.com/mitchellh/colorstring"
|
"github.com/mitchellh/colorstring"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// FormatStateOpts are the options for formatting a state.
|
||||||
|
type FormatStateOpts struct {
|
||||||
|
// State is the state to format. This is required.
|
||||||
|
State *terraform.State
|
||||||
|
|
||||||
|
// Color is the colorizer. This is optional.
|
||||||
|
Color *colorstring.Colorize
|
||||||
|
|
||||||
|
// ModuleDepth is the depth of the modules to expand. By default this
|
||||||
|
// is zero which will not expand modules at all.
|
||||||
|
ModuleDepth int
|
||||||
|
}
|
||||||
|
|
||||||
// FormatState takes a state and returns a string
|
// FormatState takes a state and returns a string
|
||||||
func FormatState(s *terraform.State, c *colorstring.Colorize) string {
|
func FormatState(opts *FormatStateOpts) string {
|
||||||
if c == nil {
|
if opts.Color == nil {
|
||||||
panic("colorize not given")
|
panic("colorize not given")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s := opts.State
|
||||||
if len(s.Modules) == 0 {
|
if len(s.Modules) == 0 {
|
||||||
return "The state file is empty. No resources are represented."
|
return "The state file is empty. No resources are represented."
|
||||||
}
|
}
|
||||||
|
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
|
buf.WriteString("[reset]")
|
||||||
|
|
||||||
|
// Format all the modules
|
||||||
for _, m := range s.Modules {
|
for _, m := range s.Modules {
|
||||||
formatStateModule(&buf, m, c)
|
if len(m.Path)-1 <= opts.ModuleDepth || opts.ModuleDepth == -1 {
|
||||||
|
formatStateModuleExpand(&buf, m, opts)
|
||||||
|
} else {
|
||||||
|
formatStateModuleSingle(&buf, m, opts)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.Color(strings.TrimSpace(buf.String()))
|
// Write the outputs for the root module
|
||||||
|
m := s.RootModule()
|
||||||
|
if len(m.Outputs) > 0 {
|
||||||
|
buf.WriteString("\nOutputs:\n\n")
|
||||||
|
|
||||||
|
// Sort the outputs
|
||||||
|
ks := make([]string, 0, len(m.Outputs))
|
||||||
|
for k, _ := range m.Outputs {
|
||||||
|
ks = append(ks, k)
|
||||||
|
}
|
||||||
|
sort.Strings(ks)
|
||||||
|
|
||||||
|
// Output each output k/v pair
|
||||||
|
for _, k := range ks {
|
||||||
|
v := m.Outputs[k]
|
||||||
|
buf.WriteString(fmt.Sprintf("%s = %s\n", k, v))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return opts.Color.Color(strings.TrimSpace(buf.String()))
|
||||||
}
|
}
|
||||||
|
|
||||||
func formatStateModule(buf *bytes.Buffer, m *terraform.ModuleState, c *colorstring.Colorize) {
|
func formatStateModuleExpand(
|
||||||
buf.WriteString("[reset]")
|
buf *bytes.Buffer, m *terraform.ModuleState, opts *FormatStateOpts) {
|
||||||
|
var moduleName string
|
||||||
|
if !m.IsRoot() {
|
||||||
|
moduleName = fmt.Sprintf("module.%s", strings.Join(m.Path[1:], "."))
|
||||||
|
}
|
||||||
|
|
||||||
// First get the names of all the resources so we can show them
|
// First get the names of all the resources so we can show them
|
||||||
// in alphabetical order.
|
// in alphabetical order.
|
||||||
|
@ -41,6 +85,11 @@ func formatStateModule(buf *bytes.Buffer, m *terraform.ModuleState, c *colorstri
|
||||||
|
|
||||||
// Go through each resource and begin building up the output.
|
// Go through each resource and begin building up the output.
|
||||||
for _, k := range names {
|
for _, k := range names {
|
||||||
|
name := k
|
||||||
|
if moduleName != "" {
|
||||||
|
name = moduleName + "." + name
|
||||||
|
}
|
||||||
|
|
||||||
rs := m.Resources[k]
|
rs := m.Resources[k]
|
||||||
is := rs.Primary
|
is := rs.Primary
|
||||||
id := is.ID
|
id := is.ID
|
||||||
|
@ -53,7 +102,7 @@ func formatStateModule(buf *bytes.Buffer, m *terraform.ModuleState, c *colorstri
|
||||||
taintStr = " (tainted)"
|
taintStr = " (tainted)"
|
||||||
}
|
}
|
||||||
|
|
||||||
buf.WriteString(fmt.Sprintf("%s:%s\n", k, taintStr))
|
buf.WriteString(fmt.Sprintf("%s:%s\n", name, taintStr))
|
||||||
buf.WriteString(fmt.Sprintf(" id = %s\n", id))
|
buf.WriteString(fmt.Sprintf(" id = %s\n", id))
|
||||||
|
|
||||||
// Sort the attributes
|
// Sort the attributes
|
||||||
|
@ -75,20 +124,14 @@ func formatStateModule(buf *bytes.Buffer, m *terraform.ModuleState, c *colorstri
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(m.Outputs) > 0 {
|
buf.WriteString("[reset]\n")
|
||||||
buf.WriteString("\nOutputs:\n\n")
|
}
|
||||||
|
|
||||||
// Sort the outputs
|
func formatStateModuleSingle(
|
||||||
ks := make([]string, 0, len(m.Outputs))
|
buf *bytes.Buffer, m *terraform.ModuleState, opts *FormatStateOpts) {
|
||||||
for k, _ := range m.Outputs {
|
// Header with the module name
|
||||||
ks = append(ks, k)
|
buf.WriteString(fmt.Sprintf("module.%s\n", strings.Join(m.Path[1:], ".")))
|
||||||
}
|
|
||||||
sort.Strings(ks)
|
// Now just write how many resources are in here.
|
||||||
|
buf.WriteString(fmt.Sprintf(" %d resource(s)\n", len(m.Resources)))
|
||||||
// Output each output k/v pair
|
|
||||||
for _, k := range ks {
|
|
||||||
v := m.Outputs[k]
|
|
||||||
buf.WriteString(fmt.Sprintf("%s = %s\n", k, v))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,9 +16,12 @@ type ShowCommand struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ShowCommand) Run(args []string) int {
|
func (c *ShowCommand) Run(args []string) int {
|
||||||
|
var moduleDepth int
|
||||||
|
|
||||||
args = c.Meta.process(args, false)
|
args = c.Meta.process(args, false)
|
||||||
|
|
||||||
cmdFlags := flag.NewFlagSet("show", flag.ContinueOnError)
|
cmdFlags := flag.NewFlagSet("show", flag.ContinueOnError)
|
||||||
|
cmdFlags.IntVar(&moduleDepth, "module-depth", 0, "module-depth")
|
||||||
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
|
||||||
|
@ -73,13 +76,18 @@ func (c *ShowCommand) Run(args []string) int {
|
||||||
|
|
||||||
if plan != nil {
|
if plan != nil {
|
||||||
c.Ui.Output(FormatPlan(&FormatPlanOpts{
|
c.Ui.Output(FormatPlan(&FormatPlanOpts{
|
||||||
Plan: plan,
|
Plan: plan,
|
||||||
Color: c.Colorize(),
|
Color: c.Colorize(),
|
||||||
|
ModuleDepth: moduleDepth,
|
||||||
}))
|
}))
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Ui.Output(FormatState(state, c.Colorize()))
|
c.Ui.Output(FormatState(&FormatStateOpts{
|
||||||
|
State: state,
|
||||||
|
Color: c.Colorize(),
|
||||||
|
ModuleDepth: moduleDepth,
|
||||||
|
}))
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,7 +100,10 @@ Usage: terraform show [options] path
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
|
|
||||||
-no-color If specified, output won't contain any color.
|
-module-depth=n Specifies the depth of modules to show in the output.
|
||||||
|
By default this is zero. -1 will expand all.
|
||||||
|
|
||||||
|
-no-color If specified, output won't contain any color.
|
||||||
|
|
||||||
`
|
`
|
||||||
return strings.TrimSpace(helpText)
|
return strings.TrimSpace(helpText)
|
||||||
|
|
|
@ -182,6 +182,11 @@ type ModuleState struct {
|
||||||
Resources map[string]*ResourceState `json:"resources"`
|
Resources map[string]*ResourceState `json:"resources"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsRoot says whether or not this module diff is for the root module.
|
||||||
|
func (m *ModuleState) IsRoot() bool {
|
||||||
|
return reflect.DeepEqual(m.Path, rootModulePath)
|
||||||
|
}
|
||||||
|
|
||||||
// Orphans returns a list of keys of resources that are in the State
|
// Orphans returns a list of keys of resources that are in the State
|
||||||
// but aren't present in the configuration itself. Hence, these keys
|
// but aren't present in the configuration itself. Hence, these keys
|
||||||
// represent the state of resources that are orphans.
|
// represent the state of resources that are orphans.
|
||||||
|
|
Loading…
Reference in New Issue