command: trigger still applying cancellations from a channel

This commit is contained in:
Mitchell Hashimoto 2017-03-02 11:15:02 -08:00
parent 17c9a403f2
commit 866de2776e
No known key found for this signature in database
GPG Key ID: 744E147AA52F5B0A
1 changed files with 59 additions and 49 deletions

View File

@ -33,8 +33,12 @@ type UiHook struct {
// uiResourceState tracks the state of a single resource
type uiResourceState struct {
Op uiResourceOp
Start time.Time
Name string
ResourceId string
Op uiResourceOp
Start time.Time
DoneCh chan struct{} // To be used for cancellation
}
// uiResourceOp is an enum for operations on a resource
@ -63,13 +67,6 @@ func (h *UiHook) PreApply(
op = uiResourceCreate
}
h.l.Lock()
h.resources[id] = uiResourceState{
Op: op,
Start: time.Now().Round(time.Second),
}
h.l.Unlock()
var operation string
switch op {
case uiResourceModify:
@ -131,8 +128,9 @@ func (h *UiHook) PreApply(
attrString = "\n " + attrString
}
var stateIdSuffix string
var stateId, stateIdSuffix string
if s != nil && s.ID != "" {
stateId = s.ID
stateIdSuffix = fmt.Sprintf(" (ID: %s)", truncateId(s.ID, maxIdLen))
}
@ -143,51 +141,59 @@ func (h *UiHook) PreApply(
stateIdSuffix,
attrString)))
// Set a timer to show an operation is still happening
time.AfterFunc(periodicUiTimer, func() { h.stillApplying(id, s) })
uiState := uiResourceState{
Name: id,
ResourceId: stateId,
Op: op,
Start: time.Now().Round(time.Second),
DoneCh: make(chan struct{}),
}
h.l.Lock()
h.resources[id] = uiState
h.l.Unlock()
// Start goroutine that shows progress
go h.stillApplying(uiState)
return terraform.HookActionContinue, nil
}
func (h *UiHook) stillApplying(id string, s *terraform.InstanceState) {
// Grab the operation. We defer the lock here to avoid the "still..."
// message showing up after a completion message.
h.l.Lock()
defer h.l.Unlock()
state, ok := h.resources[id]
func (h *UiHook) stillApplying(state uiResourceState) {
for {
select {
case <-state.DoneCh:
return
// If the resource is out of the map it means we're done with it
if !ok {
return
case <-time.After(periodicUiTimer):
// Timer up, show status
}
var msg string
switch state.Op {
case uiResourceModify:
msg = "Still modifying..."
case uiResourceDestroy:
msg = "Still destroying..."
case uiResourceCreate:
msg = "Still creating..."
case uiResourceUnknown:
return
}
idSuffix := ""
if v := state.ResourceId; v != "" {
idSuffix = fmt.Sprintf("ID: %s, ", truncateId(v, maxIdLen))
}
h.ui.Output(h.Colorize.Color(fmt.Sprintf(
"[reset][bold]%s: %s (%s%s elapsed)[reset]",
state.Name,
msg,
idSuffix,
time.Now().Round(time.Second).Sub(state.Start),
)))
}
var msg string
switch state.Op {
case uiResourceModify:
msg = "Still modifying..."
case uiResourceDestroy:
msg = "Still destroying..."
case uiResourceCreate:
msg = "Still creating..."
case uiResourceUnknown:
return
}
var stateIdSuffix string
if s != nil && s.ID != "" {
stateIdSuffix = fmt.Sprintf("ID: %s, ", truncateId(s.ID, maxIdLen))
}
h.ui.Output(h.Colorize.Color(fmt.Sprintf(
"[reset][bold]%s: %s (%s%s elapsed)[reset]",
id,
msg,
stateIdSuffix,
time.Now().Round(time.Second).Sub(state.Start),
)))
// Reschedule
time.AfterFunc(periodicUiTimer, func() { h.stillApplying(id, s) })
}
func (h *UiHook) PostApply(
@ -200,6 +206,10 @@ func (h *UiHook) PostApply(
h.l.Lock()
state := h.resources[id]
if state.DoneCh != nil {
close(state.DoneCh)
}
delete(h.resources, id)
h.l.Unlock()