Skip to content

Commit

Permalink
bugfix: make container exit with real exit code
Browse files Browse the repository at this point in the history
1. make container exit with real exit code
2. fix stop wait after stdin close

Fixes: #1075

Signed-off-by: Ace-Tang <[email protected]>
  • Loading branch information
Ace-Tang committed Apr 12, 2018
1 parent 8d90aba commit f130501
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 4 deletions.
29 changes: 28 additions & 1 deletion cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,23 @@ func (c *Cli) Client() client.CommonAPIClient {

// Run executes the client program.
func (c *Cli) Run() error {
return c.rootCmd.Execute()
err := c.rootCmd.Execute()
if err != nil {
// deal with ExitError, which should be recognize as error, and should
// not be exit with status 0.
if exitErr, ok := err.(ExitError); ok {
if exitErr.Status != "" {
fmt.Fprintln(os.Stderr, exitErr.Status)
}
if exitErr.Code == 0 {
// when get error with ExitError, code should not be 0.
exitErr.Code = 1
}
os.Exit(exitErr.Code)
}
}

return err
}

// AddCommand add a subcommand.
Expand Down Expand Up @@ -140,3 +156,14 @@ func (c *Cli) Print(obj interface{}) {

display.Flush()
}

// ExitError defines exit error produce by cli commands.
type ExitError struct {
Code int
Status string
}

// Error inplements error interface.
func (e ExitError) Error() string {
return fmt.Sprintf("Exit Code: %d, Status: %s", e.Code, e.Status)
}
13 changes: 12 additions & 1 deletion cli/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,14 +108,14 @@ func (rc *RunCommand) runRun(args []string) error {
if err != nil {
return fmt.Errorf("failed to attach container: %v", err)
}
defer conn.Close()

go func() {
io.Copy(os.Stdout, br)
wait <- struct{}{}
}()
go func() {
io.Copy(conn, os.Stdin)
wait <- struct{}{}
}()
}

Expand All @@ -130,6 +130,17 @@ func (rc *RunCommand) runRun(args []string) error {
} else {
fmt.Fprintf(os.Stdout, "%s\n", result.ID)
}

info, err := apiClient.ContainerGet(ctx, containerName)
if err != nil {

}

code := info.State.ExitCode
if code != 0 {
return ExitError{Code: int(code)}
}

return nil
}

Expand Down
13 changes: 12 additions & 1 deletion cli/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ func (s *StartCommand) runStart(args []string) error {
if err != nil {
return fmt.Errorf("failed to attach container: %v", err)
}
defer conn.Close()

wait = make(chan struct{})
go func() {
Expand All @@ -80,7 +81,6 @@ func (s *StartCommand) runStart(args []string) error {
}()
go func() {
io.Copy(conn, os.Stdin)
close(wait)
}()
}

Expand All @@ -93,6 +93,17 @@ func (s *StartCommand) runStart(args []string) error {
if s.attach || s.stdin {
<-wait
}

info, err := apiClient.ContainerGet(ctx, container)
if err != nil {

}

code := info.State.ExitCode
if code != 0 {
return ExitError{Code: int(code)}
}

return nil
}

Expand Down
18 changes: 17 additions & 1 deletion test/cli_run_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -817,7 +817,7 @@ func (suite *PouchRunSuite) TestRunWithDiskQuota(c *check.C) {
// TestRunWithAnnotation is to verify the valid running container with annotation, and verify SpecAnnotation filed has been in inspect output.
func (suite *PouchRunSuite) TestRunWithAnnotation(c *check.C) {
cname := "TestRunWithAnnotation"
command.PouchRun("run", "-d", "--annotation", "a=b", "--annotation", "foo=bar", "--name", cname, busyboxImage).Stdout()
command.PouchRun("run", "-d", "--annotation", "a=b", "--annotation", "foo=bar", "--name", cname, busyboxImage).Assert(c, icmd.Success)

output := command.PouchRun("inspect", cname).Stdout()
result := &types.ContainerJSON{}
Expand All @@ -835,3 +835,19 @@ func (suite *PouchRunSuite) TestRunWithAnnotation(c *check.C) {
c.Assert(util.PartialEqual(annotationStr, "a=b"), check.IsNil)
c.Assert(util.PartialEqual(annotationStr, "foo=bar"), check.IsNil)
}

// TestRunWithExitCode is to verify the valid running container with exit code != 0.
func (suite *PouchRunSuite) TestRunWithExitCode(c *check.C) {
cname := "TestRunWithExitCode"
ret := command.PouchRun("run", "--name", cname, busyboxImage, "sh", "-c", "exit 101")
// test process exit code $? == 101
ret.Assert(c, icmd.Expected{ExitCode: 101})

// test container ExitCode == 101
output := command.PouchRun("inspect", cname).Stdout()
result := &types.ContainerJSON{}
if err := json.Unmarshal([]byte(output), result); err != nil {
c.Errorf("failed to decode inspect output: %v", err)
}
c.Assert(result.State.ExitCode, check.Equals, int64(101))
}
23 changes: 23 additions & 0 deletions test/cli_start_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ package main

import (
"bufio"
"encoding/json"
"os/exec"
"strings"

"github.com/alibaba/pouch/apis/types"
"github.com/alibaba/pouch/test/command"
"github.com/alibaba/pouch/test/environment"

Expand Down Expand Up @@ -244,3 +246,24 @@ func (suite *PouchStartSuite) TestStartWithAnnotation(c *check.C) {

command.PouchRun("start", name).Assert(c, icmd.Success)
}

// TestStartWithExitCode starts a container with annotation.
func (suite *PouchStartSuite) TestStartWithExitCode(c *check.C) {
name := "start-exitcode"

res := command.PouchRun("create", "--name", name, busyboxImage, "sh", "-c", "exit 101")
res.Assert(c, icmd.Success)
defer DelContainerForceMultyTime(c, name)

// test process exit code $? == 101
ret := command.PouchRun("start", "-a", name)
ret.Assert(c, icmd.Expected{ExitCode: 101})

// test container ExitCode == 101
output := command.PouchRun("inspect", name).Stdout()
result := &types.ContainerJSON{}
if err := json.Unmarshal([]byte(output), result); err != nil {
c.Errorf("failed to decode inspect output: %v", err)
}
c.Assert(result.State.ExitCode, check.Equals, int64(101))
}

0 comments on commit f130501

Please sign in to comment.