diff --git a/cli/command/network/remove.go b/cli/command/network/remove.go index ed1b7f264f7a..151c531f2391 100644 --- a/cli/command/network/remove.go +++ b/cli/command/network/remove.go @@ -3,6 +3,7 @@ package network import ( "context" "fmt" + "strconv" "github.com/docker/cli/cli" "github.com/docker/cli/cli/command" @@ -68,7 +69,7 @@ func runRemove(ctx context.Context, dockerCLI command.Cli, networks []string, op } if status != 0 { - return cli.StatusError{StatusCode: status} + return cli.StatusError{StatusCode: status, Status: "exit status " + strconv.Itoa(status)} } return nil } diff --git a/cli/error.go b/cli/error.go index 1d35b4e77d65..3d198917ccf9 100644 --- a/cli/error.go +++ b/cli/error.go @@ -1,9 +1,5 @@ package cli -import ( - "strconv" -) - // StatusError reports an unsuccessful exit by a command. type StatusError struct { Cause error @@ -21,7 +17,9 @@ func (e StatusError) Error() string { if e.Cause != nil { return e.Cause.Error() } - return "exit status " + strconv.Itoa(e.StatusCode) + // we don't want to set a default message here, + // some commands might want to be explicit about the error message + return "" } func (e StatusError) Unwrap() error { diff --git a/cmd/docker/docker.go b/cmd/docker/docker.go index 46a235c4bdb8..5183d455f9cd 100644 --- a/cmd/docker/docker.go +++ b/cmd/docker/docker.go @@ -43,7 +43,9 @@ func main() { } if err != nil && !errdefs.IsCancelled(err) { - _, _ = fmt.Fprintln(os.Stderr, err) + if err.Error() != "" { + _, _ = fmt.Fprintln(os.Stderr, err) + } os.Exit(getExitCode(err)) } } diff --git a/e2e/cli-plugins/socket_test.go b/e2e/cli-plugins/socket_test.go index c641f0b7dac4..c754e27111fc 100644 --- a/e2e/cli-plugins/socket_test.go +++ b/e2e/cli-plugins/socket_test.go @@ -137,7 +137,6 @@ func TestPluginSocketBackwardsCompatible(t *testing.T) { assert.Assert(t, errors.As(err, &exitError)) assert.Check(t, exitError.Exited()) assert.Check(t, is.Equal(exitError.ExitCode(), 1)) - assert.Check(t, is.ErrorContains(err, "exit status 1")) // the plugin process does not receive a SIGINT and does // the CLI cannot cancel it over the socket, so it kills @@ -199,11 +198,10 @@ func TestPluginSocketCommunication(t *testing.T) { assert.Assert(t, errors.As(err, &exitError)) assert.Check(t, exitError.Exited()) assert.Check(t, is.Equal(exitError.ExitCode(), 2)) - assert.Check(t, is.ErrorContains(err, "exit status 2")) // the plugin does not get signalled, but it does get its // context canceled by the CLI through the socket - const expected = "test-socket: exiting after context was done\nexit status 2" + const expected = "test-socket: exiting after context was done" actual := strings.TrimSpace(string(out)) assert.Check(t, is.Equal(actual, expected)) }) @@ -238,7 +236,6 @@ func TestPluginSocketCommunication(t *testing.T) { assert.Assert(t, errors.As(err, &exitError)) assert.Check(t, exitError.Exited()) assert.Check(t, is.Equal(exitError.ExitCode(), 1)) - assert.Check(t, is.ErrorContains(err, "exit status 1")) // the plugin process does not receive a SIGINT and does // not exit after having it's context canceled, so the CLI diff --git a/e2e/container/attach_test.go b/e2e/container/attach_test.go index 545d86ed707a..49765da891a8 100644 --- a/e2e/container/attach_test.go +++ b/e2e/container/attach_test.go @@ -58,5 +58,4 @@ func TestAttachInterrupt(t *testing.T) { // the CLI should exit with 33 (the SIGINT was forwarded to the container), and the // CLI process waited for the container exit and properly captured/set the exit code assert.Equal(t, c.ProcessState.ExitCode(), 33) - assert.Equal(t, d.String(), "exit status 33\n") } diff --git a/e2e/container/run_test.go b/e2e/container/run_test.go index f4e591e21d4d..ec56d03b2b56 100644 --- a/e2e/container/run_test.go +++ b/e2e/container/run_test.go @@ -68,7 +68,6 @@ func TestRunAttach(t *testing.T) { } assert.Equal(t, c.ProcessState.ExitCode(), 7) - assert.Check(t, is.Contains(d.String(), "exit status 7")) }) } }