make plans cancellable

There was no cancellation context for a plan, so it would always have to
run to completion as SIGINT was being swallowed.

Move the shutdown channel to the command Meta since it's used in
multiple commands.
This commit is contained in:
James Bardin 2017-12-01 11:03:41 -05:00
parent 8891694762
commit 3aaa1e9d04
5 changed files with 28 additions and 14 deletions

View File

@ -24,9 +24,6 @@ type ApplyCommand struct {
// If true, then this apply command will become the "destroy"
// command. It is just like apply but only processes a destroy.
Destroy bool
// When this channel is closed, the apply will be cancelled.
ShutdownCh <-chan struct{}
}
func (c *ApplyCommand) Run(args []string) int {

View File

@ -837,9 +837,8 @@ func TestApply_shutdown(t *testing.T) {
Meta: Meta{
testingOverrides: metaOverridesForProvider(p),
Ui: ui,
ShutdownCh: shutdownCh,
},
ShutdownCh: shutdownCh,
}
p.DiffFn = func(

View File

@ -17,9 +17,6 @@ import (
// configuration and actually builds or changes infrastructure.
type ConsoleCommand struct {
Meta
// When this channel is closed, the apply will be cancelled.
ShutdownCh <-chan struct{}
}
func (c *ConsoleCommand) Run(args []string) int {

View File

@ -76,6 +76,9 @@ type Meta struct {
// is not suitable, e.g. because of a read-only filesystem.
OverrideDataDir string
// When this channel is closed, the command will be cancelled.
ShutdownCh <-chan struct{}
//----------------------------------------------------------
// Protected: commands can set these
//----------------------------------------------------------

View File

@ -104,17 +104,35 @@ func (c *PlanCommand) Run(args []string) int {
opReq.Type = backend.OperationTypePlan
// Perform the operation
op, err := b.Operation(context.Background(), opReq)
ctx, ctxCancel := context.WithCancel(context.Background())
defer ctxCancel()
op, err := b.Operation(ctx, opReq)
if err != nil {
c.Ui.Error(fmt.Sprintf("Error starting operation: %s", err))
return 1
}
// Wait for the operation to complete
<-op.Done()
if err := op.Err; err != nil {
c.showDiagnostics(err)
return 1
select {
case <-c.ShutdownCh:
// Cancel our context so we can start gracefully exiting
ctxCancel()
// Notify the user
c.Ui.Output(outputInterrupt)
// Still get the result, since there is still one
select {
case <-c.ShutdownCh:
c.Ui.Error(
"Two interrupts received. Exiting immediately")
return 1
case <-op.Done():
}
case <-op.Done():
if err := op.Err; err != nil {
c.showDiagnostics(err)
return 1
}
}
/*