diff --git a/client/checkpoint_list.go b/client/checkpoint_list.go index 66d46dd161..39cfb959ff 100644 --- a/client/checkpoint_list.go +++ b/client/checkpoint_list.go @@ -20,7 +20,7 @@ func (cli *Client) CheckpointList(ctx context.Context, container string, options resp, err := cli.get(ctx, "/containers/"+container+"/checkpoints", query, nil) defer ensureReaderClosed(resp) if err != nil { - return checkpoints, wrapResponseError(err, resp, "container", container) + return checkpoints, err } err = json.NewDecoder(resp.body).Decode(&checkpoints) diff --git a/client/config_inspect.go b/client/config_inspect.go index f1b0d7f753..9be7882c3d 100644 --- a/client/config_inspect.go +++ b/client/config_inspect.go @@ -20,7 +20,7 @@ func (cli *Client) ConfigInspectWithRaw(ctx context.Context, id string) (swarm.C resp, err := cli.get(ctx, "/configs/"+id, nil, nil) defer ensureReaderClosed(resp) if err != nil { - return swarm.Config{}, nil, wrapResponseError(err, resp, "config", id) + return swarm.Config{}, nil, err } body, err := io.ReadAll(resp.body) diff --git a/client/config_remove.go b/client/config_remove.go index 93de0d8445..24b94e9c18 100644 --- a/client/config_remove.go +++ b/client/config_remove.go @@ -9,5 +9,5 @@ func (cli *Client) ConfigRemove(ctx context.Context, id string) error { } resp, err := cli.delete(ctx, "/configs/"+id, nil, nil) defer ensureReaderClosed(resp) - return wrapResponseError(err, resp, "config", id) + return err } diff --git a/client/container_copy.go b/client/container_copy.go index c0a47c14e3..d8b7bb6b91 100644 --- a/client/container_copy.go +++ b/client/container_copy.go @@ -23,7 +23,7 @@ func (cli *Client) ContainerStatPath(ctx context.Context, containerID, path stri response, err := cli.head(ctx, urlStr, query, nil) defer ensureReaderClosed(response) if err != nil { - return types.ContainerPathStat{}, wrapResponseError(err, response, "container:path", containerID+":"+path) + return types.ContainerPathStat{}, err } return getContainerPathStatFromHeader(response.header) } @@ -47,7 +47,7 @@ func (cli *Client) CopyToContainer(ctx context.Context, containerID, dstPath str response, err := cli.putRaw(ctx, apiPath, query, content, nil) defer ensureReaderClosed(response) if err != nil { - return wrapResponseError(err, response, "container:path", containerID+":"+dstPath) + return err } // TODO this code converts non-error status-codes (e.g., "204 No Content") into an error; verify if this is the desired behavior @@ -67,7 +67,7 @@ func (cli *Client) CopyFromContainer(ctx context.Context, containerID, srcPath s apiPath := "/containers/" + containerID + "/archive" response, err := cli.get(ctx, apiPath, query, nil) if err != nil { - return nil, types.ContainerPathStat{}, wrapResponseError(err, response, "container:path", containerID+":"+srcPath) + return nil, types.ContainerPathStat{}, err } // TODO this code converts non-error status-codes (e.g., "204 No Content") into an error; verify if this is the desired behavior diff --git a/client/container_inspect.go b/client/container_inspect.go index 43db32bd97..d48f0d3a68 100644 --- a/client/container_inspect.go +++ b/client/container_inspect.go @@ -18,7 +18,7 @@ func (cli *Client) ContainerInspect(ctx context.Context, containerID string) (ty serverResp, err := cli.get(ctx, "/containers/"+containerID+"/json", nil, nil) defer ensureReaderClosed(serverResp) if err != nil { - return types.ContainerJSON{}, wrapResponseError(err, serverResp, "container", containerID) + return types.ContainerJSON{}, err } var response types.ContainerJSON @@ -38,7 +38,7 @@ func (cli *Client) ContainerInspectWithRaw(ctx context.Context, containerID stri serverResp, err := cli.get(ctx, "/containers/"+containerID+"/json", query, nil) defer ensureReaderClosed(serverResp) if err != nil { - return types.ContainerJSON{}, nil, wrapResponseError(err, serverResp, "container", containerID) + return types.ContainerJSON{}, nil, err } body, err := io.ReadAll(serverResp.body) diff --git a/client/container_logs.go b/client/container_logs.go index 5b6541f035..e9ae2f680f 100644 --- a/client/container_logs.go +++ b/client/container_logs.go @@ -74,7 +74,7 @@ func (cli *Client) ContainerLogs(ctx context.Context, container string, options resp, err := cli.get(ctx, "/containers/"+container+"/logs", query, nil) if err != nil { - return nil, wrapResponseError(err, resp, "container", container) + return nil, err } return resp.body, nil } diff --git a/client/container_remove.go b/client/container_remove.go index df81461b88..c21de609b0 100644 --- a/client/container_remove.go +++ b/client/container_remove.go @@ -23,5 +23,5 @@ func (cli *Client) ContainerRemove(ctx context.Context, containerID string, opti resp, err := cli.delete(ctx, "/containers/"+containerID, query, nil) defer ensureReaderClosed(resp) - return wrapResponseError(err, resp, "container", containerID) + return err } diff --git a/client/container_remove_test.go b/client/container_remove_test.go index ffc15eaf7e..07c147e2b5 100644 --- a/client/container_remove_test.go +++ b/client/container_remove_test.go @@ -12,7 +12,6 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/errdefs" "gotest.tools/v3/assert" - is "gotest.tools/v3/assert/cmp" ) func TestContainerRemoveError(t *testing.T) { @@ -27,10 +26,10 @@ func TestContainerRemoveError(t *testing.T) { func TestContainerRemoveNotFoundError(t *testing.T) { client := &Client{ - client: newMockClient(errorMock(http.StatusNotFound, "missing")), + client: newMockClient(errorMock(http.StatusNotFound, "no such container: container_id")), } err := client.ContainerRemove(context.Background(), "container_id", types.ContainerRemoveOptions{}) - assert.Check(t, is.Error(err, "Error: No such container: container_id")) + assert.ErrorContains(t, err, "no such container: container_id") assert.Check(t, IsErrNotFound(err)) } diff --git a/client/errors.go b/client/errors.go index 041bc8d49c..257921cebb 100644 --- a/client/errors.go +++ b/client/errors.go @@ -2,7 +2,6 @@ package client // import "github.com/docker/docker/client" import ( "fmt" - "net/http" "github.com/docker/docker/api/types/versions" "github.com/docker/docker/errdefs" @@ -59,19 +58,6 @@ func (e objectNotFoundError) Error() string { return fmt.Sprintf("Error: No such %s: %s", e.object, e.id) } -func wrapResponseError(err error, resp serverResponse, object, id string) error { - switch { - case err == nil: - return nil - case resp.statusCode == http.StatusNotFound: - return objectNotFoundError{object: object, id: id} - case resp.statusCode == http.StatusNotImplemented: - return errdefs.NotImplemented(err) - default: - return err - } -} - // unauthorizedError represents an authorization error in a remote registry. type unauthorizedError struct { cause error diff --git a/client/image_inspect.go b/client/image_inspect.go index 03aa12d8b4..1de10e5a08 100644 --- a/client/image_inspect.go +++ b/client/image_inspect.go @@ -17,7 +17,7 @@ func (cli *Client) ImageInspectWithRaw(ctx context.Context, imageID string) (typ serverResp, err := cli.get(ctx, "/images/"+imageID+"/json", nil, nil) defer ensureReaderClosed(serverResp) if err != nil { - return types.ImageInspect{}, nil, wrapResponseError(err, serverResp, "image", imageID) + return types.ImageInspect{}, nil, err } body, err := io.ReadAll(serverResp.body) diff --git a/client/image_remove.go b/client/image_remove.go index 84a41af0f2..6a9fb3f41f 100644 --- a/client/image_remove.go +++ b/client/image_remove.go @@ -23,7 +23,7 @@ func (cli *Client) ImageRemove(ctx context.Context, imageID string, options type resp, err := cli.delete(ctx, "/images/"+imageID, query, nil) defer ensureReaderClosed(resp) if err != nil { - return dels, wrapResponseError(err, resp, "image", imageID) + return dels, err } err = json.NewDecoder(resp.body).Decode(&dels) diff --git a/client/image_remove_test.go b/client/image_remove_test.go index 919baa2f68..cdf70b34c5 100644 --- a/client/image_remove_test.go +++ b/client/image_remove_test.go @@ -13,7 +13,6 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/errdefs" "gotest.tools/v3/assert" - is "gotest.tools/v3/assert/cmp" ) func TestImageRemoveError(t *testing.T) { @@ -29,11 +28,11 @@ func TestImageRemoveError(t *testing.T) { func TestImageRemoveImageNotFound(t *testing.T) { client := &Client{ - client: newMockClient(errorMock(http.StatusNotFound, "missing")), + client: newMockClient(errorMock(http.StatusNotFound, "no such image: unknown")), } _, err := client.ImageRemove(context.Background(), "unknown", types.ImageRemoveOptions{}) - assert.Check(t, is.Error(err, "Error: No such image: unknown")) + assert.ErrorContains(t, err, "no such image: unknown") assert.Check(t, IsErrNotFound(err)) } diff --git a/client/network_inspect.go b/client/network_inspect.go index ecf20ceb6e..0f90e2bb90 100644 --- a/client/network_inspect.go +++ b/client/network_inspect.go @@ -36,7 +36,7 @@ func (cli *Client) NetworkInspectWithRaw(ctx context.Context, networkID string, resp, err = cli.get(ctx, "/networks/"+networkID, query, nil) defer ensureReaderClosed(resp) if err != nil { - return networkResource, nil, wrapResponseError(err, resp, "network", networkID) + return networkResource, nil, err } body, err := io.ReadAll(resp.body) diff --git a/client/network_inspect_test.go b/client/network_inspect_test.go index 84278fff65..2af672e400 100644 --- a/client/network_inspect_test.go +++ b/client/network_inspect_test.go @@ -14,7 +14,6 @@ import ( "github.com/docker/docker/api/types/network" "github.com/docker/docker/errdefs" "gotest.tools/v3/assert" - is "gotest.tools/v3/assert/cmp" ) func TestNetworkInspect(t *testing.T) { @@ -37,7 +36,7 @@ func TestNetworkInspect(t *testing.T) { return nil, errors.New("expected URL '/networks/network_id', got " + req.URL.Path) } if strings.Contains(req.URL.RawQuery, "scope=global") { - return errorMock(http.StatusNotFound, "Error: No such network: unknown")(req) + return errorMock(http.StatusNotFound, "Error: No such network: network_id")(req) } var ( content []byte @@ -88,12 +87,12 @@ func TestNetworkInspect(t *testing.T) { }) t.Run("global scope", func(t *testing.T) { _, err := client.NetworkInspect(context.Background(), "network_id", types.NetworkInspectOptions{Scope: "global"}) - assert.Check(t, is.Error(err, "Error: No such network: network_id")) + assert.ErrorContains(t, err, "Error: No such network: network_id") assert.Check(t, IsErrNotFound(err)) }) t.Run("unknown network", func(t *testing.T) { _, err := client.NetworkInspect(context.Background(), "unknown", types.NetworkInspectOptions{}) - assert.Check(t, is.Error(err, "Error: No such network: unknown")) + assert.ErrorContains(t, err, "Error: No such network: unknown") assert.Check(t, IsErrNotFound(err)) }) t.Run("server error", func(t *testing.T) { diff --git a/client/network_remove.go b/client/network_remove.go index e71b16d869..9d6c6cef07 100644 --- a/client/network_remove.go +++ b/client/network_remove.go @@ -6,5 +6,5 @@ import "context" func (cli *Client) NetworkRemove(ctx context.Context, networkID string) error { resp, err := cli.delete(ctx, "/networks/"+networkID, nil, nil) defer ensureReaderClosed(resp) - return wrapResponseError(err, resp, "network", networkID) + return err } diff --git a/client/node_inspect.go b/client/node_inspect.go index b58db52856..95ab9b1be0 100644 --- a/client/node_inspect.go +++ b/client/node_inspect.go @@ -17,7 +17,7 @@ func (cli *Client) NodeInspectWithRaw(ctx context.Context, nodeID string) (swarm serverResp, err := cli.get(ctx, "/nodes/"+nodeID, nil, nil) defer ensureReaderClosed(serverResp) if err != nil { - return swarm.Node{}, nil, wrapResponseError(err, serverResp, "node", nodeID) + return swarm.Node{}, nil, err } body, err := io.ReadAll(serverResp.body) diff --git a/client/node_remove.go b/client/node_remove.go index 03ab878097..e44436debc 100644 --- a/client/node_remove.go +++ b/client/node_remove.go @@ -16,5 +16,5 @@ func (cli *Client) NodeRemove(ctx context.Context, nodeID string, options types. resp, err := cli.delete(ctx, "/nodes/"+nodeID, query, nil) defer ensureReaderClosed(resp) - return wrapResponseError(err, resp, "node", nodeID) + return err } diff --git a/client/plugin_inspect.go b/client/plugin_inspect.go index 4a90bec51a..f09e460660 100644 --- a/client/plugin_inspect.go +++ b/client/plugin_inspect.go @@ -17,7 +17,7 @@ func (cli *Client) PluginInspectWithRaw(ctx context.Context, name string) (*type resp, err := cli.get(ctx, "/plugins/"+name+"/json", nil, nil) defer ensureReaderClosed(resp) if err != nil { - return nil, nil, wrapResponseError(err, resp, "plugin", name) + return nil, nil, err } body, err := io.ReadAll(resp.body) diff --git a/client/plugin_list.go b/client/plugin_list.go index cf1935e2f5..2091a054d6 100644 --- a/client/plugin_list.go +++ b/client/plugin_list.go @@ -25,7 +25,7 @@ func (cli *Client) PluginList(ctx context.Context, filter filters.Args) (types.P resp, err := cli.get(ctx, "/plugins", query, nil) defer ensureReaderClosed(resp) if err != nil { - return plugins, wrapResponseError(err, resp, "plugin", "") + return plugins, err } err = json.NewDecoder(resp.body).Decode(&plugins) diff --git a/client/plugin_remove.go b/client/plugin_remove.go index 51ca1040d6..4cd66958c3 100644 --- a/client/plugin_remove.go +++ b/client/plugin_remove.go @@ -16,5 +16,5 @@ func (cli *Client) PluginRemove(ctx context.Context, name string, options types. resp, err := cli.delete(ctx, "/plugins/"+name, query, nil) defer ensureReaderClosed(resp) - return wrapResponseError(err, resp, "plugin", name) + return err } diff --git a/client/secret_inspect.go b/client/secret_inspect.go index c07c9550d4..5906874b15 100644 --- a/client/secret_inspect.go +++ b/client/secret_inspect.go @@ -20,7 +20,7 @@ func (cli *Client) SecretInspectWithRaw(ctx context.Context, id string) (swarm.S resp, err := cli.get(ctx, "/secrets/"+id, nil, nil) defer ensureReaderClosed(resp) if err != nil { - return swarm.Secret{}, nil, wrapResponseError(err, resp, "secret", id) + return swarm.Secret{}, nil, err } body, err := io.ReadAll(resp.body) diff --git a/client/secret_remove.go b/client/secret_remove.go index f6c69e57f8..f47f68b6e0 100644 --- a/client/secret_remove.go +++ b/client/secret_remove.go @@ -9,5 +9,5 @@ func (cli *Client) SecretRemove(ctx context.Context, id string) error { } resp, err := cli.delete(ctx, "/secrets/"+id, nil, nil) defer ensureReaderClosed(resp) - return wrapResponseError(err, resp, "secret", id) + return err } diff --git a/client/service_inspect.go b/client/service_inspect.go index c5368bab1e..cee020c98b 100644 --- a/client/service_inspect.go +++ b/client/service_inspect.go @@ -22,7 +22,7 @@ func (cli *Client) ServiceInspectWithRaw(ctx context.Context, serviceID string, serverResp, err := cli.get(ctx, "/services/"+serviceID, query, nil) defer ensureReaderClosed(serverResp) if err != nil { - return swarm.Service{}, nil, wrapResponseError(err, serverResp, "service", serviceID) + return swarm.Service{}, nil, err } body, err := io.ReadAll(serverResp.body) diff --git a/client/service_remove.go b/client/service_remove.go index 953a2adf5a..2c46326ebc 100644 --- a/client/service_remove.go +++ b/client/service_remove.go @@ -6,5 +6,5 @@ import "context" func (cli *Client) ServiceRemove(ctx context.Context, serviceID string) error { resp, err := cli.delete(ctx, "/services/"+serviceID, nil, nil) defer ensureReaderClosed(resp) - return wrapResponseError(err, resp, "service", serviceID) + return err } diff --git a/client/service_remove_test.go b/client/service_remove_test.go index a6d6f37cb4..0f8b0dedec 100644 --- a/client/service_remove_test.go +++ b/client/service_remove_test.go @@ -11,7 +11,6 @@ import ( "github.com/docker/docker/errdefs" "gotest.tools/v3/assert" - is "gotest.tools/v3/assert/cmp" ) func TestServiceRemoveError(t *testing.T) { @@ -27,11 +26,11 @@ func TestServiceRemoveError(t *testing.T) { func TestServiceRemoveNotFoundError(t *testing.T) { client := &Client{ - client: newMockClient(errorMock(http.StatusNotFound, "missing")), + client: newMockClient(errorMock(http.StatusNotFound, "no such service: service_id")), } err := client.ServiceRemove(context.Background(), "service_id") - assert.Check(t, is.Error(err, "Error: No such service: service_id")) + assert.ErrorContains(t, err, "no such service: service_id") assert.Check(t, IsErrNotFound(err)) } diff --git a/client/task_inspect.go b/client/task_inspect.go index 410fc526e2..dde1f6c59d 100644 --- a/client/task_inspect.go +++ b/client/task_inspect.go @@ -17,7 +17,7 @@ func (cli *Client) TaskInspectWithRaw(ctx context.Context, taskID string) (swarm serverResp, err := cli.get(ctx, "/tasks/"+taskID, nil, nil) defer ensureReaderClosed(serverResp) if err != nil { - return swarm.Task{}, nil, wrapResponseError(err, serverResp, "task", taskID) + return swarm.Task{}, nil, err } body, err := io.ReadAll(serverResp.body) diff --git a/client/volume_inspect.go b/client/volume_inspect.go index 5c5b3f905c..070209b35e 100644 --- a/client/volume_inspect.go +++ b/client/volume_inspect.go @@ -25,7 +25,7 @@ func (cli *Client) VolumeInspectWithRaw(ctx context.Context, volumeID string) (t resp, err := cli.get(ctx, "/volumes/"+volumeID, nil, nil) defer ensureReaderClosed(resp) if err != nil { - return volume, nil, wrapResponseError(err, resp, "volume", volumeID) + return volume, nil, err } body, err := io.ReadAll(resp.body) diff --git a/client/volume_remove.go b/client/volume_remove.go index 79decdafab..1f26438360 100644 --- a/client/volume_remove.go +++ b/client/volume_remove.go @@ -17,5 +17,5 @@ func (cli *Client) VolumeRemove(ctx context.Context, volumeID string, force bool } resp, err := cli.delete(ctx, "/volumes/"+volumeID, query, nil) defer ensureReaderClosed(resp) - return wrapResponseError(err, resp, "volume", volumeID) + return err } diff --git a/integration-cli/docker_api_containers_test.go b/integration-cli/docker_api_containers_test.go index 878ddfe0e1..e8baeff5f9 100644 --- a/integration-cli/docker_api_containers_test.go +++ b/integration-cli/docker_api_containers_test.go @@ -23,6 +23,7 @@ import ( "github.com/docker/docker/api/types/versions" "github.com/docker/docker/client" dconfig "github.com/docker/docker/daemon/config" + "github.com/docker/docker/errdefs" "github.com/docker/docker/integration-cli/cli" "github.com/docker/docker/integration-cli/cli/build" "github.com/docker/docker/pkg/ioutils" @@ -1590,7 +1591,7 @@ func (s *DockerSuite) TestContainerAPIDeleteWithEmptyName(c *testing.T) { defer cli.Close() err = cli.ContainerRemove(context.Background(), "", types.ContainerRemoveOptions{}) - assert.ErrorContains(c, err, "No such container") + assert.Check(c, errdefs.IsNotFound(err)) } func (s *DockerSuite) TestContainerAPIStatsWithNetworkDisabled(c *testing.T) { diff --git a/integration/container/copy_test.go b/integration/container/copy_test.go index 128e202903..e7405e638c 100644 --- a/integration/container/copy_test.go +++ b/integration/container/copy_test.go @@ -4,7 +4,6 @@ import ( "archive/tar" "context" "encoding/json" - "fmt" "io" "os" "testing" @@ -28,8 +27,7 @@ func TestCopyFromContainerPathDoesNotExist(t *testing.T) { _, _, err := apiclient.CopyFromContainer(ctx, cid, "/dne") assert.Check(t, client.IsErrNotFound(err)) - expected := fmt.Sprintf("No such container:path: %s:%s", cid, "/dne") - assert.Check(t, is.ErrorContains(err, expected)) + assert.ErrorContains(t, err, "Could not find the file /dne in container "+cid) } func TestCopyFromContainerPathIsNotDir(t *testing.T) { @@ -58,8 +56,7 @@ func TestCopyToContainerPathDoesNotExist(t *testing.T) { err := apiclient.CopyToContainer(ctx, cid, "/dne", nil, types.CopyToContainerOptions{}) assert.Check(t, client.IsErrNotFound(err)) - expected := fmt.Sprintf("No such container:path: %s:%s", cid, "/dne") - assert.Check(t, is.ErrorContains(err, expected)) + assert.ErrorContains(t, err, "Could not find the file /dne in container "+cid) } func TestCopyToContainerPathIsNotDir(t *testing.T) {