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"
|
||||
)
|
||||
|
||||
// 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
|
||||
func FormatState(s *terraform.State, c *colorstring.Colorize) string {
|
||||
if c == nil {
|
||||
func FormatState(opts *FormatStateOpts) string {
|
||||
if opts.Color == nil {
|
||||
panic("colorize not given")
|
||||
}
|
||||
|
||||
s := opts.State
|
||||
if len(s.Modules) == 0 {
|
||||
return "The state file is empty. No resources are represented."
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
buf.WriteString("[reset]")
|
||||
|
||||
// Format all the 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) {
|
||||
buf.WriteString("[reset]")
|
||||
func formatStateModuleExpand(
|
||||
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
|
||||
// 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.
|
||||
for _, k := range names {
|
||||
name := k
|
||||
if moduleName != "" {
|
||||
name = moduleName + "." + name
|
||||
}
|
||||
|
||||
rs := m.Resources[k]
|
||||
is := rs.Primary
|
||||
id := is.ID
|
||||
|
@ -53,7 +102,7 @@ func formatStateModule(buf *bytes.Buffer, m *terraform.ModuleState, c *colorstri
|
|||
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))
|
||||
|
||||
// Sort the attributes
|
||||
|
@ -75,20 +124,14 @@ func formatStateModule(buf *bytes.Buffer, m *terraform.ModuleState, c *colorstri
|
|||
}
|
||||
}
|
||||
|
||||
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))
|
||||
}
|
||||
}
|
||||
buf.WriteString("[reset]\n")
|
||||
}
|
||||
|
||||
func formatStateModuleSingle(
|
||||
buf *bytes.Buffer, m *terraform.ModuleState, opts *FormatStateOpts) {
|
||||
// Header with the module name
|
||||
buf.WriteString(fmt.Sprintf("module.%s\n", strings.Join(m.Path[1:], ".")))
|
||||
|
||||
// Now just write how many resources are in here.
|
||||
buf.WriteString(fmt.Sprintf(" %d resource(s)\n", len(m.Resources)))
|
||||
}
|
||||
|
|
|
@ -16,9 +16,12 @@ type ShowCommand struct {
|
|||
}
|
||||
|
||||
func (c *ShowCommand) Run(args []string) int {
|
||||
var moduleDepth int
|
||||
|
||||
args = c.Meta.process(args, false)
|
||||
|
||||
cmdFlags := flag.NewFlagSet("show", flag.ContinueOnError)
|
||||
cmdFlags.IntVar(&moduleDepth, "module-depth", 0, "module-depth")
|
||||
cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }
|
||||
if err := cmdFlags.Parse(args); err != nil {
|
||||
return 1
|
||||
|
@ -73,13 +76,18 @@ func (c *ShowCommand) Run(args []string) int {
|
|||
|
||||
if plan != nil {
|
||||
c.Ui.Output(FormatPlan(&FormatPlanOpts{
|
||||
Plan: plan,
|
||||
Color: c.Colorize(),
|
||||
Plan: plan,
|
||||
Color: c.Colorize(),
|
||||
ModuleDepth: moduleDepth,
|
||||
}))
|
||||
return 0
|
||||
}
|
||||
|
||||
c.Ui.Output(FormatState(state, c.Colorize()))
|
||||
c.Ui.Output(FormatState(&FormatStateOpts{
|
||||
State: state,
|
||||
Color: c.Colorize(),
|
||||
ModuleDepth: moduleDepth,
|
||||
}))
|
||||
return 0
|
||||
}
|
||||
|
||||
|
@ -92,7 +100,10 @@ Usage: terraform show [options] path
|
|||
|
||||
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)
|
||||
|
|
|
@ -182,6 +182,11 @@ type ModuleState struct {
|
|||
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
|
||||
// but aren't present in the configuration itself. Hence, these keys
|
||||
// represent the state of resources that are orphans.
|
||||
|
|
Loading…
Reference in New Issue