coalesce the backened interrupt code
Moves the nested select statements for backend operations into a single function. The only difference in this part was that apply called PersistState, which should be harmless regardless of the type of operation being run.
This commit is contained in:
parent
ecd9ef0f77
commit
ef8ed1e275
|
@ -5,6 +5,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
|
@ -273,6 +274,53 @@ func (b *Local) Operation(ctx context.Context, op *backend.Operation) (*backend.
|
|||
return runningOp, nil
|
||||
}
|
||||
|
||||
// opWait wats for the operation to complete, and a stop signal or a
|
||||
// cancelation signal.
|
||||
func (b *Local) opWait(
|
||||
doneCh <-chan struct{},
|
||||
stopCtx context.Context,
|
||||
cancelCtx context.Context,
|
||||
tfCtx *terraform.Context,
|
||||
opState state.State) (canceled bool) {
|
||||
// Wait for the operation to finish or for us to be interrupted so
|
||||
// we can handle it properly.
|
||||
select {
|
||||
case <-stopCtx.Done():
|
||||
if b.CLI != nil {
|
||||
b.CLI.Output("stopping operation...")
|
||||
}
|
||||
|
||||
// try to force a PersistState just in case the process is terminated
|
||||
// before we can complete.
|
||||
if err := opState.PersistState(); err != nil {
|
||||
// We can't error out from here, but warn the user if there was an error.
|
||||
// If this isn't transient, we will catch it again below, and
|
||||
// attempt to save the state another way.
|
||||
if b.CLI != nil {
|
||||
b.CLI.Error(fmt.Sprintf(earlyStateWriteErrorFmt, err))
|
||||
}
|
||||
}
|
||||
|
||||
// Stop execution
|
||||
go tfCtx.Stop()
|
||||
|
||||
select {
|
||||
case <-cancelCtx.Done():
|
||||
log.Println("[WARN] running operation canceled")
|
||||
// if the operation was canceled, we need to return immediately
|
||||
canceled = true
|
||||
case <-doneCh:
|
||||
}
|
||||
case <-cancelCtx.Done():
|
||||
// this should not be called without first attempting to stop the
|
||||
// operation
|
||||
log.Println("[ERROR] running operation canceled without Stop")
|
||||
canceled = true
|
||||
case <-doneCh:
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Colorize returns the Colorize structure that can be used for colorizing
|
||||
// output. This is gauranteed to always return a non-nil value and so is useful
|
||||
// as a helper to wrap any potentially colored strings.
|
||||
|
|
|
@ -154,42 +154,8 @@ func (b *Local) opApply(
|
|||
applyState = tfCtx.State()
|
||||
}()
|
||||
|
||||
// Wait for the apply to finish or for us to be interrupted so
|
||||
// we can handle it properly.
|
||||
err = nil
|
||||
select {
|
||||
case <-stopCtx.Done():
|
||||
if b.CLI != nil {
|
||||
b.CLI.Output("stopping apply operation...")
|
||||
}
|
||||
|
||||
// try to force a PersistState just in case the process is terminated
|
||||
// before we can complete.
|
||||
if err := opState.PersistState(); err != nil {
|
||||
// We can't error out from here, but warn the user if there was an error.
|
||||
// If this isn't transient, we will catch it again below, and
|
||||
// attempt to save the state another way.
|
||||
if b.CLI != nil {
|
||||
b.CLI.Error(fmt.Sprintf(earlyStateWriteErrorFmt, err))
|
||||
}
|
||||
}
|
||||
|
||||
// Stop execution
|
||||
go tfCtx.Stop()
|
||||
|
||||
select {
|
||||
case <-cancelCtx.Done():
|
||||
log.Println("[WARN] running operation canceled")
|
||||
// if the operation was canceled, we need to return immediately
|
||||
return
|
||||
case <-doneCh:
|
||||
}
|
||||
case <-cancelCtx.Done():
|
||||
// this should not be called without first attempting to stop the
|
||||
// operation
|
||||
log.Println("[ERROR] running operation canceled without Stop")
|
||||
if b.opWait(doneCh, stopCtx, cancelCtx, tfCtx, opState) {
|
||||
return
|
||||
case <-doneCh:
|
||||
}
|
||||
|
||||
// Store the final state
|
||||
|
|
|
@ -112,28 +112,8 @@ func (b *Local) opPlan(
|
|||
plan, planErr = tfCtx.Plan()
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-stopCtx.Done():
|
||||
if b.CLI != nil {
|
||||
b.CLI.Output("stopping plan operation...")
|
||||
}
|
||||
|
||||
// Stop execution
|
||||
go tfCtx.Stop()
|
||||
|
||||
select {
|
||||
case <-cancelCtx.Done():
|
||||
log.Println("[WARN] running operation canceled")
|
||||
// if the operation was canceled, we need to return immediately
|
||||
return
|
||||
case <-doneCh:
|
||||
}
|
||||
case <-cancelCtx.Done():
|
||||
// this should not be called without first attempting to stop the
|
||||
// operation
|
||||
log.Println("[ERROR] running operation canceled without Stop")
|
||||
if b.opWait(doneCh, stopCtx, cancelCtx, tfCtx, opState) {
|
||||
return
|
||||
case <-doneCh:
|
||||
}
|
||||
|
||||
if planErr != nil {
|
||||
|
|
|
@ -91,28 +91,8 @@ func (b *Local) opRefresh(
|
|||
log.Printf("[INFO] backend/local: refresh calling Refresh")
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-stopCtx.Done():
|
||||
if b.CLI != nil {
|
||||
b.CLI.Output("stopping refresh operation...")
|
||||
}
|
||||
|
||||
// Stop execution
|
||||
go tfCtx.Stop()
|
||||
|
||||
select {
|
||||
case <-cancelCtx.Done():
|
||||
log.Println("[WARN] running operation canceled")
|
||||
// if the operation was canceled, we need to return immediately
|
||||
return
|
||||
case <-doneCh:
|
||||
}
|
||||
case <-cancelCtx.Done():
|
||||
// this should not be called without first attempting to stop the
|
||||
// operation
|
||||
log.Println("[ERROR] running operation canceled without Stop")
|
||||
if b.opWait(doneCh, stopCtx, cancelCtx, tfCtx, opState) {
|
||||
return
|
||||
case <-doneCh:
|
||||
}
|
||||
|
||||
// write the resulting state to the running op
|
||||
|
|
Loading…
Reference in New Issue