From 0dc6d97a3790885f021f5e6f167d8912cc33519d Mon Sep 17 00:00:00 2001 From: Martin Atkins Date: Wed, 21 Jun 2017 18:38:33 -0700 Subject: [PATCH] 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. --- command/format/plan.go | 47 +++++++++++++++++++++++-------------- command/format/plan_test.go | 4 ++-- 2 files changed, 31 insertions(+), 20 deletions(-) diff --git a/command/format/plan.go b/command/format/plan.go index b270e2d3c..6bc699e39 100644 --- a/command/format/plan.go +++ b/command/format/plan.go @@ -6,6 +6,7 @@ import ( "sort" "strings" + "github.com/hashicorp/terraform/config" "github.com/hashicorp/terraform/terraform" "github.com/mitchellh/colorstring" ) @@ -58,18 +59,27 @@ func formatPlanModuleExpand( return } - var moduleName string + var modulePath []string 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 // easier to scan through, so get all the resource names and sort them. 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) + 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 for _, name := range names { @@ -78,25 +88,23 @@ func formatPlanModuleExpand( continue } - dataSource := strings.HasPrefix(name, "data.") - - if moduleName != "" { - name = moduleName + "." + name - } + addr := addrs[name] + addrStr := addr.String() + dataSource := addr.Mode == config.DataResourceMode // Determine the color for the text (green for adding, yellow // for change, red for delete), and symbol, and output the // resource header. color := "yellow" - symbol := "~" + symbol := " ~" oldValues := true switch rdiff.ChangeType() { case terraform.DiffDestroyCreate: - color = "green" - symbol = "-/+" + color = "yellow" + symbol = "[red]-[reset]/[green]+[reset][yellow]" case terraform.DiffCreate: color = "green" - symbol = "+" + symbol = " +" oldValues = false // 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 // naming scheme for data resources. if dataSource { - symbol = "<=" + symbol = " <=" color = "cyan" } case terraform.DiffDestroy: color = "red" - symbol = "-" + symbol = " -" } var extraAttr []string @@ -125,10 +133,13 @@ func formatPlanModuleExpand( if len(extraAttr) > 0 { 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( "[%s]%s %s%s\n", - color, symbol, name, extraStr))) + color, symbol, addrStr, extraStr))) // Get all the attributes that are changing, and sort them. Also // determine the longest key so that we can align them all. @@ -175,7 +186,7 @@ func formatPlanModuleExpand( u = attrDiff.Old } buf.WriteString(fmt.Sprintf( - " %s:%s %#v => %#v%s\n", + " %s:%s %#v => %#v%s\n", attrK, strings.Repeat(" ", keyLen-len(attrK)), u, @@ -183,7 +194,7 @@ func formatPlanModuleExpand( updateMsg)) } else { buf.WriteString(fmt.Sprintf( - " %s:%s %#v%s\n", + " %s:%s %#v%s\n", attrK, strings.Repeat(" ", keyLen-len(attrK)), v, diff --git a/command/format/plan_test.go b/command/format/plan_test.go index 41321653a..82390d3d9 100644 --- a/command/format/plan_test.go +++ b/command/format/plan_test.go @@ -121,7 +121,7 @@ func TestPlan_rootDataSource(t *testing.T) { expected := strings.TrimSpace(` <= data.type.name - A: "B" + A: "B" `) if actual != expected { t.Fatalf("expected:\n\n%s\n\ngot:\n\n%s", expected, actual) @@ -162,7 +162,7 @@ func TestPlan_nestedDataSource(t *testing.T) { expected := strings.TrimSpace(` <= module.nested.data.type.name - A: "B" + A: "B" `) if actual != expected { t.Fatalf("expected:\n\n%s\n\ngot:\n\n%s", expected, actual)