core: Correctly format nested outputs

This commit pretty prints outputs which consist of nested complex
structures (e.g. lists of lists, lists of maps).

Fixes #7143.
This commit is contained in:
James Nugent 2016-07-12 10:35:44 -06:00
parent ecdc5065bf
commit ef3aad1231
1 changed files with 77 additions and 5 deletions

View File

@ -122,7 +122,16 @@ func (c *OutputCommand) Run(args []string) int {
break break
} }
c.Ui.Output(fmt.Sprintf("%s", output[indexInt])) outputVal := output[indexInt]
switch typedOutputVal := outputVal.(type) {
case string:
c.Ui.Output(fmt.Sprintf("%s", typedOutputVal))
case []interface{}:
c.Ui.Output(fmt.Sprintf("%s", formatNestedList("", typedOutputVal)))
case map[string]interface{}:
c.Ui.Output(fmt.Sprintf("%s", formatNestedMap("", typedOutputVal)))
}
return 0 return 0
case map[string]interface{}: case map[string]interface{}:
if index == "" { if index == "" {
@ -131,7 +140,14 @@ func (c *OutputCommand) Run(args []string) int {
} }
if value, ok := output[index]; ok { if value, ok := output[index]; ok {
c.Ui.Output(fmt.Sprintf("%s", value)) switch typedOutputVal := value.(type) {
case string:
c.Ui.Output(fmt.Sprintf("%s", typedOutputVal))
case []interface{}:
c.Ui.Output(fmt.Sprintf("%s", formatNestedList("", typedOutputVal)))
case map[string]interface{}:
c.Ui.Output(fmt.Sprintf("%s", formatNestedMap("", typedOutputVal)))
}
return 0 return 0
} else { } else {
return 1 return 1
@ -144,6 +160,23 @@ func (c *OutputCommand) Run(args []string) int {
return 0 return 0
} }
func formatNestedList(indent string, outputList []interface{}) string {
outputBuf := new(bytes.Buffer)
outputBuf.WriteString(fmt.Sprintf("%s[", indent))
lastIdx := len(outputList) - 1
for i, value := range outputList {
outputBuf.WriteString(fmt.Sprintf("\n%s%s%s", indent, " ", value))
if i != lastIdx {
outputBuf.WriteString(",")
}
}
outputBuf.WriteString(fmt.Sprintf("\n%s]", indent))
return strings.TrimPrefix(outputBuf.String(), "\n")
}
func formatListOutput(indent, outputName string, outputList []interface{}) string { func formatListOutput(indent, outputName string, outputList []interface{}) string {
keyIndent := "" keyIndent := ""
@ -154,8 +187,23 @@ func formatListOutput(indent, outputName string, outputList []interface{}) strin
keyIndent = " " keyIndent = " "
} }
for _, value := range outputList { lastIdx := len(outputList) - 1
for i, value := range outputList {
switch typedValue := value.(type) {
case string:
outputBuf.WriteString(fmt.Sprintf("\n%s%s%s", indent, keyIndent, value)) outputBuf.WriteString(fmt.Sprintf("\n%s%s%s", indent, keyIndent, value))
case []interface{}:
outputBuf.WriteString(fmt.Sprintf("\n%s%s", indent,
formatNestedList(indent+keyIndent, typedValue)))
case map[string]interface{}:
outputBuf.WriteString(fmt.Sprintf("\n%s%s", indent,
formatNestedMap(indent+keyIndent, typedValue)))
}
if lastIdx != i {
outputBuf.WriteString(",")
}
} }
if outputName != "" { if outputName != "" {
@ -169,6 +217,30 @@ func formatListOutput(indent, outputName string, outputList []interface{}) strin
return strings.TrimPrefix(outputBuf.String(), "\n") return strings.TrimPrefix(outputBuf.String(), "\n")
} }
func formatNestedMap(indent string, outputMap map[string]interface{}) string {
ks := make([]string, 0, len(outputMap))
for k, _ := range outputMap {
ks = append(ks, k)
}
sort.Strings(ks)
outputBuf := new(bytes.Buffer)
outputBuf.WriteString(fmt.Sprintf("%s{", indent))
lastIdx := len(outputMap) - 1
for i, k := range ks {
v := outputMap[k]
outputBuf.WriteString(fmt.Sprintf("\n%s%s = %v", indent+" ", k, v))
if lastIdx != i {
outputBuf.WriteString(",")
}
}
outputBuf.WriteString(fmt.Sprintf("\n%s}", indent))
return strings.TrimPrefix(outputBuf.String(), "\n")
}
func formatMapOutput(indent, outputName string, outputMap map[string]interface{}) string { func formatMapOutput(indent, outputName string, outputMap map[string]interface{}) string {
ks := make([]string, 0, len(outputMap)) ks := make([]string, 0, len(outputMap))
for k, _ := range outputMap { for k, _ := range outputMap {