command/format: minor adjustments to plan rendering
This change makes various minor adjustments to the rendering of plans in the output of "terraform plan": - Resources are identified using the standard resource address syntax, rather than exposing the legacy internal representation used in the module diff resource keys. This fixes #8713. - Subjectively, having square brackets in the addresses made it look more visually "off" when the same name but with different indices were shown together with differing-length "symbols", so the symbols are now all padded and right-aligned to three characters for consistent layout across all operations. - The -/+ action is now more visually distinct, using several different colors to help communicate what it will do and including a more obvious "(new resource required)" marker to help draw attention to this not being just an update diff. This fixes #15350. - The resources are now sorted in a manner that sorts index [10] after index [9], rather than after index [1] as we did before. This makes it easier to scan the list and avoids the common confusion where it seems that there are only 10 items when in fact there are 11-20 items with all the tens hiding further up in the list.
This commit is contained in:
parent
53c0ff4017
commit
0dc6d97a37
|
@ -6,6 +6,7 @@ import (
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/config"
|
||||||
"github.com/hashicorp/terraform/terraform"
|
"github.com/hashicorp/terraform/terraform"
|
||||||
"github.com/mitchellh/colorstring"
|
"github.com/mitchellh/colorstring"
|
||||||
)
|
)
|
||||||
|
@ -58,18 +59,27 @@ func formatPlanModuleExpand(
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var moduleName string
|
var modulePath []string
|
||||||
if !m.IsRoot() {
|
if !m.IsRoot() {
|
||||||
moduleName = fmt.Sprintf("module.%s", strings.Join(m.Path[1:], "."))
|
modulePath = m.Path[1:]
|
||||||
}
|
}
|
||||||
|
|
||||||
// We want to output the resources in sorted order to make things
|
// We want to output the resources in sorted order to make things
|
||||||
// easier to scan through, so get all the resource names and sort them.
|
// easier to scan through, so get all the resource names and sort them.
|
||||||
names := make([]string, 0, len(m.Resources))
|
names := make([]string, 0, len(m.Resources))
|
||||||
for name, _ := range m.Resources {
|
addrs := map[string]*terraform.ResourceAddress{}
|
||||||
|
for name := range m.Resources {
|
||||||
names = append(names, name)
|
names = append(names, name)
|
||||||
|
var err error
|
||||||
|
addrs[name], err = terraform.ParseResourceAddressForInstanceDiff(modulePath, name)
|
||||||
|
if err != nil {
|
||||||
|
// should never happen; indicates invalid diff
|
||||||
|
panic("invalid resource address in diff")
|
||||||
}
|
}
|
||||||
sort.Strings(names)
|
}
|
||||||
|
sort.Slice(names, func(i, j int) bool {
|
||||||
|
return addrs[names[i]].Less(addrs[names[j]])
|
||||||
|
})
|
||||||
|
|
||||||
// Go through each sorted name and start building the output
|
// Go through each sorted name and start building the output
|
||||||
for _, name := range names {
|
for _, name := range names {
|
||||||
|
@ -78,25 +88,23 @@ func formatPlanModuleExpand(
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
dataSource := strings.HasPrefix(name, "data.")
|
addr := addrs[name]
|
||||||
|
addrStr := addr.String()
|
||||||
if moduleName != "" {
|
dataSource := addr.Mode == config.DataResourceMode
|
||||||
name = moduleName + "." + name
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine the color for the text (green for adding, yellow
|
// Determine the color for the text (green for adding, yellow
|
||||||
// for change, red for delete), and symbol, and output the
|
// for change, red for delete), and symbol, and output the
|
||||||
// resource header.
|
// resource header.
|
||||||
color := "yellow"
|
color := "yellow"
|
||||||
symbol := "~"
|
symbol := " ~"
|
||||||
oldValues := true
|
oldValues := true
|
||||||
switch rdiff.ChangeType() {
|
switch rdiff.ChangeType() {
|
||||||
case terraform.DiffDestroyCreate:
|
case terraform.DiffDestroyCreate:
|
||||||
color = "green"
|
color = "yellow"
|
||||||
symbol = "-/+"
|
symbol = "[red]-[reset]/[green]+[reset][yellow]"
|
||||||
case terraform.DiffCreate:
|
case terraform.DiffCreate:
|
||||||
color = "green"
|
color = "green"
|
||||||
symbol = "+"
|
symbol = " +"
|
||||||
oldValues = false
|
oldValues = false
|
||||||
|
|
||||||
// If we're "creating" a data resource then we'll present it
|
// If we're "creating" a data resource then we'll present it
|
||||||
|
@ -106,12 +114,12 @@ func formatPlanModuleExpand(
|
||||||
// to work with, so we need to cheat and exploit knowledge of the
|
// to work with, so we need to cheat and exploit knowledge of the
|
||||||
// naming scheme for data resources.
|
// naming scheme for data resources.
|
||||||
if dataSource {
|
if dataSource {
|
||||||
symbol = "<="
|
symbol = " <="
|
||||||
color = "cyan"
|
color = "cyan"
|
||||||
}
|
}
|
||||||
case terraform.DiffDestroy:
|
case terraform.DiffDestroy:
|
||||||
color = "red"
|
color = "red"
|
||||||
symbol = "-"
|
symbol = " -"
|
||||||
}
|
}
|
||||||
|
|
||||||
var extraAttr []string
|
var extraAttr []string
|
||||||
|
@ -125,10 +133,13 @@ func formatPlanModuleExpand(
|
||||||
if len(extraAttr) > 0 {
|
if len(extraAttr) > 0 {
|
||||||
extraStr = fmt.Sprintf(" (%s)", strings.Join(extraAttr, ", "))
|
extraStr = fmt.Sprintf(" (%s)", strings.Join(extraAttr, ", "))
|
||||||
}
|
}
|
||||||
|
if rdiff.ChangeType() == terraform.DiffDestroyCreate {
|
||||||
|
extraStr = extraStr + opts.Color.Color(" [red][bold](new resource required)")
|
||||||
|
}
|
||||||
|
|
||||||
buf.WriteString(opts.Color.Color(fmt.Sprintf(
|
buf.WriteString(opts.Color.Color(fmt.Sprintf(
|
||||||
"[%s]%s %s%s\n",
|
"[%s]%s %s%s\n",
|
||||||
color, symbol, name, extraStr)))
|
color, symbol, addrStr, extraStr)))
|
||||||
|
|
||||||
// Get all the attributes that are changing, and sort them. Also
|
// Get all the attributes that are changing, and sort them. Also
|
||||||
// determine the longest key so that we can align them all.
|
// determine the longest key so that we can align them all.
|
||||||
|
|
Loading…
Reference in New Issue