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"
"strings"
"sync"
"time"
"unicode"
"github.com/hashicorp/terraform/terraform"
@ -14,6 +15,8 @@ import (
"github.com/mitchellh/colorstring"
)
const periodicUiTimer = 10 * time.Second
type UiHook struct {
terraform.NilHook
@ -22,10 +25,17 @@ type UiHook struct {
l sync.Mutex
once sync.Once
resources map[string]uiResourceOp
resources map[string]uiResourceState
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
const (
@ -51,7 +61,10 @@ func (h *UiHook) PreApply(
}
h.l.Lock()
h.resources[id] = op
h.resources[id] = uiResourceState{
Op: op,
Start: time.Now().Round(time.Second),
}
h.l.Unlock()
var operation string
@ -113,9 +126,46 @@ func (h *UiHook) PreApply(
operation,
attrString)))
// Set a timer to show an operation is still happening
time.AfterFunc(periodicUiTimer, func() { h.stillApplying(id) })
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(
n *terraform.InstanceInfo,
s *terraform.InstanceState,
@ -123,12 +173,12 @@ func (h *UiHook) PostApply(
id := n.HumanId()
h.l.Lock()
op := h.resources[id]
state := h.resources[id]
delete(h.resources, id)
h.l.Unlock()
var msg string
switch op {
switch state.Op {
case uiResourceModify:
msg = "Modifications complete"
case uiResourceDestroy:
@ -205,7 +255,7 @@ func (h *UiHook) init() {
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
// underlying reader/writer that is in place.