From 81bb9978ab5ac99e84a5bf62d0d469f0aec1d506 Mon Sep 17 00:00:00 2001 From: Daniel Nephin Date: Fri, 8 Sep 2017 12:04:34 -0400 Subject: [PATCH] Cleanup client not found errors. And fix remove calls to return a notFound error Signed-off-by: Daniel Nephin --- client/checkpoint_list.go | 6 +- client/config_inspect.go | 6 +- client/config_remove.go | 2 +- client/container_create.go | 2 +- client/container_inspect.go | 11 +- client/container_remove.go | 2 +- client/container_remove_test.go | 16 +- client/errors.go | 177 +++--------------- client/image_inspect.go | 6 +- client/image_remove.go | 8 +- client/image_remove_test.go | 12 +- client/network_inspect.go | 6 +- client/network_inspect_test.go | 13 +- client/network_remove.go | 2 +- client/node_inspect.go | 6 +- client/node_remove.go | 2 +- client/ping.go | 4 +- client/plugin_inspect.go | 6 +- client/plugin_remove.go | 2 +- client/request.go | 2 +- client/secret_inspect.go | 6 +- client/secret_remove.go | 2 +- client/service_inspect.go | 6 +- client/service_remove.go | 2 +- client/service_remove_test.go | 13 +- client/task_inspect.go | 7 +- client/volume_inspect.go | 8 +- client/volume_remove.go | 2 +- integration-cli/docker_api_containers_test.go | 2 +- .../docker_api_swarm_config_test.go | 4 +- .../docker_api_swarm_secret_test.go | 6 +- 31 files changed, 86 insertions(+), 263 deletions(-) diff --git a/client/checkpoint_list.go b/client/checkpoint_list.go index ffe44bc976..9835bad5ca 100644 --- a/client/checkpoint_list.go +++ b/client/checkpoint_list.go @@ -2,7 +2,6 @@ package client import ( "encoding/json" - "net/http" "net/url" "github.com/docker/docker/api/types" @@ -20,10 +19,7 @@ func (cli *Client) CheckpointList(ctx context.Context, container string, options resp, err := cli.get(ctx, "/containers/"+container+"/checkpoints", query, nil) if err != nil { - if resp.statusCode == http.StatusNotFound { - return checkpoints, containerNotFoundError{container} - } - return checkpoints, err + return checkpoints, wrapResponseError(err, resp, "container", container) } err = json.NewDecoder(resp.body).Decode(&checkpoints) diff --git a/client/config_inspect.go b/client/config_inspect.go index ebb6d636c2..b44d6fdd7e 100644 --- a/client/config_inspect.go +++ b/client/config_inspect.go @@ -4,7 +4,6 @@ import ( "bytes" "encoding/json" "io/ioutil" - "net/http" "github.com/docker/docker/api/types/swarm" "golang.org/x/net/context" @@ -17,10 +16,7 @@ func (cli *Client) ConfigInspectWithRaw(ctx context.Context, id string) (swarm.C } resp, err := cli.get(ctx, "/configs/"+id, nil, nil) if err != nil { - if resp.statusCode == http.StatusNotFound { - return swarm.Config{}, nil, configNotFoundError{id} - } - return swarm.Config{}, nil, err + return swarm.Config{}, nil, wrapResponseError(err, resp, "config", id) } defer ensureReaderClosed(resp) diff --git a/client/config_remove.go b/client/config_remove.go index 726b5c8530..e025d44f79 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) ensureReaderClosed(resp) - return err + return wrapResponseError(err, resp, "config", id) } diff --git a/client/container_create.go b/client/container_create.go index 6841b0b282..bd817e7fd1 100644 --- a/client/container_create.go +++ b/client/container_create.go @@ -45,7 +45,7 @@ func (cli *Client) ContainerCreate(ctx context.Context, config *container.Config serverResp, err := cli.post(ctx, "/containers/create", query, body, nil) if err != nil { if serverResp.statusCode == 404 && strings.Contains(err.Error(), "No such image") { - return response, imageNotFoundError{config.Image} + return response, objectNotFoundError{object: "image", id: config.Image} } return response, err } diff --git a/client/container_inspect.go b/client/container_inspect.go index 17f1809747..a15db14be8 100644 --- a/client/container_inspect.go +++ b/client/container_inspect.go @@ -4,7 +4,6 @@ import ( "bytes" "encoding/json" "io/ioutil" - "net/http" "net/url" "github.com/docker/docker/api/types" @@ -15,10 +14,7 @@ import ( func (cli *Client) ContainerInspect(ctx context.Context, containerID string) (types.ContainerJSON, error) { serverResp, err := cli.get(ctx, "/containers/"+containerID+"/json", nil, nil) if err != nil { - if serverResp.statusCode == http.StatusNotFound { - return types.ContainerJSON{}, containerNotFoundError{containerID} - } - return types.ContainerJSON{}, err + return types.ContainerJSON{}, wrapResponseError(err, serverResp, "container", containerID) } var response types.ContainerJSON @@ -35,10 +31,7 @@ func (cli *Client) ContainerInspectWithRaw(ctx context.Context, containerID stri } serverResp, err := cli.get(ctx, "/containers/"+containerID+"/json", query, nil) if err != nil { - if serverResp.statusCode == http.StatusNotFound { - return types.ContainerJSON{}, nil, containerNotFoundError{containerID} - } - return types.ContainerJSON{}, nil, err + return types.ContainerJSON{}, nil, wrapResponseError(err, serverResp, "container", containerID) } defer ensureReaderClosed(serverResp) diff --git a/client/container_remove.go b/client/container_remove.go index 3a79590ced..070108bf3e 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) ensureReaderClosed(resp) - return err + return wrapResponseError(err, resp, "container", containerID) } diff --git a/client/container_remove_test.go b/client/container_remove_test.go index 798c08b333..0eab7ee518 100644 --- a/client/container_remove_test.go +++ b/client/container_remove_test.go @@ -9,6 +9,7 @@ import ( "testing" "github.com/docker/docker/api/types" + "github.com/stretchr/testify/assert" "golang.org/x/net/context" ) @@ -17,9 +18,16 @@ func TestContainerRemoveError(t *testing.T) { client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), } err := client.ContainerRemove(context.Background(), "container_id", types.ContainerRemoveOptions{}) - if err == nil || err.Error() != "Error response from daemon: Server error" { - t.Fatalf("expected a Server Error, got %v", err) + assert.EqualError(t, err, "Error response from daemon: Server error") +} + +func TestContainerRemoveNotFoundError(t *testing.T) { + client := &Client{ + client: newMockClient(errorMock(http.StatusNotFound, "missing")), } + err := client.ContainerRemove(context.Background(), "container_id", types.ContainerRemoveOptions{}) + assert.EqualError(t, err, "Error: No such container: container_id") + assert.True(t, IsErrNotFound(err)) } func TestContainerRemove(t *testing.T) { @@ -53,7 +61,5 @@ func TestContainerRemove(t *testing.T) { RemoveVolumes: true, Force: true, }) - if err != nil { - t.Fatal(err) - } + assert.NoError(t, err) } diff --git a/client/errors.go b/client/errors.go index 3f9d36dc14..cad4521757 100644 --- a/client/errors.go +++ b/client/errors.go @@ -3,6 +3,8 @@ package client import ( "fmt" + "net/http" + "github.com/docker/docker/api/types/versions" "github.com/pkg/errors" ) @@ -43,19 +45,28 @@ func IsErrNotFound(err error) bool { return ok && te.NotFound() } -// imageNotFoundError implements an error returned when an image is not in the docker host. -type imageNotFoundError struct { - imageID string +type objectNotFoundError struct { + object string + id string } -// NotFound indicates that this error type is of NotFound -func (e imageNotFoundError) NotFound() bool { +func (e objectNotFoundError) NotFound() bool { return true } -// Error returns a string representation of an imageNotFoundError -func (e imageNotFoundError) Error() string { - return fmt.Sprintf("Error: No such image: %s", e.imageID) +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} + default: + return err + } } // IsErrImageNotFound returns true if the error is caused @@ -66,21 +77,6 @@ func IsErrImageNotFound(err error) bool { return IsErrNotFound(err) } -// containerNotFoundError implements an error returned when a container is not in the docker host. -type containerNotFoundError struct { - containerID string -} - -// NotFound indicates that this error type is of NotFound -func (e containerNotFoundError) NotFound() bool { - return true -} - -// Error returns a string representation of a containerNotFoundError -func (e containerNotFoundError) Error() string { - return fmt.Sprintf("Error: No such container: %s", e.containerID) -} - // IsErrContainerNotFound returns true if the error is caused // when a container is not found in the docker host. // @@ -89,21 +85,6 @@ func IsErrContainerNotFound(err error) bool { return IsErrNotFound(err) } -// networkNotFoundError implements an error returned when a network is not in the docker host. -type networkNotFoundError struct { - networkID string -} - -// NotFound indicates that this error type is of NotFound -func (e networkNotFoundError) NotFound() bool { - return true -} - -// Error returns a string representation of a networkNotFoundError -func (e networkNotFoundError) Error() string { - return fmt.Sprintf("Error: No such network: %s", e.networkID) -} - // IsErrNetworkNotFound returns true if the error is caused // when a network is not found in the docker host. // @@ -112,21 +93,6 @@ func IsErrNetworkNotFound(err error) bool { return IsErrNotFound(err) } -// volumeNotFoundError implements an error returned when a volume is not in the docker host. -type volumeNotFoundError struct { - volumeID string -} - -// NotFound indicates that this error type is of NotFound -func (e volumeNotFoundError) NotFound() bool { - return true -} - -// Error returns a string representation of a volumeNotFoundError -func (e volumeNotFoundError) Error() string { - return fmt.Sprintf("Error: No such volume: %s", e.volumeID) -} - // IsErrVolumeNotFound returns true if the error is caused // when a volume is not found in the docker host. // @@ -152,43 +118,12 @@ func IsErrUnauthorized(err error) bool { return ok } -// nodeNotFoundError implements an error returned when a node is not found. -type nodeNotFoundError struct { - nodeID string -} - -// Error returns a string representation of a nodeNotFoundError -func (e nodeNotFoundError) Error() string { - return fmt.Sprintf("Error: No such node: %s", e.nodeID) -} - -// NotFound indicates that this error type is of NotFound -func (e nodeNotFoundError) NotFound() bool { - return true -} - // IsErrNodeNotFound returns true if the error is caused // when a node is not found. // // Deprecated: Use IsErrNotFound func IsErrNodeNotFound(err error) bool { - _, ok := err.(nodeNotFoundError) - return ok -} - -// serviceNotFoundError implements an error returned when a service is not found. -type serviceNotFoundError struct { - serviceID string -} - -// Error returns a string representation of a serviceNotFoundError -func (e serviceNotFoundError) Error() string { - return fmt.Sprintf("Error: No such service: %s", e.serviceID) -} - -// NotFound indicates that this error type is of NotFound -func (e serviceNotFoundError) NotFound() bool { - return true + return IsErrNotFound(err) } // IsErrServiceNotFound returns true if the error is caused @@ -196,23 +131,7 @@ func (e serviceNotFoundError) NotFound() bool { // // Deprecated: Use IsErrNotFound func IsErrServiceNotFound(err error) bool { - _, ok := err.(serviceNotFoundError) - return ok -} - -// taskNotFoundError implements an error returned when a task is not found. -type taskNotFoundError struct { - taskID string -} - -// Error returns a string representation of a taskNotFoundError -func (e taskNotFoundError) Error() string { - return fmt.Sprintf("Error: No such task: %s", e.taskID) -} - -// NotFound indicates that this error type is of NotFound -func (e taskNotFoundError) NotFound() bool { - return true + return IsErrNotFound(err) } // IsErrTaskNotFound returns true if the error is caused @@ -220,8 +139,7 @@ func (e taskNotFoundError) NotFound() bool { // // Deprecated: Use IsErrNotFound func IsErrTaskNotFound(err error) bool { - _, ok := err.(taskNotFoundError) - return ok + return IsErrNotFound(err) } type pluginPermissionDenied struct { @@ -248,43 +166,12 @@ func (cli *Client) NewVersionError(APIrequired, feature string) error { return nil } -// secretNotFoundError implements an error returned when a secret is not found. -type secretNotFoundError struct { - name string -} - -// Error returns a string representation of a secretNotFoundError -func (e secretNotFoundError) Error() string { - return fmt.Sprintf("Error: no such secret: %s", e.name) -} - -// NotFound indicates that this error type is of NotFound -func (e secretNotFoundError) NotFound() bool { - return true -} - // IsErrSecretNotFound returns true if the error is caused // when a secret is not found. // // Deprecated: Use IsErrNotFound func IsErrSecretNotFound(err error) bool { - _, ok := err.(secretNotFoundError) - return ok -} - -// configNotFoundError implements an error returned when a config is not found. -type configNotFoundError struct { - name string -} - -// Error returns a string representation of a configNotFoundError -func (e configNotFoundError) Error() string { - return fmt.Sprintf("Error: no such config: %s", e.name) -} - -// NotFound indicates that this error type is of NotFound -func (e configNotFoundError) NotFound() bool { - return true + return IsErrNotFound(err) } // IsErrConfigNotFound returns true if the error is caused @@ -292,23 +179,7 @@ func (e configNotFoundError) NotFound() bool { // // Deprecated: Use IsErrNotFound func IsErrConfigNotFound(err error) bool { - _, ok := err.(configNotFoundError) - return ok -} - -// pluginNotFoundError implements an error returned when a plugin is not in the docker host. -type pluginNotFoundError struct { - name string -} - -// NotFound indicates that this error type is of NotFound -func (e pluginNotFoundError) NotFound() bool { - return true -} - -// Error returns a string representation of a pluginNotFoundError -func (e pluginNotFoundError) Error() string { - return fmt.Sprintf("Error: No such plugin: %s", e.name) + return IsErrNotFound(err) } // IsErrPluginNotFound returns true if the error is caused diff --git a/client/image_inspect.go b/client/image_inspect.go index b3a64ce2f8..1bc5919907 100644 --- a/client/image_inspect.go +++ b/client/image_inspect.go @@ -4,7 +4,6 @@ import ( "bytes" "encoding/json" "io/ioutil" - "net/http" "github.com/docker/docker/api/types" "golang.org/x/net/context" @@ -14,10 +13,7 @@ import ( func (cli *Client) ImageInspectWithRaw(ctx context.Context, imageID string) (types.ImageInspect, []byte, error) { serverResp, err := cli.get(ctx, "/images/"+imageID+"/json", nil, nil) if err != nil { - if serverResp.statusCode == http.StatusNotFound { - return types.ImageInspect{}, nil, imageNotFoundError{imageID} - } - return types.ImageInspect{}, nil, err + return types.ImageInspect{}, nil, wrapResponseError(err, serverResp, "image", imageID) } defer ensureReaderClosed(serverResp) diff --git a/client/image_remove.go b/client/image_remove.go index 94e4b74ec3..81d6c5438d 100644 --- a/client/image_remove.go +++ b/client/image_remove.go @@ -2,7 +2,6 @@ package client import ( "encoding/json" - "net/http" "net/url" "github.com/docker/docker/api/types" @@ -20,15 +19,12 @@ func (cli *Client) ImageRemove(ctx context.Context, imageID string, options type query.Set("noprune", "1") } + var dels []types.ImageDeleteResponseItem resp, err := cli.delete(ctx, "/images/"+imageID, query, nil) if err != nil { - if resp.statusCode == http.StatusNotFound { - return nil, imageNotFoundError{imageID} - } - return nil, err + return dels, wrapResponseError(err, resp, "image", imageID) } - var dels []types.ImageDeleteResponseItem err = json.NewDecoder(resp.body).Decode(&dels) ensureReaderClosed(resp) return dels, err diff --git a/client/image_remove_test.go b/client/image_remove_test.go index 5a391b0ae6..6149db7cb6 100644 --- a/client/image_remove_test.go +++ b/client/image_remove_test.go @@ -10,6 +10,7 @@ import ( "testing" "github.com/docker/docker/api/types" + "github.com/stretchr/testify/assert" "golang.org/x/net/context" ) @@ -19,20 +20,17 @@ func TestImageRemoveError(t *testing.T) { } _, err := client.ImageRemove(context.Background(), "image_id", types.ImageRemoveOptions{}) - if err == nil || err.Error() != "Error response from daemon: Server error" { - t.Fatalf("expected a Server Error, got %v", err) - } + assert.EqualError(t, err, "Error response from daemon: Server error") } func TestImageRemoveImageNotFound(t *testing.T) { client := &Client{ - client: newMockClient(errorMock(http.StatusNotFound, "Server error")), + client: newMockClient(errorMock(http.StatusNotFound, "missing")), } _, err := client.ImageRemove(context.Background(), "unknown", types.ImageRemoveOptions{}) - if err == nil || !IsErrNotFound(err) { - t.Fatalf("expected an imageNotFoundError error, got %v", err) - } + assert.EqualError(t, err, "Error: No such image: unknown") + assert.True(t, IsErrNotFound(err)) } func TestImageRemove(t *testing.T) { diff --git a/client/network_inspect.go b/client/network_inspect.go index 848c9799fb..afabe65970 100644 --- a/client/network_inspect.go +++ b/client/network_inspect.go @@ -4,7 +4,6 @@ import ( "bytes" "encoding/json" "io/ioutil" - "net/http" "net/url" "github.com/docker/docker/api/types" @@ -33,10 +32,7 @@ func (cli *Client) NetworkInspectWithRaw(ctx context.Context, networkID string, } resp, err = cli.get(ctx, "/networks/"+networkID, query, nil) if err != nil { - if resp.statusCode == http.StatusNotFound { - return networkResource, nil, networkNotFoundError{networkID} - } - return networkResource, nil, err + return networkResource, nil, wrapResponseError(err, resp, "network", networkID) } defer ensureReaderClosed(resp) diff --git a/client/network_inspect_test.go b/client/network_inspect_test.go index 9bfb55d74e..56399c7bc2 100644 --- a/client/network_inspect_test.go +++ b/client/network_inspect_test.go @@ -21,20 +21,17 @@ func TestNetworkInspectError(t *testing.T) { } _, err := client.NetworkInspect(context.Background(), "nothing", types.NetworkInspectOptions{}) - if err == nil || err.Error() != "Error response from daemon: Server error" { - t.Fatalf("expected a Server Error, got %v", err) - } + assert.EqualError(t, err, "Error response from daemon: Server error") } -func TestNetworkInspectContainerNotFound(t *testing.T) { +func TestNetworkInspectNotFoundError(t *testing.T) { client := &Client{ - client: newMockClient(errorMock(http.StatusNotFound, "Server error")), + client: newMockClient(errorMock(http.StatusNotFound, "missing")), } _, err := client.NetworkInspect(context.Background(), "unknown", types.NetworkInspectOptions{}) - if err == nil || !IsErrNetworkNotFound(err) { - t.Fatalf("expected a networkNotFound error, got %v", err) - } + assert.EqualError(t, err, "Error: No such network: unknown") + assert.True(t, IsErrNotFound(err)) } func TestNetworkInspect(t *testing.T) { diff --git a/client/network_remove.go b/client/network_remove.go index 6bd6748924..0811b5b51c 100644 --- a/client/network_remove.go +++ b/client/network_remove.go @@ -6,5 +6,5 @@ import "golang.org/x/net/context" func (cli *Client) NetworkRemove(ctx context.Context, networkID string) error { resp, err := cli.delete(ctx, "/networks/"+networkID, nil, nil) ensureReaderClosed(resp) - return err + return wrapResponseError(err, resp, "network", networkID) } diff --git a/client/node_inspect.go b/client/node_inspect.go index abf505d29c..791d2c0066 100644 --- a/client/node_inspect.go +++ b/client/node_inspect.go @@ -4,7 +4,6 @@ import ( "bytes" "encoding/json" "io/ioutil" - "net/http" "github.com/docker/docker/api/types/swarm" "golang.org/x/net/context" @@ -14,10 +13,7 @@ import ( func (cli *Client) NodeInspectWithRaw(ctx context.Context, nodeID string) (swarm.Node, []byte, error) { serverResp, err := cli.get(ctx, "/nodes/"+nodeID, nil, nil) if err != nil { - if serverResp.statusCode == http.StatusNotFound { - return swarm.Node{}, nil, nodeNotFoundError{nodeID} - } - return swarm.Node{}, nil, err + return swarm.Node{}, nil, wrapResponseError(err, serverResp, "node", nodeID) } defer ensureReaderClosed(serverResp) diff --git a/client/node_remove.go b/client/node_remove.go index 0a77f3d578..adbf52febb 100644 --- a/client/node_remove.go +++ b/client/node_remove.go @@ -17,5 +17,5 @@ func (cli *Client) NodeRemove(ctx context.Context, nodeID string, options types. resp, err := cli.delete(ctx, "/nodes/"+nodeID, query, nil) ensureReaderClosed(resp) - return err + return wrapResponseError(err, resp, "node", nodeID) } diff --git a/client/ping.go b/client/ping.go index 8501375c88..0b6e450da7 100644 --- a/client/ping.go +++ b/client/ping.go @@ -28,7 +28,5 @@ func (cli *Client) Ping(ctx context.Context) (types.Ping, error) { } ping.OSType = serverResp.header.Get("OSType") } - - err = cli.checkResponseErr(serverResp) - return ping, err + return ping, cli.checkResponseErr(serverResp) } diff --git a/client/plugin_inspect.go b/client/plugin_inspect.go index 89f39ee2c6..6a6fc18dfe 100644 --- a/client/plugin_inspect.go +++ b/client/plugin_inspect.go @@ -4,7 +4,6 @@ import ( "bytes" "encoding/json" "io/ioutil" - "net/http" "github.com/docker/docker/api/types" "golang.org/x/net/context" @@ -14,10 +13,7 @@ import ( func (cli *Client) PluginInspectWithRaw(ctx context.Context, name string) (*types.Plugin, []byte, error) { resp, err := cli.get(ctx, "/plugins/"+name+"/json", nil, nil) if err != nil { - if resp.statusCode == http.StatusNotFound { - return nil, nil, pluginNotFoundError{name} - } - return nil, nil, err + return nil, nil, wrapResponseError(err, resp, "plugin", name) } defer ensureReaderClosed(resp) diff --git a/client/plugin_remove.go b/client/plugin_remove.go index b017e4d348..b498c48203 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) ensureReaderClosed(resp) - return err + return wrapResponseError(err, resp, "plugin", name) } diff --git a/client/request.go b/client/request.go index 3e7d43feac..615d0b989d 100644 --- a/client/request.go +++ b/client/request.go @@ -203,7 +203,7 @@ func (cli *Client) checkResponseErr(serverResp serverResponse) error { return err } if len(body) == 0 { - return fmt.Errorf("Error: request returned %s for API route and version %s, check if the server supports the requested API version", http.StatusText(serverResp.statusCode), serverResp.reqURL) + return fmt.Errorf("request returned %s for API route and version %s, check if the server supports the requested API version", http.StatusText(serverResp.statusCode), serverResp.reqURL) } var ct string diff --git a/client/secret_inspect.go b/client/secret_inspect.go index 9b602972bc..6927ea96fa 100644 --- a/client/secret_inspect.go +++ b/client/secret_inspect.go @@ -4,7 +4,6 @@ import ( "bytes" "encoding/json" "io/ioutil" - "net/http" "github.com/docker/docker/api/types/swarm" "golang.org/x/net/context" @@ -17,10 +16,7 @@ func (cli *Client) SecretInspectWithRaw(ctx context.Context, id string) (swarm.S } resp, err := cli.get(ctx, "/secrets/"+id, nil, nil) if err != nil { - if resp.statusCode == http.StatusNotFound { - return swarm.Secret{}, nil, secretNotFoundError{id} - } - return swarm.Secret{}, nil, err + return swarm.Secret{}, nil, wrapResponseError(err, resp, "secret", id) } defer ensureReaderClosed(resp) diff --git a/client/secret_remove.go b/client/secret_remove.go index c5e37af17d..9b4ee71e2c 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) ensureReaderClosed(resp) - return err + return wrapResponseError(err, resp, "secret", id) } diff --git a/client/service_inspect.go b/client/service_inspect.go index d7e051e3a4..3e9699e5e0 100644 --- a/client/service_inspect.go +++ b/client/service_inspect.go @@ -5,7 +5,6 @@ import ( "encoding/json" "fmt" "io/ioutil" - "net/http" "net/url" "github.com/docker/docker/api/types" @@ -19,10 +18,7 @@ func (cli *Client) ServiceInspectWithRaw(ctx context.Context, serviceID string, query.Set("insertDefaults", fmt.Sprintf("%v", opts.InsertDefaults)) serverResp, err := cli.get(ctx, "/services/"+serviceID, query, nil) if err != nil { - if serverResp.statusCode == http.StatusNotFound { - return swarm.Service{}, nil, serviceNotFoundError{serviceID} - } - return swarm.Service{}, nil, err + return swarm.Service{}, nil, wrapResponseError(err, serverResp, "service", serviceID) } defer ensureReaderClosed(serverResp) diff --git a/client/service_remove.go b/client/service_remove.go index a9331f92c2..ad992c01d0 100644 --- a/client/service_remove.go +++ b/client/service_remove.go @@ -6,5 +6,5 @@ import "golang.org/x/net/context" func (cli *Client) ServiceRemove(ctx context.Context, serviceID string) error { resp, err := cli.delete(ctx, "/services/"+serviceID, nil, nil) ensureReaderClosed(resp) - return err + return wrapResponseError(err, resp, "service", serviceID) } diff --git a/client/service_remove_test.go b/client/service_remove_test.go index 8e2ac259c1..d7c51ef3dc 100644 --- a/client/service_remove_test.go +++ b/client/service_remove_test.go @@ -8,6 +8,7 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "golang.org/x/net/context" ) @@ -17,9 +18,17 @@ func TestServiceRemoveError(t *testing.T) { } err := client.ServiceRemove(context.Background(), "service_id") - if err == nil || err.Error() != "Error response from daemon: Server error" { - t.Fatalf("expected a Server Error, got %v", err) + assert.EqualError(t, err, "Error response from daemon: Server error") +} + +func TestServiceRemoveNotFoundError(t *testing.T) { + client := &Client{ + client: newMockClient(errorMock(http.StatusNotFound, "missing")), } + + err := client.ServiceRemove(context.Background(), "service_id") + assert.EqualError(t, err, "Error: No such service: service_id") + assert.True(t, IsErrNotFound(err)) } func TestServiceRemove(t *testing.T) { diff --git a/client/task_inspect.go b/client/task_inspect.go index bc8058fc32..dc08cedb96 100644 --- a/client/task_inspect.go +++ b/client/task_inspect.go @@ -4,10 +4,8 @@ import ( "bytes" "encoding/json" "io/ioutil" - "net/http" "github.com/docker/docker/api/types/swarm" - "golang.org/x/net/context" ) @@ -15,10 +13,7 @@ import ( func (cli *Client) TaskInspectWithRaw(ctx context.Context, taskID string) (swarm.Task, []byte, error) { serverResp, err := cli.get(ctx, "/tasks/"+taskID, nil, nil) if err != nil { - if serverResp.statusCode == http.StatusNotFound { - return swarm.Task{}, nil, taskNotFoundError{taskID} - } - return swarm.Task{}, nil, err + return swarm.Task{}, nil, wrapResponseError(err, serverResp, "task", taskID) } defer ensureReaderClosed(serverResp) diff --git a/client/volume_inspect.go b/client/volume_inspect.go index 4722d467ca..9889343849 100644 --- a/client/volume_inspect.go +++ b/client/volume_inspect.go @@ -4,7 +4,6 @@ import ( "bytes" "encoding/json" "io/ioutil" - "net/http" "path" "github.com/docker/docker/api/types" @@ -23,16 +22,13 @@ func (cli *Client) VolumeInspectWithRaw(ctx context.Context, volumeID string) (t // request url will not contain a trailing / which calls the volume list API // instead of volume inspect if volumeID == "" { - return types.Volume{}, nil, volumeNotFoundError{volumeID} + return types.Volume{}, nil, objectNotFoundError{object: "volume", id: volumeID} } var volume types.Volume resp, err := cli.get(ctx, path.Join("/volumes", volumeID), nil, nil) if err != nil { - if resp.statusCode == http.StatusNotFound { - return volume, nil, volumeNotFoundError{volumeID} - } - return volume, nil, err + return volume, nil, wrapResponseError(err, resp, "volume", volumeID) } defer ensureReaderClosed(resp) diff --git a/client/volume_remove.go b/client/volume_remove.go index 6c26575b49..3ffb8bcf2e 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) ensureReaderClosed(resp) - return err + return wrapResponseError(err, resp, "volume", volumeID) } diff --git a/integration-cli/docker_api_containers_test.go b/integration-cli/docker_api_containers_test.go index da9507267d..4a7e363d1c 100644 --- a/integration-cli/docker_api_containers_test.go +++ b/integration-cli/docker_api_containers_test.go @@ -1617,7 +1617,7 @@ func (s *DockerSuite) TestContainerAPIDeleteWithEmptyName(c *check.C) { defer cli.Close() err = cli.ContainerRemove(context.Background(), "", types.ContainerRemoveOptions{}) - c.Assert(err.Error(), checker.Contains, "Error response from daemon: page not found") + c.Assert(err.Error(), checker.Contains, "No such container") } func (s *DockerSuite) TestContainerAPIStatsWithNetworkDisabled(c *check.C) { diff --git a/integration-cli/docker_api_swarm_config_test.go b/integration-cli/docker_api_swarm_config_test.go index c06f3c45ea..c01d80ff7f 100644 --- a/integration-cli/docker_api_swarm_config_test.go +++ b/integration-cli/docker_api_swarm_config_test.go @@ -55,10 +55,8 @@ func (s *DockerSwarmSuite) TestAPISwarmConfigsDelete(c *check.C) { c.Assert(err, checker.IsNil) defer cli.Close() - expected := "no such config" - _, _, err = cli.ConfigInspectWithRaw(context.Background(), id) - c.Assert(err.Error(), checker.Contains, expected) + c.Assert(err.Error(), checker.Contains, "No such config") } func (s *DockerSwarmSuite) TestAPISwarmConfigsUpdate(c *check.C) { diff --git a/integration-cli/docker_api_swarm_secret_test.go b/integration-cli/docker_api_swarm_secret_test.go index db346dd283..c30e2237d8 100644 --- a/integration-cli/docker_api_swarm_secret_test.go +++ b/integration-cli/docker_api_swarm_secret_test.go @@ -64,14 +64,12 @@ func (s *DockerSwarmSuite) TestAPISwarmSecretsDelete(c *check.C) { c.Assert(err, checker.IsNil) defer cli.Close() - expected := "no such secret" _, _, err = cli.SecretInspectWithRaw(context.Background(), id) - c.Assert(err.Error(), checker.Contains, expected) + c.Assert(err.Error(), checker.Contains, "No such secret") id = "non-existing" - expected = "secret non-existing not found" err = cli.SecretRemove(context.Background(), id) - c.Assert(err.Error(), checker.Contains, expected) + c.Assert(err.Error(), checker.Contains, "No such secret: non-existing") } func (s *DockerSwarmSuite) TestAPISwarmSecretsUpdate(c *check.C) {