From c615afc0976121ccef6c8967b68df420a3497b3d Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sat, 12 Jul 2014 17:03:55 -0700 Subject: [PATCH] command/apply: improved output, still not done --- command/apply.go | 3 ++ command/format_plan.go | 2 +- command/hook_ui.go | 66 ++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 67 insertions(+), 4 deletions(-) diff --git a/command/apply.go b/command/apply.go index 636a8daa7..0b7d36243 100644 --- a/command/apply.go +++ b/command/apply.go @@ -71,6 +71,7 @@ func (c *ApplyCommand) Run(args []string) int { return 1 } + // Start the apply in a goroutine so that we can be interrupted. var state *terraform.State var applyErr error doneCh := make(chan struct{}) @@ -79,6 +80,8 @@ func (c *ApplyCommand) Run(args []string) int { state, applyErr = ctx.Apply() }() + // Wait for the apply to finish or for us to be interrupted so + // we can handle it properly. err = nil select { case <-c.ShutdownCh: diff --git a/command/format_plan.go b/command/format_plan.go index 9c51ef01f..6b7e69485 100644 --- a/command/format_plan.go +++ b/command/format_plan.go @@ -81,7 +81,7 @@ func FormatPlan(p *terraform.Plan, c *colorstring.Colorize) string { } buf.WriteString(fmt.Sprintf( - " %s:%s %#v => %#v%s\n", + " %s:%s %#v => %#v%s\n", attrK, strings.Repeat(" ", keyLen-len(attrK)), attrDiff.Old, diff --git a/command/hook_ui.go b/command/hook_ui.go index e873f8a12..434fae020 100644 --- a/command/hook_ui.go +++ b/command/hook_ui.go @@ -1,17 +1,22 @@ package command import ( + "bytes" "fmt" + "sort" + "strings" "sync" "github.com/hashicorp/terraform/terraform" "github.com/mitchellh/cli" + "github.com/mitchellh/colorstring" ) type UiHook struct { terraform.NilHook - Ui cli.Ui + Colorize *colorstring.Colorize + Ui cli.Ui once sync.Once ui cli.Ui @@ -23,7 +28,55 @@ func (h *UiHook) PreApply( d *terraform.ResourceDiff) (terraform.HookAction, error) { h.once.Do(h.init) - h.ui.Output(fmt.Sprintf("%s: Applying...", id)) + operation := "Modifying..." + if d.Destroy { + operation = "Destroying..." + } else if s.ID == "" { + operation = "Creating..." + } + + attrBuf := new(bytes.Buffer) + + // Get all the attributes that are changing, and sort them. Also + // determine the longest key so that we can align them all. + keyLen := 0 + keys := make([]string, 0, len(d.Attributes)) + for key, _ := range d.Attributes { + // Skip the ID since we do that specially + if key == "id" { + continue + } + + keys = append(keys, key) + if len(key) > keyLen { + keyLen = len(key) + } + } + sort.Strings(keys) + + // Go through and output each attribute + for _, attrK := range keys { + attrDiff := d.Attributes[attrK] + + v := attrDiff.New + if attrDiff.NewComputed { + v = "" + } + + attrBuf.WriteString(fmt.Sprintf( + " %s:%s %#v => %#v\n", + attrK, + strings.Repeat(" ", keyLen-len(attrK)), + attrDiff.Old, + v)) + } + + h.ui.Output(h.Colorize.Color(fmt.Sprintf( + "[bold]%s: %s[reset_bold]\n %s", + id, + operation, + strings.TrimSpace(attrBuf.String())))) + return terraform.HookActionContinue, nil } @@ -36,11 +89,18 @@ func (h *UiHook) PreRefresh( id string, s *terraform.ResourceState) (terraform.HookAction, error) { h.once.Do(h.init) - h.ui.Output(fmt.Sprintf("%s: Refreshing state (ID: %s)", id, s.ID)) + //h.ui.Output(fmt.Sprintf("%s: Refreshing state (ID: %s)", id, s.ID)) return terraform.HookActionContinue, nil } func (h *UiHook) init() { + if h.Colorize == nil { + h.Colorize = &colorstring.Colorize{ + Colors: colorstring.DefaultColors, + Reset: true, + } + } + // Wrap the ui so that it is safe for concurrency regardless of the // underlying reader/writer that is in place. h.ui = &cli.ConcurrentUi{Ui: h.Ui}