And fix remove calls to return a notFound error
Signed-off-by: Daniel Nephin <dnephin@docker.com>
| ... | ... |
@@ -2,7 +2,6 @@ package client |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 | 4 |
"encoding/json" |
| 5 |
- "net/http" |
|
| 6 | 5 |
"net/url" |
| 7 | 6 |
|
| 8 | 7 |
"github.com/docker/docker/api/types" |
| ... | ... |
@@ -20,10 +19,7 @@ func (cli *Client) CheckpointList(ctx context.Context, container string, options |
| 20 | 20 |
|
| 21 | 21 |
resp, err := cli.get(ctx, "/containers/"+container+"/checkpoints", query, nil) |
| 22 | 22 |
if err != nil {
|
| 23 |
- if resp.statusCode == http.StatusNotFound {
|
|
| 24 |
- return checkpoints, containerNotFoundError{container}
|
|
| 25 |
- } |
|
| 26 |
- return checkpoints, err |
|
| 23 |
+ return checkpoints, wrapResponseError(err, resp, "container", container) |
|
| 27 | 24 |
} |
| 28 | 25 |
|
| 29 | 26 |
err = json.NewDecoder(resp.body).Decode(&checkpoints) |
| ... | ... |
@@ -4,7 +4,6 @@ import ( |
| 4 | 4 |
"bytes" |
| 5 | 5 |
"encoding/json" |
| 6 | 6 |
"io/ioutil" |
| 7 |
- "net/http" |
|
| 8 | 7 |
|
| 9 | 8 |
"github.com/docker/docker/api/types/swarm" |
| 10 | 9 |
"golang.org/x/net/context" |
| ... | ... |
@@ -17,10 +16,7 @@ func (cli *Client) ConfigInspectWithRaw(ctx context.Context, id string) (swarm.C |
| 17 | 17 |
} |
| 18 | 18 |
resp, err := cli.get(ctx, "/configs/"+id, nil, nil) |
| 19 | 19 |
if err != nil {
|
| 20 |
- if resp.statusCode == http.StatusNotFound {
|
|
| 21 |
- return swarm.Config{}, nil, configNotFoundError{id}
|
|
| 22 |
- } |
|
| 23 |
- return swarm.Config{}, nil, err
|
|
| 20 |
+ return swarm.Config{}, nil, wrapResponseError(err, resp, "config", id)
|
|
| 24 | 21 |
} |
| 25 | 22 |
defer ensureReaderClosed(resp) |
| 26 | 23 |
|
| ... | ... |
@@ -45,7 +45,7 @@ func (cli *Client) ContainerCreate(ctx context.Context, config *container.Config |
| 45 | 45 |
serverResp, err := cli.post(ctx, "/containers/create", query, body, nil) |
| 46 | 46 |
if err != nil {
|
| 47 | 47 |
if serverResp.statusCode == 404 && strings.Contains(err.Error(), "No such image") {
|
| 48 |
- return response, imageNotFoundError{config.Image}
|
|
| 48 |
+ return response, objectNotFoundError{object: "image", id: config.Image}
|
|
| 49 | 49 |
} |
| 50 | 50 |
return response, err |
| 51 | 51 |
} |
| ... | ... |
@@ -4,7 +4,6 @@ import ( |
| 4 | 4 |
"bytes" |
| 5 | 5 |
"encoding/json" |
| 6 | 6 |
"io/ioutil" |
| 7 |
- "net/http" |
|
| 8 | 7 |
"net/url" |
| 9 | 8 |
|
| 10 | 9 |
"github.com/docker/docker/api/types" |
| ... | ... |
@@ -15,10 +14,7 @@ import ( |
| 15 | 15 |
func (cli *Client) ContainerInspect(ctx context.Context, containerID string) (types.ContainerJSON, error) {
|
| 16 | 16 |
serverResp, err := cli.get(ctx, "/containers/"+containerID+"/json", nil, nil) |
| 17 | 17 |
if err != nil {
|
| 18 |
- if serverResp.statusCode == http.StatusNotFound {
|
|
| 19 |
- return types.ContainerJSON{}, containerNotFoundError{containerID}
|
|
| 20 |
- } |
|
| 21 |
- return types.ContainerJSON{}, err
|
|
| 18 |
+ return types.ContainerJSON{}, wrapResponseError(err, serverResp, "container", containerID)
|
|
| 22 | 19 |
} |
| 23 | 20 |
|
| 24 | 21 |
var response types.ContainerJSON |
| ... | ... |
@@ -35,10 +31,7 @@ func (cli *Client) ContainerInspectWithRaw(ctx context.Context, containerID stri |
| 35 | 35 |
} |
| 36 | 36 |
serverResp, err := cli.get(ctx, "/containers/"+containerID+"/json", query, nil) |
| 37 | 37 |
if err != nil {
|
| 38 |
- if serverResp.statusCode == http.StatusNotFound {
|
|
| 39 |
- return types.ContainerJSON{}, nil, containerNotFoundError{containerID}
|
|
| 40 |
- } |
|
| 41 |
- return types.ContainerJSON{}, nil, err
|
|
| 38 |
+ return types.ContainerJSON{}, nil, wrapResponseError(err, serverResp, "container", containerID)
|
|
| 42 | 39 |
} |
| 43 | 40 |
defer ensureReaderClosed(serverResp) |
| 44 | 41 |
|
| ... | ... |
@@ -23,5 +23,5 @@ func (cli *Client) ContainerRemove(ctx context.Context, containerID string, opti |
| 23 | 23 |
|
| 24 | 24 |
resp, err := cli.delete(ctx, "/containers/"+containerID, query, nil) |
| 25 | 25 |
ensureReaderClosed(resp) |
| 26 |
- return err |
|
| 26 |
+ return wrapResponseError(err, resp, "container", containerID) |
|
| 27 | 27 |
} |
| ... | ... |
@@ -9,6 +9,7 @@ import ( |
| 9 | 9 |
"testing" |
| 10 | 10 |
|
| 11 | 11 |
"github.com/docker/docker/api/types" |
| 12 |
+ "github.com/stretchr/testify/assert" |
|
| 12 | 13 |
"golang.org/x/net/context" |
| 13 | 14 |
) |
| 14 | 15 |
|
| ... | ... |
@@ -17,9 +18,16 @@ func TestContainerRemoveError(t *testing.T) {
|
| 17 | 17 |
client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), |
| 18 | 18 |
} |
| 19 | 19 |
err := client.ContainerRemove(context.Background(), "container_id", types.ContainerRemoveOptions{})
|
| 20 |
- if err == nil || err.Error() != "Error response from daemon: Server error" {
|
|
| 21 |
- t.Fatalf("expected a Server Error, got %v", err)
|
|
| 20 |
+ assert.EqualError(t, err, "Error response from daemon: Server error") |
|
| 21 |
+} |
|
| 22 |
+ |
|
| 23 |
+func TestContainerRemoveNotFoundError(t *testing.T) {
|
|
| 24 |
+ client := &Client{
|
|
| 25 |
+ client: newMockClient(errorMock(http.StatusNotFound, "missing")), |
|
| 22 | 26 |
} |
| 27 |
+ err := client.ContainerRemove(context.Background(), "container_id", types.ContainerRemoveOptions{})
|
|
| 28 |
+ assert.EqualError(t, err, "Error: No such container: container_id") |
|
| 29 |
+ assert.True(t, IsErrNotFound(err)) |
|
| 23 | 30 |
} |
| 24 | 31 |
|
| 25 | 32 |
func TestContainerRemove(t *testing.T) {
|
| ... | ... |
@@ -53,7 +61,5 @@ func TestContainerRemove(t *testing.T) {
|
| 53 | 53 |
RemoveVolumes: true, |
| 54 | 54 |
Force: true, |
| 55 | 55 |
}) |
| 56 |
- if err != nil {
|
|
| 57 |
- t.Fatal(err) |
|
| 58 |
- } |
|
| 56 |
+ assert.NoError(t, err) |
|
| 59 | 57 |
} |
| ... | ... |
@@ -3,6 +3,8 @@ package client |
| 3 | 3 |
import ( |
| 4 | 4 |
"fmt" |
| 5 | 5 |
|
| 6 |
+ "net/http" |
|
| 7 |
+ |
|
| 6 | 8 |
"github.com/docker/docker/api/types/versions" |
| 7 | 9 |
"github.com/pkg/errors" |
| 8 | 10 |
) |
| ... | ... |
@@ -43,19 +45,28 @@ func IsErrNotFound(err error) bool {
|
| 43 | 43 |
return ok && te.NotFound() |
| 44 | 44 |
} |
| 45 | 45 |
|
| 46 |
-// imageNotFoundError implements an error returned when an image is not in the docker host. |
|
| 47 |
-type imageNotFoundError struct {
|
|
| 48 |
- imageID string |
|
| 46 |
+type objectNotFoundError struct {
|
|
| 47 |
+ object string |
|
| 48 |
+ id string |
|
| 49 | 49 |
} |
| 50 | 50 |
|
| 51 |
-// NotFound indicates that this error type is of NotFound |
|
| 52 |
-func (e imageNotFoundError) NotFound() bool {
|
|
| 51 |
+func (e objectNotFoundError) NotFound() bool {
|
|
| 53 | 52 |
return true |
| 54 | 53 |
} |
| 55 | 54 |
|
| 56 |
-// Error returns a string representation of an imageNotFoundError |
|
| 57 |
-func (e imageNotFoundError) Error() string {
|
|
| 58 |
- return fmt.Sprintf("Error: No such image: %s", e.imageID)
|
|
| 55 |
+func (e objectNotFoundError) Error() string {
|
|
| 56 |
+ return fmt.Sprintf("Error: No such %s: %s", e.object, e.id)
|
|
| 57 |
+} |
|
| 58 |
+ |
|
| 59 |
+func wrapResponseError(err error, resp serverResponse, object, id string) error {
|
|
| 60 |
+ switch {
|
|
| 61 |
+ case err == nil: |
|
| 62 |
+ return nil |
|
| 63 |
+ case resp.statusCode == http.StatusNotFound: |
|
| 64 |
+ return objectNotFoundError{object: object, id: id}
|
|
| 65 |
+ default: |
|
| 66 |
+ return err |
|
| 67 |
+ } |
|
| 59 | 68 |
} |
| 60 | 69 |
|
| 61 | 70 |
// IsErrImageNotFound returns true if the error is caused |
| ... | ... |
@@ -66,21 +77,6 @@ func IsErrImageNotFound(err error) bool {
|
| 66 | 66 |
return IsErrNotFound(err) |
| 67 | 67 |
} |
| 68 | 68 |
|
| 69 |
-// containerNotFoundError implements an error returned when a container is not in the docker host. |
|
| 70 |
-type containerNotFoundError struct {
|
|
| 71 |
- containerID string |
|
| 72 |
-} |
|
| 73 |
- |
|
| 74 |
-// NotFound indicates that this error type is of NotFound |
|
| 75 |
-func (e containerNotFoundError) NotFound() bool {
|
|
| 76 |
- return true |
|
| 77 |
-} |
|
| 78 |
- |
|
| 79 |
-// Error returns a string representation of a containerNotFoundError |
|
| 80 |
-func (e containerNotFoundError) Error() string {
|
|
| 81 |
- return fmt.Sprintf("Error: No such container: %s", e.containerID)
|
|
| 82 |
-} |
|
| 83 |
- |
|
| 84 | 69 |
// IsErrContainerNotFound returns true if the error is caused |
| 85 | 70 |
// when a container is not found in the docker host. |
| 86 | 71 |
// |
| ... | ... |
@@ -89,21 +85,6 @@ func IsErrContainerNotFound(err error) bool {
|
| 89 | 89 |
return IsErrNotFound(err) |
| 90 | 90 |
} |
| 91 | 91 |
|
| 92 |
-// networkNotFoundError implements an error returned when a network is not in the docker host. |
|
| 93 |
-type networkNotFoundError struct {
|
|
| 94 |
- networkID string |
|
| 95 |
-} |
|
| 96 |
- |
|
| 97 |
-// NotFound indicates that this error type is of NotFound |
|
| 98 |
-func (e networkNotFoundError) NotFound() bool {
|
|
| 99 |
- return true |
|
| 100 |
-} |
|
| 101 |
- |
|
| 102 |
-// Error returns a string representation of a networkNotFoundError |
|
| 103 |
-func (e networkNotFoundError) Error() string {
|
|
| 104 |
- return fmt.Sprintf("Error: No such network: %s", e.networkID)
|
|
| 105 |
-} |
|
| 106 |
- |
|
| 107 | 92 |
// IsErrNetworkNotFound returns true if the error is caused |
| 108 | 93 |
// when a network is not found in the docker host. |
| 109 | 94 |
// |
| ... | ... |
@@ -112,21 +93,6 @@ func IsErrNetworkNotFound(err error) bool {
|
| 112 | 112 |
return IsErrNotFound(err) |
| 113 | 113 |
} |
| 114 | 114 |
|
| 115 |
-// volumeNotFoundError implements an error returned when a volume is not in the docker host. |
|
| 116 |
-type volumeNotFoundError struct {
|
|
| 117 |
- volumeID string |
|
| 118 |
-} |
|
| 119 |
- |
|
| 120 |
-// NotFound indicates that this error type is of NotFound |
|
| 121 |
-func (e volumeNotFoundError) NotFound() bool {
|
|
| 122 |
- return true |
|
| 123 |
-} |
|
| 124 |
- |
|
| 125 |
-// Error returns a string representation of a volumeNotFoundError |
|
| 126 |
-func (e volumeNotFoundError) Error() string {
|
|
| 127 |
- return fmt.Sprintf("Error: No such volume: %s", e.volumeID)
|
|
| 128 |
-} |
|
| 129 |
- |
|
| 130 | 115 |
// IsErrVolumeNotFound returns true if the error is caused |
| 131 | 116 |
// when a volume is not found in the docker host. |
| 132 | 117 |
// |
| ... | ... |
@@ -152,43 +118,12 @@ func IsErrUnauthorized(err error) bool {
|
| 152 | 152 |
return ok |
| 153 | 153 |
} |
| 154 | 154 |
|
| 155 |
-// nodeNotFoundError implements an error returned when a node is not found. |
|
| 156 |
-type nodeNotFoundError struct {
|
|
| 157 |
- nodeID string |
|
| 158 |
-} |
|
| 159 |
- |
|
| 160 |
-// Error returns a string representation of a nodeNotFoundError |
|
| 161 |
-func (e nodeNotFoundError) Error() string {
|
|
| 162 |
- return fmt.Sprintf("Error: No such node: %s", e.nodeID)
|
|
| 163 |
-} |
|
| 164 |
- |
|
| 165 |
-// NotFound indicates that this error type is of NotFound |
|
| 166 |
-func (e nodeNotFoundError) NotFound() bool {
|
|
| 167 |
- return true |
|
| 168 |
-} |
|
| 169 |
- |
|
| 170 | 155 |
// IsErrNodeNotFound returns true if the error is caused |
| 171 | 156 |
// when a node is not found. |
| 172 | 157 |
// |
| 173 | 158 |
// Deprecated: Use IsErrNotFound |
| 174 | 159 |
func IsErrNodeNotFound(err error) bool {
|
| 175 |
- _, ok := err.(nodeNotFoundError) |
|
| 176 |
- return ok |
|
| 177 |
-} |
|
| 178 |
- |
|
| 179 |
-// serviceNotFoundError implements an error returned when a service is not found. |
|
| 180 |
-type serviceNotFoundError struct {
|
|
| 181 |
- serviceID string |
|
| 182 |
-} |
|
| 183 |
- |
|
| 184 |
-// Error returns a string representation of a serviceNotFoundError |
|
| 185 |
-func (e serviceNotFoundError) Error() string {
|
|
| 186 |
- return fmt.Sprintf("Error: No such service: %s", e.serviceID)
|
|
| 187 |
-} |
|
| 188 |
- |
|
| 189 |
-// NotFound indicates that this error type is of NotFound |
|
| 190 |
-func (e serviceNotFoundError) NotFound() bool {
|
|
| 191 |
- return true |
|
| 160 |
+ return IsErrNotFound(err) |
|
| 192 | 161 |
} |
| 193 | 162 |
|
| 194 | 163 |
// IsErrServiceNotFound returns true if the error is caused |
| ... | ... |
@@ -196,23 +131,7 @@ func (e serviceNotFoundError) NotFound() bool {
|
| 196 | 196 |
// |
| 197 | 197 |
// Deprecated: Use IsErrNotFound |
| 198 | 198 |
func IsErrServiceNotFound(err error) bool {
|
| 199 |
- _, ok := err.(serviceNotFoundError) |
|
| 200 |
- return ok |
|
| 201 |
-} |
|
| 202 |
- |
|
| 203 |
-// taskNotFoundError implements an error returned when a task is not found. |
|
| 204 |
-type taskNotFoundError struct {
|
|
| 205 |
- taskID string |
|
| 206 |
-} |
|
| 207 |
- |
|
| 208 |
-// Error returns a string representation of a taskNotFoundError |
|
| 209 |
-func (e taskNotFoundError) Error() string {
|
|
| 210 |
- return fmt.Sprintf("Error: No such task: %s", e.taskID)
|
|
| 211 |
-} |
|
| 212 |
- |
|
| 213 |
-// NotFound indicates that this error type is of NotFound |
|
| 214 |
-func (e taskNotFoundError) NotFound() bool {
|
|
| 215 |
- return true |
|
| 199 |
+ return IsErrNotFound(err) |
|
| 216 | 200 |
} |
| 217 | 201 |
|
| 218 | 202 |
// IsErrTaskNotFound returns true if the error is caused |
| ... | ... |
@@ -220,8 +139,7 @@ func (e taskNotFoundError) NotFound() bool {
|
| 220 | 220 |
// |
| 221 | 221 |
// Deprecated: Use IsErrNotFound |
| 222 | 222 |
func IsErrTaskNotFound(err error) bool {
|
| 223 |
- _, ok := err.(taskNotFoundError) |
|
| 224 |
- return ok |
|
| 223 |
+ return IsErrNotFound(err) |
|
| 225 | 224 |
} |
| 226 | 225 |
|
| 227 | 226 |
type pluginPermissionDenied struct {
|
| ... | ... |
@@ -248,43 +166,12 @@ func (cli *Client) NewVersionError(APIrequired, feature string) error {
|
| 248 | 248 |
return nil |
| 249 | 249 |
} |
| 250 | 250 |
|
| 251 |
-// secretNotFoundError implements an error returned when a secret is not found. |
|
| 252 |
-type secretNotFoundError struct {
|
|
| 253 |
- name string |
|
| 254 |
-} |
|
| 255 |
- |
|
| 256 |
-// Error returns a string representation of a secretNotFoundError |
|
| 257 |
-func (e secretNotFoundError) Error() string {
|
|
| 258 |
- return fmt.Sprintf("Error: no such secret: %s", e.name)
|
|
| 259 |
-} |
|
| 260 |
- |
|
| 261 |
-// NotFound indicates that this error type is of NotFound |
|
| 262 |
-func (e secretNotFoundError) NotFound() bool {
|
|
| 263 |
- return true |
|
| 264 |
-} |
|
| 265 |
- |
|
| 266 | 251 |
// IsErrSecretNotFound returns true if the error is caused |
| 267 | 252 |
// when a secret is not found. |
| 268 | 253 |
// |
| 269 | 254 |
// Deprecated: Use IsErrNotFound |
| 270 | 255 |
func IsErrSecretNotFound(err error) bool {
|
| 271 |
- _, ok := err.(secretNotFoundError) |
|
| 272 |
- return ok |
|
| 273 |
-} |
|
| 274 |
- |
|
| 275 |
-// configNotFoundError implements an error returned when a config is not found. |
|
| 276 |
-type configNotFoundError struct {
|
|
| 277 |
- name string |
|
| 278 |
-} |
|
| 279 |
- |
|
| 280 |
-// Error returns a string representation of a configNotFoundError |
|
| 281 |
-func (e configNotFoundError) Error() string {
|
|
| 282 |
- return fmt.Sprintf("Error: no such config: %s", e.name)
|
|
| 283 |
-} |
|
| 284 |
- |
|
| 285 |
-// NotFound indicates that this error type is of NotFound |
|
| 286 |
-func (e configNotFoundError) NotFound() bool {
|
|
| 287 |
- return true |
|
| 256 |
+ return IsErrNotFound(err) |
|
| 288 | 257 |
} |
| 289 | 258 |
|
| 290 | 259 |
// IsErrConfigNotFound returns true if the error is caused |
| ... | ... |
@@ -292,23 +179,7 @@ func (e configNotFoundError) NotFound() bool {
|
| 292 | 292 |
// |
| 293 | 293 |
// Deprecated: Use IsErrNotFound |
| 294 | 294 |
func IsErrConfigNotFound(err error) bool {
|
| 295 |
- _, ok := err.(configNotFoundError) |
|
| 296 |
- return ok |
|
| 297 |
-} |
|
| 298 |
- |
|
| 299 |
-// pluginNotFoundError implements an error returned when a plugin is not in the docker host. |
|
| 300 |
-type pluginNotFoundError struct {
|
|
| 301 |
- name string |
|
| 302 |
-} |
|
| 303 |
- |
|
| 304 |
-// NotFound indicates that this error type is of NotFound |
|
| 305 |
-func (e pluginNotFoundError) NotFound() bool {
|
|
| 306 |
- return true |
|
| 307 |
-} |
|
| 308 |
- |
|
| 309 |
-// Error returns a string representation of a pluginNotFoundError |
|
| 310 |
-func (e pluginNotFoundError) Error() string {
|
|
| 311 |
- return fmt.Sprintf("Error: No such plugin: %s", e.name)
|
|
| 295 |
+ return IsErrNotFound(err) |
|
| 312 | 296 |
} |
| 313 | 297 |
|
| 314 | 298 |
// IsErrPluginNotFound returns true if the error is caused |
| ... | ... |
@@ -4,7 +4,6 @@ import ( |
| 4 | 4 |
"bytes" |
| 5 | 5 |
"encoding/json" |
| 6 | 6 |
"io/ioutil" |
| 7 |
- "net/http" |
|
| 8 | 7 |
|
| 9 | 8 |
"github.com/docker/docker/api/types" |
| 10 | 9 |
"golang.org/x/net/context" |
| ... | ... |
@@ -14,10 +13,7 @@ import ( |
| 14 | 14 |
func (cli *Client) ImageInspectWithRaw(ctx context.Context, imageID string) (types.ImageInspect, []byte, error) {
|
| 15 | 15 |
serverResp, err := cli.get(ctx, "/images/"+imageID+"/json", nil, nil) |
| 16 | 16 |
if err != nil {
|
| 17 |
- if serverResp.statusCode == http.StatusNotFound {
|
|
| 18 |
- return types.ImageInspect{}, nil, imageNotFoundError{imageID}
|
|
| 19 |
- } |
|
| 20 |
- return types.ImageInspect{}, nil, err
|
|
| 17 |
+ return types.ImageInspect{}, nil, wrapResponseError(err, serverResp, "image", imageID)
|
|
| 21 | 18 |
} |
| 22 | 19 |
defer ensureReaderClosed(serverResp) |
| 23 | 20 |
|
| ... | ... |
@@ -2,7 +2,6 @@ package client |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 | 4 |
"encoding/json" |
| 5 |
- "net/http" |
|
| 6 | 5 |
"net/url" |
| 7 | 6 |
|
| 8 | 7 |
"github.com/docker/docker/api/types" |
| ... | ... |
@@ -20,15 +19,12 @@ func (cli *Client) ImageRemove(ctx context.Context, imageID string, options type |
| 20 | 20 |
query.Set("noprune", "1")
|
| 21 | 21 |
} |
| 22 | 22 |
|
| 23 |
+ var dels []types.ImageDeleteResponseItem |
|
| 23 | 24 |
resp, err := cli.delete(ctx, "/images/"+imageID, query, nil) |
| 24 | 25 |
if err != nil {
|
| 25 |
- if resp.statusCode == http.StatusNotFound {
|
|
| 26 |
- return nil, imageNotFoundError{imageID}
|
|
| 27 |
- } |
|
| 28 |
- return nil, err |
|
| 26 |
+ return dels, wrapResponseError(err, resp, "image", imageID) |
|
| 29 | 27 |
} |
| 30 | 28 |
|
| 31 |
- var dels []types.ImageDeleteResponseItem |
|
| 32 | 29 |
err = json.NewDecoder(resp.body).Decode(&dels) |
| 33 | 30 |
ensureReaderClosed(resp) |
| 34 | 31 |
return dels, err |
| ... | ... |
@@ -10,6 +10,7 @@ import ( |
| 10 | 10 |
"testing" |
| 11 | 11 |
|
| 12 | 12 |
"github.com/docker/docker/api/types" |
| 13 |
+ "github.com/stretchr/testify/assert" |
|
| 13 | 14 |
"golang.org/x/net/context" |
| 14 | 15 |
) |
| 15 | 16 |
|
| ... | ... |
@@ -19,20 +20,17 @@ func TestImageRemoveError(t *testing.T) {
|
| 19 | 19 |
} |
| 20 | 20 |
|
| 21 | 21 |
_, err := client.ImageRemove(context.Background(), "image_id", types.ImageRemoveOptions{})
|
| 22 |
- if err == nil || err.Error() != "Error response from daemon: Server error" {
|
|
| 23 |
- t.Fatalf("expected a Server Error, got %v", err)
|
|
| 24 |
- } |
|
| 22 |
+ assert.EqualError(t, err, "Error response from daemon: Server error") |
|
| 25 | 23 |
} |
| 26 | 24 |
|
| 27 | 25 |
func TestImageRemoveImageNotFound(t *testing.T) {
|
| 28 | 26 |
client := &Client{
|
| 29 |
- client: newMockClient(errorMock(http.StatusNotFound, "Server error")), |
|
| 27 |
+ client: newMockClient(errorMock(http.StatusNotFound, "missing")), |
|
| 30 | 28 |
} |
| 31 | 29 |
|
| 32 | 30 |
_, err := client.ImageRemove(context.Background(), "unknown", types.ImageRemoveOptions{})
|
| 33 |
- if err == nil || !IsErrNotFound(err) {
|
|
| 34 |
- t.Fatalf("expected an imageNotFoundError error, got %v", err)
|
|
| 35 |
- } |
|
| 31 |
+ assert.EqualError(t, err, "Error: No such image: unknown") |
|
| 32 |
+ assert.True(t, IsErrNotFound(err)) |
|
| 36 | 33 |
} |
| 37 | 34 |
|
| 38 | 35 |
func TestImageRemove(t *testing.T) {
|
| ... | ... |
@@ -4,7 +4,6 @@ import ( |
| 4 | 4 |
"bytes" |
| 5 | 5 |
"encoding/json" |
| 6 | 6 |
"io/ioutil" |
| 7 |
- "net/http" |
|
| 8 | 7 |
"net/url" |
| 9 | 8 |
|
| 10 | 9 |
"github.com/docker/docker/api/types" |
| ... | ... |
@@ -33,10 +32,7 @@ func (cli *Client) NetworkInspectWithRaw(ctx context.Context, networkID string, |
| 33 | 33 |
} |
| 34 | 34 |
resp, err = cli.get(ctx, "/networks/"+networkID, query, nil) |
| 35 | 35 |
if err != nil {
|
| 36 |
- if resp.statusCode == http.StatusNotFound {
|
|
| 37 |
- return networkResource, nil, networkNotFoundError{networkID}
|
|
| 38 |
- } |
|
| 39 |
- return networkResource, nil, err |
|
| 36 |
+ return networkResource, nil, wrapResponseError(err, resp, "network", networkID) |
|
| 40 | 37 |
} |
| 41 | 38 |
defer ensureReaderClosed(resp) |
| 42 | 39 |
|
| ... | ... |
@@ -21,20 +21,17 @@ func TestNetworkInspectError(t *testing.T) {
|
| 21 | 21 |
} |
| 22 | 22 |
|
| 23 | 23 |
_, err := client.NetworkInspect(context.Background(), "nothing", types.NetworkInspectOptions{})
|
| 24 |
- if err == nil || err.Error() != "Error response from daemon: Server error" {
|
|
| 25 |
- t.Fatalf("expected a Server Error, got %v", err)
|
|
| 26 |
- } |
|
| 24 |
+ assert.EqualError(t, err, "Error response from daemon: Server error") |
|
| 27 | 25 |
} |
| 28 | 26 |
|
| 29 |
-func TestNetworkInspectContainerNotFound(t *testing.T) {
|
|
| 27 |
+func TestNetworkInspectNotFoundError(t *testing.T) {
|
|
| 30 | 28 |
client := &Client{
|
| 31 |
- client: newMockClient(errorMock(http.StatusNotFound, "Server error")), |
|
| 29 |
+ client: newMockClient(errorMock(http.StatusNotFound, "missing")), |
|
| 32 | 30 |
} |
| 33 | 31 |
|
| 34 | 32 |
_, err := client.NetworkInspect(context.Background(), "unknown", types.NetworkInspectOptions{})
|
| 35 |
- if err == nil || !IsErrNetworkNotFound(err) {
|
|
| 36 |
- t.Fatalf("expected a networkNotFound error, got %v", err)
|
|
| 37 |
- } |
|
| 33 |
+ assert.EqualError(t, err, "Error: No such network: unknown") |
|
| 34 |
+ assert.True(t, IsErrNotFound(err)) |
|
| 38 | 35 |
} |
| 39 | 36 |
|
| 40 | 37 |
func TestNetworkInspect(t *testing.T) {
|
| ... | ... |
@@ -6,5 +6,5 @@ import "golang.org/x/net/context" |
| 6 | 6 |
func (cli *Client) NetworkRemove(ctx context.Context, networkID string) error {
|
| 7 | 7 |
resp, err := cli.delete(ctx, "/networks/"+networkID, nil, nil) |
| 8 | 8 |
ensureReaderClosed(resp) |
| 9 |
- return err |
|
| 9 |
+ return wrapResponseError(err, resp, "network", networkID) |
|
| 10 | 10 |
} |
| ... | ... |
@@ -4,7 +4,6 @@ import ( |
| 4 | 4 |
"bytes" |
| 5 | 5 |
"encoding/json" |
| 6 | 6 |
"io/ioutil" |
| 7 |
- "net/http" |
|
| 8 | 7 |
|
| 9 | 8 |
"github.com/docker/docker/api/types/swarm" |
| 10 | 9 |
"golang.org/x/net/context" |
| ... | ... |
@@ -14,10 +13,7 @@ import ( |
| 14 | 14 |
func (cli *Client) NodeInspectWithRaw(ctx context.Context, nodeID string) (swarm.Node, []byte, error) {
|
| 15 | 15 |
serverResp, err := cli.get(ctx, "/nodes/"+nodeID, nil, nil) |
| 16 | 16 |
if err != nil {
|
| 17 |
- if serverResp.statusCode == http.StatusNotFound {
|
|
| 18 |
- return swarm.Node{}, nil, nodeNotFoundError{nodeID}
|
|
| 19 |
- } |
|
| 20 |
- return swarm.Node{}, nil, err
|
|
| 17 |
+ return swarm.Node{}, nil, wrapResponseError(err, serverResp, "node", nodeID)
|
|
| 21 | 18 |
} |
| 22 | 19 |
defer ensureReaderClosed(serverResp) |
| 23 | 20 |
|
| ... | ... |
@@ -4,7 +4,6 @@ import ( |
| 4 | 4 |
"bytes" |
| 5 | 5 |
"encoding/json" |
| 6 | 6 |
"io/ioutil" |
| 7 |
- "net/http" |
|
| 8 | 7 |
|
| 9 | 8 |
"github.com/docker/docker/api/types" |
| 10 | 9 |
"golang.org/x/net/context" |
| ... | ... |
@@ -14,10 +13,7 @@ import ( |
| 14 | 14 |
func (cli *Client) PluginInspectWithRaw(ctx context.Context, name string) (*types.Plugin, []byte, error) {
|
| 15 | 15 |
resp, err := cli.get(ctx, "/plugins/"+name+"/json", nil, nil) |
| 16 | 16 |
if err != nil {
|
| 17 |
- if resp.statusCode == http.StatusNotFound {
|
|
| 18 |
- return nil, nil, pluginNotFoundError{name}
|
|
| 19 |
- } |
|
| 20 |
- return nil, nil, err |
|
| 17 |
+ return nil, nil, wrapResponseError(err, resp, "plugin", name) |
|
| 21 | 18 |
} |
| 22 | 19 |
|
| 23 | 20 |
defer ensureReaderClosed(resp) |
| ... | ... |
@@ -203,7 +203,7 @@ func (cli *Client) checkResponseErr(serverResp serverResponse) error {
|
| 203 | 203 |
return err |
| 204 | 204 |
} |
| 205 | 205 |
if len(body) == 0 {
|
| 206 |
- 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)
|
|
| 206 |
+ 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)
|
|
| 207 | 207 |
} |
| 208 | 208 |
|
| 209 | 209 |
var ct string |
| ... | ... |
@@ -4,7 +4,6 @@ import ( |
| 4 | 4 |
"bytes" |
| 5 | 5 |
"encoding/json" |
| 6 | 6 |
"io/ioutil" |
| 7 |
- "net/http" |
|
| 8 | 7 |
|
| 9 | 8 |
"github.com/docker/docker/api/types/swarm" |
| 10 | 9 |
"golang.org/x/net/context" |
| ... | ... |
@@ -17,10 +16,7 @@ func (cli *Client) SecretInspectWithRaw(ctx context.Context, id string) (swarm.S |
| 17 | 17 |
} |
| 18 | 18 |
resp, err := cli.get(ctx, "/secrets/"+id, nil, nil) |
| 19 | 19 |
if err != nil {
|
| 20 |
- if resp.statusCode == http.StatusNotFound {
|
|
| 21 |
- return swarm.Secret{}, nil, secretNotFoundError{id}
|
|
| 22 |
- } |
|
| 23 |
- return swarm.Secret{}, nil, err
|
|
| 20 |
+ return swarm.Secret{}, nil, wrapResponseError(err, resp, "secret", id)
|
|
| 24 | 21 |
} |
| 25 | 22 |
defer ensureReaderClosed(resp) |
| 26 | 23 |
|
| ... | ... |
@@ -5,7 +5,6 @@ import ( |
| 5 | 5 |
"encoding/json" |
| 6 | 6 |
"fmt" |
| 7 | 7 |
"io/ioutil" |
| 8 |
- "net/http" |
|
| 9 | 8 |
"net/url" |
| 10 | 9 |
|
| 11 | 10 |
"github.com/docker/docker/api/types" |
| ... | ... |
@@ -19,10 +18,7 @@ func (cli *Client) ServiceInspectWithRaw(ctx context.Context, serviceID string, |
| 19 | 19 |
query.Set("insertDefaults", fmt.Sprintf("%v", opts.InsertDefaults))
|
| 20 | 20 |
serverResp, err := cli.get(ctx, "/services/"+serviceID, query, nil) |
| 21 | 21 |
if err != nil {
|
| 22 |
- if serverResp.statusCode == http.StatusNotFound {
|
|
| 23 |
- return swarm.Service{}, nil, serviceNotFoundError{serviceID}
|
|
| 24 |
- } |
|
| 25 |
- return swarm.Service{}, nil, err
|
|
| 22 |
+ return swarm.Service{}, nil, wrapResponseError(err, serverResp, "service", serviceID)
|
|
| 26 | 23 |
} |
| 27 | 24 |
defer ensureReaderClosed(serverResp) |
| 28 | 25 |
|
| ... | ... |
@@ -6,5 +6,5 @@ import "golang.org/x/net/context" |
| 6 | 6 |
func (cli *Client) ServiceRemove(ctx context.Context, serviceID string) error {
|
| 7 | 7 |
resp, err := cli.delete(ctx, "/services/"+serviceID, nil, nil) |
| 8 | 8 |
ensureReaderClosed(resp) |
| 9 |
- return err |
|
| 9 |
+ return wrapResponseError(err, resp, "service", serviceID) |
|
| 10 | 10 |
} |
| ... | ... |
@@ -8,6 +8,7 @@ import ( |
| 8 | 8 |
"strings" |
| 9 | 9 |
"testing" |
| 10 | 10 |
|
| 11 |
+ "github.com/stretchr/testify/assert" |
|
| 11 | 12 |
"golang.org/x/net/context" |
| 12 | 13 |
) |
| 13 | 14 |
|
| ... | ... |
@@ -17,9 +18,17 @@ func TestServiceRemoveError(t *testing.T) {
|
| 17 | 17 |
} |
| 18 | 18 |
|
| 19 | 19 |
err := client.ServiceRemove(context.Background(), "service_id") |
| 20 |
- if err == nil || err.Error() != "Error response from daemon: Server error" {
|
|
| 21 |
- t.Fatalf("expected a Server Error, got %v", err)
|
|
| 20 |
+ assert.EqualError(t, err, "Error response from daemon: Server error") |
|
| 21 |
+} |
|
| 22 |
+ |
|
| 23 |
+func TestServiceRemoveNotFoundError(t *testing.T) {
|
|
| 24 |
+ client := &Client{
|
|
| 25 |
+ client: newMockClient(errorMock(http.StatusNotFound, "missing")), |
|
| 22 | 26 |
} |
| 27 |
+ |
|
| 28 |
+ err := client.ServiceRemove(context.Background(), "service_id") |
|
| 29 |
+ assert.EqualError(t, err, "Error: No such service: service_id") |
|
| 30 |
+ assert.True(t, IsErrNotFound(err)) |
|
| 23 | 31 |
} |
| 24 | 32 |
|
| 25 | 33 |
func TestServiceRemove(t *testing.T) {
|
| ... | ... |
@@ -4,10 +4,8 @@ import ( |
| 4 | 4 |
"bytes" |
| 5 | 5 |
"encoding/json" |
| 6 | 6 |
"io/ioutil" |
| 7 |
- "net/http" |
|
| 8 | 7 |
|
| 9 | 8 |
"github.com/docker/docker/api/types/swarm" |
| 10 |
- |
|
| 11 | 9 |
"golang.org/x/net/context" |
| 12 | 10 |
) |
| 13 | 11 |
|
| ... | ... |
@@ -15,10 +13,7 @@ import ( |
| 15 | 15 |
func (cli *Client) TaskInspectWithRaw(ctx context.Context, taskID string) (swarm.Task, []byte, error) {
|
| 16 | 16 |
serverResp, err := cli.get(ctx, "/tasks/"+taskID, nil, nil) |
| 17 | 17 |
if err != nil {
|
| 18 |
- if serverResp.statusCode == http.StatusNotFound {
|
|
| 19 |
- return swarm.Task{}, nil, taskNotFoundError{taskID}
|
|
| 20 |
- } |
|
| 21 |
- return swarm.Task{}, nil, err
|
|
| 18 |
+ return swarm.Task{}, nil, wrapResponseError(err, serverResp, "task", taskID)
|
|
| 22 | 19 |
} |
| 23 | 20 |
defer ensureReaderClosed(serverResp) |
| 24 | 21 |
|
| ... | ... |
@@ -4,7 +4,6 @@ import ( |
| 4 | 4 |
"bytes" |
| 5 | 5 |
"encoding/json" |
| 6 | 6 |
"io/ioutil" |
| 7 |
- "net/http" |
|
| 8 | 7 |
"path" |
| 9 | 8 |
|
| 10 | 9 |
"github.com/docker/docker/api/types" |
| ... | ... |
@@ -23,16 +22,13 @@ func (cli *Client) VolumeInspectWithRaw(ctx context.Context, volumeID string) (t |
| 23 | 23 |
// request url will not contain a trailing / which calls the volume list API |
| 24 | 24 |
// instead of volume inspect |
| 25 | 25 |
if volumeID == "" {
|
| 26 |
- return types.Volume{}, nil, volumeNotFoundError{volumeID}
|
|
| 26 |
+ return types.Volume{}, nil, objectNotFoundError{object: "volume", id: volumeID}
|
|
| 27 | 27 |
} |
| 28 | 28 |
|
| 29 | 29 |
var volume types.Volume |
| 30 | 30 |
resp, err := cli.get(ctx, path.Join("/volumes", volumeID), nil, nil)
|
| 31 | 31 |
if err != nil {
|
| 32 |
- if resp.statusCode == http.StatusNotFound {
|
|
| 33 |
- return volume, nil, volumeNotFoundError{volumeID}
|
|
| 34 |
- } |
|
| 35 |
- return volume, nil, err |
|
| 32 |
+ return volume, nil, wrapResponseError(err, resp, "volume", volumeID) |
|
| 36 | 33 |
} |
| 37 | 34 |
defer ensureReaderClosed(resp) |
| 38 | 35 |
|
| ... | ... |
@@ -1617,7 +1617,7 @@ func (s *DockerSuite) TestContainerAPIDeleteWithEmptyName(c *check.C) {
|
| 1617 | 1617 |
defer cli.Close() |
| 1618 | 1618 |
|
| 1619 | 1619 |
err = cli.ContainerRemove(context.Background(), "", types.ContainerRemoveOptions{})
|
| 1620 |
- c.Assert(err.Error(), checker.Contains, "Error response from daemon: page not found") |
|
| 1620 |
+ c.Assert(err.Error(), checker.Contains, "No such container") |
|
| 1621 | 1621 |
} |
| 1622 | 1622 |
|
| 1623 | 1623 |
func (s *DockerSuite) TestContainerAPIStatsWithNetworkDisabled(c *check.C) {
|
| ... | ... |
@@ -55,10 +55,8 @@ func (s *DockerSwarmSuite) TestAPISwarmConfigsDelete(c *check.C) {
|
| 55 | 55 |
c.Assert(err, checker.IsNil) |
| 56 | 56 |
defer cli.Close() |
| 57 | 57 |
|
| 58 |
- expected := "no such config" |
|
| 59 |
- |
|
| 60 | 58 |
_, _, err = cli.ConfigInspectWithRaw(context.Background(), id) |
| 61 |
- c.Assert(err.Error(), checker.Contains, expected) |
|
| 59 |
+ c.Assert(err.Error(), checker.Contains, "No such config") |
|
| 62 | 60 |
} |
| 63 | 61 |
|
| 64 | 62 |
func (s *DockerSwarmSuite) TestAPISwarmConfigsUpdate(c *check.C) {
|
| ... | ... |
@@ -64,14 +64,12 @@ func (s *DockerSwarmSuite) TestAPISwarmSecretsDelete(c *check.C) {
|
| 64 | 64 |
c.Assert(err, checker.IsNil) |
| 65 | 65 |
defer cli.Close() |
| 66 | 66 |
|
| 67 |
- expected := "no such secret" |
|
| 68 | 67 |
_, _, err = cli.SecretInspectWithRaw(context.Background(), id) |
| 69 |
- c.Assert(err.Error(), checker.Contains, expected) |
|
| 68 |
+ c.Assert(err.Error(), checker.Contains, "No such secret") |
|
| 70 | 69 |
|
| 71 | 70 |
id = "non-existing" |
| 72 |
- expected = "secret non-existing not found" |
|
| 73 | 71 |
err = cli.SecretRemove(context.Background(), id) |
| 74 |
- c.Assert(err.Error(), checker.Contains, expected) |
|
| 72 |
+ c.Assert(err.Error(), checker.Contains, "No such secret: non-existing") |
|
| 75 | 73 |
} |
| 76 | 74 |
|
| 77 | 75 |
func (s *DockerSwarmSuite) TestAPISwarmSecretsUpdate(c *check.C) {
|