Convert ExitStatus
to use fn to get details
Instead of requiring callers to read the struct fields to check for an error, provide the exit results via a function instead which is more natural. Signed-off-by: Brian Goff <cpuguy83@gmail.com>
This commit is contained in:
parent
026896ac4c
commit
6ab99edb71
@ -218,8 +218,9 @@ func (w *worker) runContainer(ctx context.Context, id string) error {
|
||||
return err
|
||||
}
|
||||
status := <-statusC
|
||||
if status.Err != nil {
|
||||
if status.Err == context.DeadlineExceeded || status.Err == context.Canceled {
|
||||
_, _, err = status.Result()
|
||||
if err != nil {
|
||||
if err == context.DeadlineExceeded || err == context.Canceled {
|
||||
return nil
|
||||
}
|
||||
w.failures++
|
||||
|
@ -60,11 +60,12 @@ var taskAttachCommand = cli.Command{
|
||||
}
|
||||
|
||||
ec := <-statusC
|
||||
if ec.Err != nil {
|
||||
code, _, err := ec.Result()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if ec.Code != 0 {
|
||||
return cli.NewExitError("", int(ec.Code))
|
||||
if code != 0 {
|
||||
return cli.NewExitError("", int(code))
|
||||
}
|
||||
return nil
|
||||
},
|
||||
|
@ -95,11 +95,12 @@ var taskExecCommand = cli.Command{
|
||||
defer stopCatch(sigc)
|
||||
}
|
||||
status := <-statusC
|
||||
if status.Err != nil {
|
||||
return status.Err
|
||||
code, _, err := status.Result()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if status.Code != 0 {
|
||||
return cli.NewExitError("", int(status.Code))
|
||||
if code != 0 {
|
||||
return cli.NewExitError("", int(code))
|
||||
}
|
||||
return nil
|
||||
},
|
||||
|
@ -155,15 +155,16 @@ var runCommand = cli.Command{
|
||||
}
|
||||
|
||||
status := <-statusC
|
||||
if status.Err != nil {
|
||||
return status.Err
|
||||
code, _, err := status.Result()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := task.Delete(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if status.Code != 0 {
|
||||
return cli.NewExitError("", int(status.Code))
|
||||
if code != 0 {
|
||||
return cli.NewExitError("", int(code))
|
||||
}
|
||||
return nil
|
||||
},
|
||||
|
@ -73,14 +73,15 @@ var taskStartCommand = cli.Command{
|
||||
}
|
||||
|
||||
status := <-statusC
|
||||
if status.Err != nil {
|
||||
code, _, err := status.Result()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := task.Delete(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if status.Code != 0 {
|
||||
return cli.NewExitError("", int(status.Code))
|
||||
if code != 0 {
|
||||
return cli.NewExitError("", int(code))
|
||||
}
|
||||
return nil
|
||||
},
|
||||
|
@ -232,7 +232,8 @@ func TestDaemonRestart(t *testing.T) {
|
||||
}
|
||||
|
||||
status := <-statusC
|
||||
if status.Err == nil {
|
||||
_, _, err = status.Result()
|
||||
if err == nil {
|
||||
t.Errorf(`first task.Wait() should have failed with "transport is closing"`)
|
||||
}
|
||||
|
||||
|
@ -139,12 +139,13 @@ func TestContainerStart(t *testing.T) {
|
||||
return
|
||||
}
|
||||
status := <-statusC
|
||||
if status.Err != nil {
|
||||
code, _, err := status.Result()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
if status.Code != 7 {
|
||||
t.Errorf("expected status 7 from wait but received %d", status.Code)
|
||||
if code != 7 {
|
||||
t.Errorf("expected status 7 from wait but received %d", code)
|
||||
}
|
||||
|
||||
deleteStatus, err := task.Delete(ctx)
|
||||
@ -214,8 +215,9 @@ func TestContainerOutput(t *testing.T) {
|
||||
}
|
||||
|
||||
status := <-statusC
|
||||
if status.Code != 0 {
|
||||
t.Errorf("expected status 0 but received %d", status)
|
||||
code, _, _ := status.Result()
|
||||
if code != 0 {
|
||||
t.Errorf("expected status 0 but received %d", code)
|
||||
}
|
||||
if _, err := task.Delete(ctx); err != nil {
|
||||
t.Error(err)
|
||||
@ -306,13 +308,14 @@ func TestContainerExec(t *testing.T) {
|
||||
|
||||
// wait for the exec to return
|
||||
status := <-processStatusC
|
||||
if status.Err != nil {
|
||||
code, _, err := status.Result()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
if status.Code != 6 {
|
||||
t.Errorf("expected exec exit code 6 but received %d", status.Code)
|
||||
if code != 6 {
|
||||
t.Errorf("expected exec exit code 6 but received %d", code)
|
||||
}
|
||||
deleteStatus, err := process.Delete(ctx)
|
||||
if err != nil {
|
||||
@ -610,7 +613,8 @@ func TestContainerAttach(t *testing.T) {
|
||||
}
|
||||
|
||||
status := <-statusC
|
||||
if status.Err != nil {
|
||||
_, _, err = status.Result()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
@ -960,12 +964,13 @@ func TestUserNamespaces(t *testing.T) {
|
||||
return
|
||||
}
|
||||
status := <-statusC
|
||||
if status.Err != nil {
|
||||
code, _, err := status.Result()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
if status.Code != 7 {
|
||||
t.Errorf("expected status 7 from wait but received %d", status.Code)
|
||||
if code != 7 {
|
||||
t.Errorf("expected status 7 from wait but received %d", code)
|
||||
}
|
||||
deleteStatus, err := task.Delete(ctx)
|
||||
if err != nil {
|
||||
@ -1043,12 +1048,13 @@ func TestWaitStoppedTask(t *testing.T) {
|
||||
return
|
||||
}
|
||||
status := <-statusC
|
||||
if status.Err != nil {
|
||||
t.Error(status.Err)
|
||||
code, _, err := status.Result()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
if status.Code != 7 {
|
||||
t.Errorf("exit status from stopped task should be 7 but received %d", status.Code)
|
||||
if code != 7 {
|
||||
t.Errorf("exit status from stopped task should be 7 but received %d", code)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1137,12 +1143,13 @@ func TestWaitStoppedProcess(t *testing.T) {
|
||||
return
|
||||
}
|
||||
status := <-statusC
|
||||
if status.Err != nil {
|
||||
code, _, err := status.Result()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
if status.Code != 6 {
|
||||
t.Errorf("exit status from stopped process should be 6 but received %d", status.Code)
|
||||
if code != 6 {
|
||||
t.Errorf("exit status from stopped process should be 6 but received %d", code)
|
||||
}
|
||||
|
||||
if err := task.Kill(ctx, syscall.SIGKILL); err != nil {
|
||||
@ -1343,12 +1350,13 @@ func TestContainerHostname(t *testing.T) {
|
||||
}
|
||||
|
||||
status := <-statusC
|
||||
if status.Err != nil {
|
||||
t.Error(status.Err)
|
||||
code, _, err := status.Result()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
if status.Code != 0 {
|
||||
t.Errorf("expected status 0 but received %d", status)
|
||||
if code != 0 {
|
||||
t.Errorf("expected status 0 but received %d", code)
|
||||
}
|
||||
if _, err := task.Delete(ctx); err != nil {
|
||||
t.Error(err)
|
||||
@ -1420,8 +1428,9 @@ func TestContainerExitedAtSet(t *testing.T) {
|
||||
}
|
||||
|
||||
status := <-statusC
|
||||
if status.Code != 0 {
|
||||
t.Errorf("expected status 0 but received %d", status)
|
||||
code, _, _ := status.Result()
|
||||
if code != 0 {
|
||||
t.Errorf("expected status 0 but received %d", code)
|
||||
}
|
||||
|
||||
if s, err := task.Status(ctx); err != nil {
|
||||
|
@ -188,10 +188,11 @@ To do this we will simply call `Kill` on the task after waiting a couple of seco
|
||||
}
|
||||
|
||||
status := <-exitStatusC
|
||||
if status.Err != nil {
|
||||
return status.Err
|
||||
code, exitedAt, err := status.Result()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("redis-server exited with status: %d\n", status.Code)
|
||||
fmt.Printf("redis-server exited with status: %d\n", code)
|
||||
```
|
||||
|
||||
We wait on our exit status channel that we setup to ensure the task has fully exited and we get the exit status.
|
||||
@ -291,10 +292,11 @@ func redisExample() error {
|
||||
// wait for the process to fully exit and print out the exit status
|
||||
|
||||
status := <-exitStatusC
|
||||
if status.Err != nil {
|
||||
code, _, err := status.Result()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("redis-server exited with status: %d\n", status.Code)
|
||||
fmt.Printf("redis-server exited with status: %d\n", code)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
27
process.go
27
process.go
@ -37,14 +37,21 @@ type Process interface {
|
||||
Status(context.Context) (Status, error)
|
||||
}
|
||||
|
||||
// ExitStatus encapsulates a process' exit code.
|
||||
// ExitStatus encapsulates a process' exit status.
|
||||
// It is used by `Wait()` to return either a process exit code or an error
|
||||
// The `Err` field is provided to return an error that may occur while waiting
|
||||
// `Err` is not used to convey an error with the process itself.
|
||||
type ExitStatus struct {
|
||||
Code uint32
|
||||
ExitedAt time.Time
|
||||
Err error
|
||||
code uint32
|
||||
exitedAt time.Time
|
||||
err error
|
||||
}
|
||||
|
||||
// Result returns the exit code and time of the exit status.
|
||||
// An error may be returned here to which indicates there was an error
|
||||
// at some point while waiting for the exit status. It does not signify
|
||||
// an error with the process itself.
|
||||
// If an error is returned, the process may still be running.
|
||||
func (s ExitStatus) Result() (uint32, time.Time, error) {
|
||||
return s.code, s.exitedAt, s.err
|
||||
}
|
||||
|
||||
type process struct {
|
||||
@ -109,7 +116,7 @@ func (p *process) Wait(ctx context.Context) (<-chan ExitStatus, error) {
|
||||
chStatus := make(chan ExitStatus, 1)
|
||||
if status.Status == Stopped {
|
||||
cancel()
|
||||
chStatus <- ExitStatus{Code: status.ExitStatus, ExitedAt: status.ExitTime}
|
||||
chStatus <- ExitStatus{code: status.ExitStatus, exitedAt: status.ExitTime}
|
||||
return chStatus, nil
|
||||
}
|
||||
|
||||
@ -119,18 +126,18 @@ func (p *process) Wait(ctx context.Context) (<-chan ExitStatus, error) {
|
||||
for {
|
||||
evt, err := eventstream.Recv()
|
||||
if err != nil {
|
||||
chStatus <- ExitStatus{Code: UnknownExitStatus, Err: err}
|
||||
chStatus <- ExitStatus{code: UnknownExitStatus, err: err}
|
||||
return
|
||||
}
|
||||
if typeurl.Is(evt.Event, &eventsapi.TaskExit{}) {
|
||||
v, err := typeurl.UnmarshalAny(evt.Event)
|
||||
if err != nil {
|
||||
chStatus <- ExitStatus{Code: UnknownExitStatus, Err: err}
|
||||
chStatus <- ExitStatus{code: UnknownExitStatus, err: err}
|
||||
return
|
||||
}
|
||||
e := v.(*eventsapi.TaskExit)
|
||||
if e.ID == p.id && e.ContainerID == p.task.id {
|
||||
chStatus <- ExitStatus{Code: e.ExitStatus, ExitedAt: e.ExitedAt}
|
||||
chStatus <- ExitStatus{code: e.ExitStatus, exitedAt: e.ExitedAt}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
8
task.go
8
task.go
@ -225,7 +225,7 @@ func (t *task) Wait(ctx context.Context) (<-chan ExitStatus, error) {
|
||||
}
|
||||
if status.Status == Stopped {
|
||||
cancel()
|
||||
chStatus <- ExitStatus{Code: status.ExitStatus, ExitedAt: status.ExitTime}
|
||||
chStatus <- ExitStatus{code: status.ExitStatus, exitedAt: status.ExitTime}
|
||||
return chStatus, nil
|
||||
}
|
||||
}
|
||||
@ -236,18 +236,18 @@ func (t *task) Wait(ctx context.Context) (<-chan ExitStatus, error) {
|
||||
for {
|
||||
evt, err := eventstream.Recv()
|
||||
if err != nil {
|
||||
chStatus <- ExitStatus{Code: UnknownExitStatus, Err: errdefs.FromGRPC(err)}
|
||||
chStatus <- ExitStatus{code: UnknownExitStatus, err: errdefs.FromGRPC(err)}
|
||||
return
|
||||
}
|
||||
if typeurl.Is(evt.Event, &eventsapi.TaskExit{}) {
|
||||
v, err := typeurl.UnmarshalAny(evt.Event)
|
||||
if err != nil {
|
||||
chStatus <- ExitStatus{Code: UnknownExitStatus, Err: err}
|
||||
chStatus <- ExitStatus{code: UnknownExitStatus, err: err}
|
||||
return
|
||||
}
|
||||
e := v.(*eventsapi.TaskExit)
|
||||
if e.ContainerID == t.id && e.Pid == t.pid {
|
||||
chStatus <- ExitStatus{Code: e.ExitStatus, ExitedAt: e.ExitedAt}
|
||||
chStatus <- ExitStatus{code: e.ExitStatus, exitedAt: e.ExitedAt}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user