move backend operation cancellation into meta
Create a single command method for running and operation with cancellation.
This commit is contained in:
parent
7cba68326a
commit
67a6152091
|
@ -2,12 +2,10 @@ package command
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/tfdiags"
|
"github.com/hashicorp/terraform/tfdiags"
|
||||||
|
|
||||||
|
@ -159,47 +157,9 @@ func (c *ApplyCommand) Run(args []string) int {
|
||||||
opReq.AutoApprove = autoApprove
|
opReq.AutoApprove = autoApprove
|
||||||
opReq.DestroyForce = destroyForce
|
opReq.DestroyForce = destroyForce
|
||||||
|
|
||||||
// Perform the operation
|
op, err := c.RunOperation(b, opReq)
|
||||||
op, err := b.Operation(context.Background(), opReq)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Ui.Error(fmt.Sprintf("Error starting operation: %s", err))
|
diags = diags.Append(err)
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for the operation to complete or an interrupt to occur
|
|
||||||
select {
|
|
||||||
case <-c.ShutdownCh:
|
|
||||||
// gracefully stop the operation
|
|
||||||
op.Stop()
|
|
||||||
|
|
||||||
// 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. Note that data\n" +
|
|
||||||
"loss may have occurred.")
|
|
||||||
|
|
||||||
// cancel the operation completely
|
|
||||||
op.Cancel()
|
|
||||||
|
|
||||||
// the operation should return asap
|
|
||||||
// but timeout just in case
|
|
||||||
select {
|
|
||||||
case <-op.Done():
|
|
||||||
case <-time.After(5 * time.Second):
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1
|
|
||||||
|
|
||||||
case <-op.Done():
|
|
||||||
}
|
|
||||||
case <-op.Done():
|
|
||||||
if err := op.Err; err != nil {
|
|
||||||
diags = diags.Append(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
c.showDiagnostics(diags)
|
c.showDiagnostics(diags)
|
||||||
|
|
|
@ -3,6 +3,7 @@ package command
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -259,6 +260,54 @@ func (m *Meta) StdinPiped() bool {
|
||||||
return fi.Mode()&os.ModeNamedPipe != 0
|
return fi.Mode()&os.ModeNamedPipe != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Meta) RunOperation(b backend.Enhanced, opReq *backend.Operation) (*backend.RunningOperation, error) {
|
||||||
|
op, err := b.Operation(context.Background(), opReq)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error starting operation: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for the operation to complete or an interrupt to occur
|
||||||
|
select {
|
||||||
|
case <-m.ShutdownCh:
|
||||||
|
// gracefully stop the operation
|
||||||
|
op.Stop()
|
||||||
|
|
||||||
|
// Notify the user
|
||||||
|
m.Ui.Output(outputInterrupt)
|
||||||
|
|
||||||
|
// Still get the result, since there is still one
|
||||||
|
select {
|
||||||
|
case <-m.ShutdownCh:
|
||||||
|
m.Ui.Error(
|
||||||
|
"Two interrupts received. Exiting immediately. Note that data\n" +
|
||||||
|
"loss may have occurred.")
|
||||||
|
|
||||||
|
// cancel the operation completely
|
||||||
|
op.Cancel()
|
||||||
|
|
||||||
|
// the operation should return asap
|
||||||
|
// but timeout just in case
|
||||||
|
select {
|
||||||
|
case <-op.Done():
|
||||||
|
case <-time.After(5 * time.Second):
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, errors.New("operation canceled")
|
||||||
|
|
||||||
|
case <-op.Done():
|
||||||
|
// operation completed after Stop
|
||||||
|
}
|
||||||
|
case <-op.Done():
|
||||||
|
// operation completed normally
|
||||||
|
}
|
||||||
|
|
||||||
|
if op.Err != nil {
|
||||||
|
return op, op.Err
|
||||||
|
}
|
||||||
|
|
||||||
|
return op, nil
|
||||||
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ProviderSkipVerifyEnvVar = "TF_SKIP_PROVIDER_VERIFY"
|
ProviderSkipVerifyEnvVar = "TF_SKIP_PROVIDER_VERIFY"
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
package command
|
package command
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
"github.com/hashicorp/terraform/config"
|
"github.com/hashicorp/terraform/config"
|
||||||
|
@ -108,43 +106,9 @@ func (c *PlanCommand) Run(args []string) int {
|
||||||
opReq.Type = backend.OperationTypePlan
|
opReq.Type = backend.OperationTypePlan
|
||||||
|
|
||||||
// Perform the operation
|
// Perform the operation
|
||||||
op, err := b.Operation(context.Background(), opReq)
|
op, err := c.RunOperation(b, opReq)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Ui.Error(fmt.Sprintf("Error starting operation: %s", err))
|
diags = diags.Append(err)
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
select {
|
|
||||||
case <-c.ShutdownCh:
|
|
||||||
// Cancel our context so we can start gracefully exiting
|
|
||||||
op.Stop()
|
|
||||||
|
|
||||||
// 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")
|
|
||||||
|
|
||||||
// cancel the operation completely
|
|
||||||
op.Cancel()
|
|
||||||
|
|
||||||
// the operation should return asap
|
|
||||||
// but timeout just in case
|
|
||||||
select {
|
|
||||||
case <-op.Done():
|
|
||||||
case <-time.After(5 * time.Second):
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1
|
|
||||||
case <-op.Done():
|
|
||||||
}
|
|
||||||
case <-op.Done():
|
|
||||||
if err := op.Err; err != nil {
|
|
||||||
diags = diags.Append(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
c.showDiagnostics(diags)
|
c.showDiagnostics(diags)
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
package command
|
package command
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
"github.com/hashicorp/terraform/config"
|
"github.com/hashicorp/terraform/config"
|
||||||
|
@ -76,47 +74,9 @@ func (c *RefreshCommand) Run(args []string) int {
|
||||||
opReq.Type = backend.OperationTypeRefresh
|
opReq.Type = backend.OperationTypeRefresh
|
||||||
opReq.Module = mod
|
opReq.Module = mod
|
||||||
|
|
||||||
// Perform the operation
|
op, err := c.RunOperation(b, opReq)
|
||||||
op, err := b.Operation(context.Background(), opReq)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Ui.Error(fmt.Sprintf("Error starting operation: %s", err))
|
diags = diags.Append(err)
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for the operation to complete or an interrupt to occur
|
|
||||||
select {
|
|
||||||
case <-c.ShutdownCh:
|
|
||||||
// gracefully stop the operation
|
|
||||||
op.Stop()
|
|
||||||
|
|
||||||
// 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. Note that data\n" +
|
|
||||||
"loss may have occurred.")
|
|
||||||
|
|
||||||
// cancel the operation completely
|
|
||||||
op.Cancel()
|
|
||||||
|
|
||||||
// the operation should return asap
|
|
||||||
// but timeout just in case
|
|
||||||
select {
|
|
||||||
case <-op.Done():
|
|
||||||
case <-time.After(5 * time.Second):
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1
|
|
||||||
|
|
||||||
case <-op.Done():
|
|
||||||
}
|
|
||||||
case <-op.Done():
|
|
||||||
if err := op.Err; err != nil {
|
|
||||||
diags = diags.Append(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
c.showDiagnostics(diags)
|
c.showDiagnostics(diags)
|
||||||
|
|
Loading…
Reference in New Issue