watch for cancellation in plan and refresh

Cancellation in the local backend was only implemented for apply.
This commit is contained in:
James Bardin 2017-12-02 17:31:28 -05:00
parent 90e986348a
commit 85295e5c23
3 changed files with 55 additions and 18 deletions

View File

@ -151,14 +151,6 @@ func (b *Local) opApply(
_, applyErr = tfCtx.Apply() _, applyErr = tfCtx.Apply()
// we always want the state, even if apply failed // we always want the state, even if apply failed
applyState = tfCtx.State() applyState = tfCtx.State()
/*
// Record any shadow errors for later
if err := ctx.ShadowError(); err != nil {
shadowErr = multierror.Append(shadowErr, multierror.Prefix(
err, "apply operation:"))
}
*/
}() }()
// Wait for the apply to finish or for us to be interrupted so // Wait for the apply to finish or for us to be interrupted so

View File

@ -101,14 +101,34 @@ func (b *Local) opPlan(
} }
} }
// Perform the plan // Perform the plan in a goroutine so we can be interrupted
log.Printf("[INFO] backend/local: plan calling Plan") var plan *terraform.Plan
plan, err := tfCtx.Plan() var planErr error
if err != nil { doneCh := make(chan struct{})
runningOp.Err = errwrap.Wrapf("Error running plan: {{err}}", err) go func() {
return defer close(doneCh)
log.Printf("[INFO] backend/local: plan calling Plan")
plan, planErr = tfCtx.Plan()
}()
select {
case <-ctx.Done():
if b.CLI != nil {
b.CLI.Output("stopping plan operation...")
}
// Stop execution
go tfCtx.Stop()
// Wait for completion still
<-doneCh
case <-doneCh:
} }
if planErr != nil {
runningOp.Err = errwrap.Wrapf("Error running plan: {{err}}", planErr)
return
}
// Record state // Record state
runningOp.PlanEmpty = plan.Diff.Empty() runningOp.PlanEmpty = plan.Diff.Empty()

View File

@ -3,6 +3,7 @@ package local
import ( import (
"context" "context"
"fmt" "fmt"
"log"
"os" "os"
"strings" "strings"
@ -12,6 +13,7 @@ import (
"github.com/hashicorp/terraform/command/clistate" "github.com/hashicorp/terraform/command/clistate"
"github.com/hashicorp/terraform/config/module" "github.com/hashicorp/terraform/config/module"
"github.com/hashicorp/terraform/state" "github.com/hashicorp/terraform/state"
"github.com/hashicorp/terraform/terraform"
) )
func (b *Local) opRefresh( func (b *Local) opRefresh(
@ -78,11 +80,34 @@ func (b *Local) opRefresh(
} }
} }
// Perform operation and write the resulting state to the running op // Perform the refresh in a goroutine so we can be interrupted
newState, err := tfCtx.Refresh() var newState *terraform.State
var refreshErr error
doneCh := make(chan struct{})
go func() {
defer close(doneCh)
newState, err = tfCtx.Refresh()
log.Printf("[INFO] backend/local: plan calling Plan")
}()
select {
case <-ctx.Done():
if b.CLI != nil {
b.CLI.Output("stopping refresh operation...")
}
// Stop execution
go tfCtx.Stop()
// Wait for completion still
<-doneCh
case <-doneCh:
}
// write the resulting state to the running op
runningOp.State = newState runningOp.State = newState
if err != nil { if refreshErr != nil {
runningOp.Err = errwrap.Wrapf("Error refreshing state: {{err}}", err) runningOp.Err = errwrap.Wrapf("Error refreshing state: {{err}}", refreshErr)
return return
} }