command: show periodic messages about continued ops

This commit is contained in:
Mitchell Hashimoto 2016-04-13 10:54:11 -07:00
parent ab14b3ad00
commit 284bc92c04
1 changed files with 55 additions and 5 deletions

View File

@ -7,6 +7,7 @@ import (
"sort" "sort"
"strings" "strings"
"sync" "sync"
"time"
"unicode" "unicode"
"github.com/hashicorp/terraform/terraform" "github.com/hashicorp/terraform/terraform"
@ -14,6 +15,8 @@ import (
"github.com/mitchellh/colorstring" "github.com/mitchellh/colorstring"
) )
const periodicUiTimer = 10 * time.Second
type UiHook struct { type UiHook struct {
terraform.NilHook terraform.NilHook
@ -22,10 +25,17 @@ type UiHook struct {
l sync.Mutex l sync.Mutex
once sync.Once once sync.Once
resources map[string]uiResourceOp resources map[string]uiResourceState
ui cli.Ui ui cli.Ui
} }
// uiResourceState tracks the state of a single resource
type uiResourceState struct {
Op uiResourceOp
Start time.Time
}
// uiResourceOp is an enum for operations on a resource
type uiResourceOp byte type uiResourceOp byte
const ( const (
@ -51,7 +61,10 @@ func (h *UiHook) PreApply(
} }
h.l.Lock() h.l.Lock()
h.resources[id] = op h.resources[id] = uiResourceState{
Op: op,
Start: time.Now().Round(time.Second),
}
h.l.Unlock() h.l.Unlock()
var operation string var operation string
@ -113,9 +126,46 @@ func (h *UiHook) PreApply(
operation, operation,
attrString))) attrString)))
// Set a timer to show an operation is still happening
time.AfterFunc(periodicUiTimer, func() { h.stillApplying(id) })
return terraform.HookActionContinue, nil return terraform.HookActionContinue, nil
} }
func (h *UiHook) stillApplying(id string) {
// Grab the operation
h.l.Lock()
state, ok := h.resources[id]
h.l.Unlock()
// If the resource is out of the map it means we're done with it
if !ok {
return
}
var msg string
switch state.Op {
case uiResourceModify:
msg = "Still modifying..."
case uiResourceDestroy:
msg = "Still destroying..."
case uiResourceCreate:
msg = "Still creating..."
case uiResourceUnknown:
return
}
h.ui.Output(h.Colorize.Color(fmt.Sprintf(
"[reset][bold]%s: %s (%s elapsed)[reset_bold]",
id,
msg,
time.Now().Round(time.Second).Sub(state.Start),
)))
// Reschedule
time.AfterFunc(periodicUiTimer, func() { h.stillApplying(id) })
}
func (h *UiHook) PostApply( func (h *UiHook) PostApply(
n *terraform.InstanceInfo, n *terraform.InstanceInfo,
s *terraform.InstanceState, s *terraform.InstanceState,
@ -123,12 +173,12 @@ func (h *UiHook) PostApply(
id := n.HumanId() id := n.HumanId()
h.l.Lock() h.l.Lock()
op := h.resources[id] state := h.resources[id]
delete(h.resources, id) delete(h.resources, id)
h.l.Unlock() h.l.Unlock()
var msg string var msg string
switch op { switch state.Op {
case uiResourceModify: case uiResourceModify:
msg = "Modifications complete" msg = "Modifications complete"
case uiResourceDestroy: case uiResourceDestroy:
@ -205,7 +255,7 @@ func (h *UiHook) init() {
panic("colorize not given") panic("colorize not given")
} }
h.resources = make(map[string]uiResourceOp) h.resources = make(map[string]uiResourceState)
// Wrap the ui so that it is safe for concurrency regardless of the // Wrap the ui so that it is safe for concurrency regardless of the
// underlying reader/writer that is in place. // underlying reader/writer that is in place.