diff --git a/tfexec/cmd_default.go b/tfexec/cmd_default.go index fca9def9..adb69bdb 100644 --- a/tfexec/cmd_default.go +++ b/tfexec/cmd_default.go @@ -10,6 +10,28 @@ import ( "sync" ) +// cmdErr is a custom error type to be returned when a cmd exits with a context +// error such as context.Canceled or context.DeadlineExceeded. +// The type is specifically designed to respond true to errors.Is for these two +// errors. +// See https://github.com/golang/go/issues/21880 for why this is necessary. +type cmdErr struct { + err error + ctxErr error +} + +func (e *cmdErr) Is(target error) bool { + switch target { + case context.DeadlineExceeded, context.Canceled: + return e.ctxErr == context.DeadlineExceeded || e.ctxErr == context.Cancelled + } + return false +} + +func (e *cmdErr) Error() string { + return e.err.Error() +} + func (tf *Terraform) runTerraformCmd(ctx context.Context, cmd *exec.Cmd) error { var errBuf strings.Builder @@ -40,8 +62,11 @@ func (tf *Terraform) runTerraformCmd(ctx context.Context, cmd *exec.Cmd) error { } err = cmd.Start() - if err == nil && ctx.Err() != nil { - err = ctx.Err() + if ctx.Err() != nil { + return cmdErr{ + err: err, + ctxErr: ctx.Err(), + } } if err != nil { return err