Browse code

Merge pull request #35638 from cpuguy83/error_helpers2

Add helpers to create errdef errors

Yong Tang authored on 2018/01/16 03:56:46
Showing 75 changed files
1 1
deleted file mode 100644
... ...
@@ -1,54 +0,0 @@
1
-package errdefs
2
-
3
-// ErrNotFound signals that the requested object doesn't exist
4
-type ErrNotFound interface {
5
-	NotFound()
6
-}
7
-
8
-// ErrInvalidParameter signals that the user input is invalid
9
-type ErrInvalidParameter interface {
10
-	InvalidParameter()
11
-}
12
-
13
-// ErrConflict signals that some internal state conflicts with the requested action and can't be performed.
14
-// A change in state should be able to clear this error.
15
-type ErrConflict interface {
16
-	Conflict()
17
-}
18
-
19
-// ErrUnauthorized is used to signify that the user is not authorized to perform a specific action
20
-type ErrUnauthorized interface {
21
-	Unauthorized()
22
-}
23
-
24
-// ErrUnavailable signals that the requested action/subsystem is not available.
25
-type ErrUnavailable interface {
26
-	Unavailable()
27
-}
28
-
29
-// ErrForbidden signals that the requested action cannot be performed under any circumstances.
30
-// When a ErrForbidden is returned, the caller should never retry the action.
31
-type ErrForbidden interface {
32
-	Forbidden()
33
-}
34
-
35
-// ErrSystem signals that some internal error occurred.
36
-// An example of this would be a failed mount request.
37
-type ErrSystem interface {
38
-	ErrSystem()
39
-}
40
-
41
-// ErrNotModified signals that an action can't be performed because it's already in the desired state
42
-type ErrNotModified interface {
43
-	NotModified()
44
-}
45
-
46
-// ErrNotImplemented signals that the requested action/feature is not implemented on the system as configured.
47
-type ErrNotImplemented interface {
48
-	NotImplemented()
49
-}
50
-
51
-// ErrUnknown signals that the kind of error that occurred is not known.
52
-type ErrUnknown interface {
53
-	Unknown()
54
-}
55 1
deleted file mode 100644
... ...
@@ -1,8 +0,0 @@
1
-// Package errdefs defines a set of error interfaces that packages should use for communicating classes of errors.
2
-// Errors that cross the package boundary should implement one (and only one) of these interfaces.
3
-//
4
-// Packages should not reference these interfaces directly, only implement them.
5
-// To check if a particular error implements one of these interfaces, there are helper
6
-// functions provided (e.g. `Is<SomeError>`) which can be used rather than asserting the interfaces directly.
7
-// If you must assert on these interfaces, be sure to check the causal chain (`err.Cause()`).
8
-package errdefs
9 1
deleted file mode 100644
... ...
@@ -1,86 +0,0 @@
1
-package errdefs
2
-
3
-type causer interface {
4
-	Cause() error
5
-}
6
-
7
-func getImplementer(err error) error {
8
-	switch e := err.(type) {
9
-	case
10
-		ErrNotFound,
11
-		ErrInvalidParameter,
12
-		ErrConflict,
13
-		ErrUnauthorized,
14
-		ErrUnavailable,
15
-		ErrForbidden,
16
-		ErrSystem,
17
-		ErrNotModified,
18
-		ErrNotImplemented,
19
-		ErrUnknown:
20
-		return e
21
-	case causer:
22
-		return getImplementer(e.Cause())
23
-	default:
24
-		return err
25
-	}
26
-}
27
-
28
-// IsNotFound returns if the passed in error is an ErrNotFound
29
-func IsNotFound(err error) bool {
30
-	_, ok := getImplementer(err).(ErrNotFound)
31
-	return ok
32
-}
33
-
34
-// IsInvalidParameter returns if the passed in error is an ErrInvalidParameter
35
-func IsInvalidParameter(err error) bool {
36
-	_, ok := getImplementer(err).(ErrInvalidParameter)
37
-	return ok
38
-}
39
-
40
-// IsConflict returns if the passed in error is an ErrConflict
41
-func IsConflict(err error) bool {
42
-	_, ok := getImplementer(err).(ErrConflict)
43
-	return ok
44
-}
45
-
46
-// IsUnauthorized returns if the the passed in error is an ErrUnauthorized
47
-func IsUnauthorized(err error) bool {
48
-	_, ok := getImplementer(err).(ErrUnauthorized)
49
-	return ok
50
-}
51
-
52
-// IsUnavailable returns if the passed in error is an ErrUnavailable
53
-func IsUnavailable(err error) bool {
54
-	_, ok := getImplementer(err).(ErrUnavailable)
55
-	return ok
56
-}
57
-
58
-// IsForbidden returns if the passed in error is an ErrForbidden
59
-func IsForbidden(err error) bool {
60
-	_, ok := getImplementer(err).(ErrForbidden)
61
-	return ok
62
-}
63
-
64
-// IsSystem returns if the passed in error is an ErrSystem
65
-func IsSystem(err error) bool {
66
-	_, ok := getImplementer(err).(ErrSystem)
67
-	return ok
68
-}
69
-
70
-// IsNotModified returns if the passed in error is a NotModified error
71
-func IsNotModified(err error) bool {
72
-	_, ok := getImplementer(err).(ErrNotModified)
73
-	return ok
74
-}
75
-
76
-// IsNotImplemented returns if the passed in error is an ErrNotImplemented
77
-func IsNotImplemented(err error) bool {
78
-	_, ok := getImplementer(err).(ErrNotImplemented)
79
-	return ok
80
-}
81
-
82
-// IsUnknown returns if the passed in error is an ErrUnknown
83
-func IsUnknown(err error) bool {
84
-	_, ok := getImplementer(err).(ErrUnknown)
85
-	return ok
86
-}
... ...
@@ -4,9 +4,9 @@ import (
4 4
 	"fmt"
5 5
 	"net/http"
6 6
 
7
-	"github.com/docker/docker/api/errdefs"
8 7
 	"github.com/docker/docker/api/types"
9 8
 	"github.com/docker/docker/api/types/versions"
9
+	"github.com/docker/docker/errdefs"
10 10
 	"github.com/gorilla/mux"
11 11
 	"github.com/sirupsen/logrus"
12 12
 	"google.golang.org/grpc"
... ...
@@ -35,7 +35,7 @@ func GetHTTPErrorStatusCode(err error) int {
35 35
 		statusCode = http.StatusNotFound
36 36
 	case errdefs.IsInvalidParameter(err):
37 37
 		statusCode = http.StatusBadRequest
38
-	case errdefs.IsConflict(err):
38
+	case errdefs.IsConflict(err) || errdefs.IsAlreadyExists(err):
39 39
 		statusCode = http.StatusConflict
40 40
 	case errdefs.IsUnauthorized(err):
41 41
 		statusCode = http.StatusUnauthorized
... ...
@@ -47,7 +47,7 @@ func GetHTTPErrorStatusCode(err error) int {
47 47
 		statusCode = http.StatusNotModified
48 48
 	case errdefs.IsNotImplemented(err):
49 49
 		statusCode = http.StatusNotImplemented
50
-	case errdefs.IsSystem(err) || errdefs.IsUnknown(err):
50
+	case errdefs.IsSystem(err) || errdefs.IsUnknown(err) || errdefs.IsDataLoss(err) || errdefs.IsDeadline(err) || errdefs.IsCancelled(err):
51 51
 		statusCode = http.StatusInternalServerError
52 52
 	default:
53 53
 		statusCode = statusCodeFromGRPCError(err)
... ...
@@ -6,6 +6,7 @@ import (
6 6
 	"net/http"
7 7
 	"strings"
8 8
 
9
+	"github.com/docker/docker/errdefs"
9 10
 	"github.com/pkg/errors"
10 11
 	"github.com/sirupsen/logrus"
11 12
 	"golang.org/x/net/context"
... ...
@@ -45,20 +46,6 @@ func CloseStreams(streams ...interface{}) {
45 45
 	}
46 46
 }
47 47
 
48
-type validationError struct {
49
-	cause error
50
-}
51
-
52
-func (e validationError) Error() string {
53
-	return e.cause.Error()
54
-}
55
-
56
-func (e validationError) Cause() error {
57
-	return e.cause
58
-}
59
-
60
-func (e validationError) InvalidParameter() {}
61
-
62 48
 // CheckForJSON makes sure that the request's Content-Type is application/json.
63 49
 func CheckForJSON(r *http.Request) error {
64 50
 	ct := r.Header.Get("Content-Type")
... ...
@@ -74,7 +61,7 @@ func CheckForJSON(r *http.Request) error {
74 74
 	if matchesContentType(ct, "application/json") {
75 75
 		return nil
76 76
 	}
77
-	return validationError{errors.Errorf("Content-Type specified (%s) must be 'application/json'", ct)}
77
+	return errdefs.InvalidParameter(errors.Errorf("Content-Type specified (%s) must be 'application/json'", ct))
78 78
 }
79 79
 
80 80
 // ParseForm ensures the request form is parsed even with invalid content types.
... ...
@@ -84,7 +71,7 @@ func ParseForm(r *http.Request) error {
84 84
 		return nil
85 85
 	}
86 86
 	if err := r.ParseForm(); err != nil && !strings.HasPrefix(err.Error(), "mime:") {
87
-		return validationError{err}
87
+		return errdefs.InvalidParameter(err)
88 88
 	}
89 89
 	return nil
90 90
 }
... ...
@@ -18,6 +18,7 @@ import (
18 18
 	"github.com/docker/docker/api/types/backend"
19 19
 	"github.com/docker/docker/api/types/container"
20 20
 	"github.com/docker/docker/api/types/versions"
21
+	"github.com/docker/docker/errdefs"
21 22
 	"github.com/docker/docker/pkg/ioutils"
22 23
 	"github.com/docker/docker/pkg/progress"
23 24
 	"github.com/docker/docker/pkg/streamformatter"
... ...
@@ -83,7 +84,7 @@ func newImageBuildOptions(ctx context.Context, r *http.Request) (*types.ImageBui
83 83
 		}
84 84
 		p := system.ParsePlatform(apiPlatform)
85 85
 		if err := system.ValidatePlatform(p); err != nil {
86
-			return nil, validationError{fmt.Errorf("invalid platform: %s", err)}
86
+			return nil, errdefs.InvalidParameter(errors.Errorf("invalid platform: %s", err))
87 87
 		}
88 88
 		options.Platform = p.OS
89 89
 	}
... ...
@@ -104,14 +105,14 @@ func newImageBuildOptions(ctx context.Context, r *http.Request) (*types.ImageBui
104 104
 	}
105 105
 
106 106
 	if runtime.GOOS != "windows" && options.SecurityOpt != nil {
107
-		return nil, validationError{fmt.Errorf("The daemon on this platform does not support setting security options on build")}
107
+		return nil, errdefs.InvalidParameter(errors.New("The daemon on this platform does not support setting security options on build"))
108 108
 	}
109 109
 
110 110
 	var buildUlimits = []*units.Ulimit{}
111 111
 	ulimitsJSON := r.FormValue("ulimits")
112 112
 	if ulimitsJSON != "" {
113 113
 		if err := json.Unmarshal([]byte(ulimitsJSON), &buildUlimits); err != nil {
114
-			return nil, errors.Wrap(validationError{err}, "error reading ulimit settings")
114
+			return nil, errors.Wrap(errdefs.InvalidParameter(err), "error reading ulimit settings")
115 115
 		}
116 116
 		options.Ulimits = buildUlimits
117 117
 	}
... ...
@@ -132,7 +133,7 @@ func newImageBuildOptions(ctx context.Context, r *http.Request) (*types.ImageBui
132 132
 	if buildArgsJSON != "" {
133 133
 		var buildArgs = map[string]*string{}
134 134
 		if err := json.Unmarshal([]byte(buildArgsJSON), &buildArgs); err != nil {
135
-			return nil, errors.Wrap(validationError{err}, "error reading build args")
135
+			return nil, errors.Wrap(errdefs.InvalidParameter(err), "error reading build args")
136 136
 		}
137 137
 		options.BuildArgs = buildArgs
138 138
 	}
... ...
@@ -141,7 +142,7 @@ func newImageBuildOptions(ctx context.Context, r *http.Request) (*types.ImageBui
141 141
 	if labelsJSON != "" {
142 142
 		var labels = map[string]string{}
143 143
 		if err := json.Unmarshal([]byte(labelsJSON), &labels); err != nil {
144
-			return nil, errors.Wrap(validationError{err}, "error reading labels")
144
+			return nil, errors.Wrap(errdefs.InvalidParameter(err), "error reading labels")
145 145
 		}
146 146
 		options.Labels = labels
147 147
 	}
... ...
@@ -167,16 +168,6 @@ func (br *buildRouter) postPrune(ctx context.Context, w http.ResponseWriter, r *
167 167
 	return httputils.WriteJSON(w, http.StatusOK, report)
168 168
 }
169 169
 
170
-type validationError struct {
171
-	cause error
172
-}
173
-
174
-func (e validationError) Error() string {
175
-	return e.cause.Error()
176
-}
177
-
178
-func (e validationError) InvalidParameter() {}
179
-
180 170
 func (br *buildRouter) postBuild(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
181 171
 	var (
182 172
 		notVerboseBuffer = bytes.NewBuffer(nil)
... ...
@@ -210,7 +201,7 @@ func (br *buildRouter) postBuild(ctx context.Context, w http.ResponseWriter, r *
210 210
 	buildOptions.AuthConfigs = getAuthConfigs(r.Header)
211 211
 
212 212
 	if buildOptions.Squash && !br.daemon.HasExperimental() {
213
-		return validationError{errors.New("squash is only supported with experimental mode")}
213
+		return errdefs.InvalidParameter(errors.New("squash is only supported with experimental mode"))
214 214
 	}
215 215
 
216 216
 	out := io.Writer(output)
... ...
@@ -5,20 +5,6 @@ import (
5 5
 	"github.com/docker/docker/api/server/router"
6 6
 )
7 7
 
8
-type validationError struct {
9
-	cause error
10
-}
11
-
12
-func (e validationError) Error() string {
13
-	return e.cause.Error()
14
-}
15
-
16
-func (e validationError) Cause() error {
17
-	return e.cause
18
-}
19
-
20
-func (e validationError) InvalidParameter() {}
21
-
22 8
 // containerRouter is a router to talk with the container controller
23 9
 type containerRouter struct {
24 10
 	backend Backend
... ...
@@ -8,7 +8,6 @@ import (
8 8
 	"strconv"
9 9
 	"syscall"
10 10
 
11
-	"github.com/docker/docker/api/errdefs"
12 11
 	"github.com/docker/docker/api/server/httputils"
13 12
 	"github.com/docker/docker/api/types"
14 13
 	"github.com/docker/docker/api/types/backend"
... ...
@@ -16,6 +15,7 @@ import (
16 16
 	"github.com/docker/docker/api/types/filters"
17 17
 	"github.com/docker/docker/api/types/versions"
18 18
 	containerpkg "github.com/docker/docker/container"
19
+	"github.com/docker/docker/errdefs"
19 20
 	"github.com/docker/docker/pkg/ioutils"
20 21
 	"github.com/docker/docker/pkg/signal"
21 22
 	"github.com/pkg/errors"
... ...
@@ -88,7 +88,7 @@ func (s *containerRouter) getContainersLogs(ctx context.Context, w http.Response
88 88
 	// with the appropriate status code.
89 89
 	stdout, stderr := httputils.BoolValue(r, "stdout"), httputils.BoolValue(r, "stderr")
90 90
 	if !(stdout || stderr) {
91
-		return validationError{errors.New("Bad parameters: you must choose at least one stream")}
91
+		return errdefs.InvalidParameter(errors.New("Bad parameters: you must choose at least one stream"))
92 92
 	}
93 93
 
94 94
 	containerName := vars["name"]
... ...
@@ -203,7 +203,7 @@ func (s *containerRouter) postContainersKill(ctx context.Context, w http.Respons
203 203
 	if sigStr := r.Form.Get("signal"); sigStr != "" {
204 204
 		var err error
205 205
 		if sig, err = signal.ParseSignal(sigStr); err != nil {
206
-			return validationError{err}
206
+			return errdefs.InvalidParameter(err)
207 207
 		}
208 208
 	}
209 209
 
... ...
@@ -468,11 +468,11 @@ func (s *containerRouter) postContainersResize(ctx context.Context, w http.Respo
468 468
 
469 469
 	height, err := strconv.Atoi(r.Form.Get("h"))
470 470
 	if err != nil {
471
-		return validationError{err}
471
+		return errdefs.InvalidParameter(err)
472 472
 	}
473 473
 	width, err := strconv.Atoi(r.Form.Get("w"))
474 474
 	if err != nil {
475
-		return validationError{err}
475
+		return errdefs.InvalidParameter(err)
476 476
 	}
477 477
 
478 478
 	return s.backend.ContainerResize(vars["name"], height, width)
... ...
@@ -490,7 +490,7 @@ func (s *containerRouter) postContainersAttach(ctx context.Context, w http.Respo
490 490
 
491 491
 	hijacker, ok := w.(http.Hijacker)
492 492
 	if !ok {
493
-		return validationError{errors.Errorf("error attaching to container %s, hijack connection missing", containerName)}
493
+		return errdefs.InvalidParameter(errors.Errorf("error attaching to container %s, hijack connection missing", containerName))
494 494
 	}
495 495
 
496 496
 	setupStreams := func() (io.ReadCloser, io.Writer, io.Writer, error) {
... ...
@@ -611,7 +611,7 @@ func (s *containerRouter) postContainersPrune(ctx context.Context, w http.Respon
611 611
 
612 612
 	pruneFilters, err := filters.FromJSON(r.Form.Get("filters"))
613 613
 	if err != nil {
614
-		return validationError{err}
614
+		return errdefs.InvalidParameter(err)
615 615
 	}
616 616
 
617 617
 	pruneReport, err := s.backend.ContainersPrune(ctx, pruneFilters)
... ...
@@ -10,6 +10,7 @@ import (
10 10
 	"github.com/docker/docker/api/server/httputils"
11 11
 	"github.com/docker/docker/api/types"
12 12
 	"github.com/docker/docker/api/types/versions"
13
+	"github.com/docker/docker/errdefs"
13 14
 	"github.com/docker/docker/pkg/stdcopy"
14 15
 	"github.com/sirupsen/logrus"
15 16
 	"golang.org/x/net/context"
... ...
@@ -137,11 +138,11 @@ func (s *containerRouter) postContainerExecResize(ctx context.Context, w http.Re
137 137
 	}
138 138
 	height, err := strconv.Atoi(r.Form.Get("h"))
139 139
 	if err != nil {
140
-		return validationError{err}
140
+		return errdefs.InvalidParameter(err)
141 141
 	}
142 142
 	width, err := strconv.Atoi(r.Form.Get("w"))
143 143
 	if err != nil {
144
-		return validationError{err}
144
+		return errdefs.InvalidParameter(err)
145 145
 	}
146 146
 
147 147
 	return s.backend.ContainerExecResize(vars["name"], height, width)
... ...
@@ -15,6 +15,7 @@ import (
15 15
 	"github.com/docker/docker/api/types/backend"
16 16
 	"github.com/docker/docker/api/types/filters"
17 17
 	"github.com/docker/docker/api/types/versions"
18
+	"github.com/docker/docker/errdefs"
18 19
 	"github.com/docker/docker/pkg/ioutils"
19 20
 	"github.com/docker/docker/pkg/streamformatter"
20 21
 	"github.com/docker/docker/pkg/system"
... ...
@@ -144,20 +145,6 @@ func (s *imageRouter) postImagesCreate(ctx context.Context, w http.ResponseWrite
144 144
 	return nil
145 145
 }
146 146
 
147
-type validationError struct {
148
-	cause error
149
-}
150
-
151
-func (e validationError) Error() string {
152
-	return e.cause.Error()
153
-}
154
-
155
-func (e validationError) Cause() error {
156
-	return e.cause
157
-}
158
-
159
-func (validationError) InvalidParameter() {}
160
-
161 147
 func (s *imageRouter) postImagesPush(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
162 148
 	metaHeaders := map[string][]string{}
163 149
 	for k, v := range r.Header {
... ...
@@ -181,7 +168,7 @@ func (s *imageRouter) postImagesPush(ctx context.Context, w http.ResponseWriter,
181 181
 	} else {
182 182
 		// the old format is supported for compatibility if there was no authConfig header
183 183
 		if err := json.NewDecoder(r.Body).Decode(authConfig); err != nil {
184
-			return errors.Wrap(validationError{err}, "Bad parameters and missing X-Registry-Auth")
184
+			return errors.Wrap(errdefs.InvalidParameter(err), "Bad parameters and missing X-Registry-Auth")
185 185
 		}
186 186
 	}
187 187
 
... ...
@@ -2,7 +2,6 @@ package network
2 2
 
3 3
 import (
4 4
 	"encoding/json"
5
-	"fmt"
6 5
 	"net/http"
7 6
 	"strconv"
8 7
 	"strings"
... ...
@@ -14,6 +13,7 @@ import (
14 14
 	"github.com/docker/docker/api/types/filters"
15 15
 	"github.com/docker/docker/api/types/network"
16 16
 	"github.com/docker/docker/api/types/versions"
17
+	"github.com/docker/docker/errdefs"
17 18
 	"github.com/docker/libnetwork"
18 19
 	netconst "github.com/docker/libnetwork/datastore"
19 20
 	"github.com/docker/libnetwork/networkdb"
... ...
@@ -101,22 +101,8 @@ func (e ambigousResultsError) Error() string {
101 101
 
102 102
 func (ambigousResultsError) InvalidParameter() {}
103 103
 
104
-type conflictError struct {
105
-	cause error
106
-}
107
-
108
-func (e conflictError) Error() string {
109
-	return e.cause.Error()
110
-}
111
-
112
-func (e conflictError) Cause() error {
113
-	return e.cause
114
-}
115
-
116
-func (e conflictError) Conflict() {}
117
-
118 104
 func nameConflict(name string) error {
119
-	return conflictError{libnetwork.NetworkNameError(name)}
105
+	return errdefs.Conflict(libnetwork.NetworkNameError(name))
120 106
 }
121 107
 
122 108
 func (n *networkRouter) getNetwork(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
... ...
@@ -589,7 +575,7 @@ func (n *networkRouter) findUniqueNetwork(term string) (types.NetworkResource, e
589 589
 		}
590 590
 	}
591 591
 	if len(listByFullName) > 1 {
592
-		return types.NetworkResource{}, fmt.Errorf("network %s is ambiguous (%d matches found based on name)", term, len(listByFullName))
592
+		return types.NetworkResource{}, errdefs.InvalidParameter(errors.Errorf("network %s is ambiguous (%d matches found based on name)", term, len(listByFullName)))
593 593
 	}
594 594
 
595 595
 	// Find based on partial ID, returns true only if no duplicates
... ...
@@ -599,8 +585,8 @@ func (n *networkRouter) findUniqueNetwork(term string) (types.NetworkResource, e
599 599
 		}
600 600
 	}
601 601
 	if len(listByPartialID) > 1 {
602
-		return types.NetworkResource{}, fmt.Errorf("network %s is ambiguous (%d matches found based on ID prefix)", term, len(listByPartialID))
602
+		return types.NetworkResource{}, errdefs.InvalidParameter(errors.Errorf("network %s is ambiguous (%d matches found based on ID prefix)", term, len(listByPartialID)))
603 603
 	}
604 604
 
605
-	return types.NetworkResource{}, libnetwork.ErrNoSuchNetwork(term)
605
+	return types.NetworkResource{}, errdefs.NotFound(libnetwork.ErrNoSuchNetwork(term))
606 606
 }
... ...
@@ -3,27 +3,14 @@ package session
3 3
 import (
4 4
 	"net/http"
5 5
 
6
+	"github.com/docker/docker/errdefs"
6 7
 	"golang.org/x/net/context"
7 8
 )
8 9
 
9
-type invalidRequest struct {
10
-	cause error
11
-}
12
-
13
-func (e invalidRequest) Error() string {
14
-	return e.cause.Error()
15
-}
16
-
17
-func (e invalidRequest) Cause() error {
18
-	return e.cause
19
-}
20
-
21
-func (e invalidRequest) InvalidParameter() {}
22
-
23 10
 func (sr *sessionRouter) startSession(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
24 11
 	err := sr.backend.HandleHTTPRequest(ctx, w, r)
25 12
 	if err != nil {
26
-		return invalidRequest{err}
13
+		return errdefs.InvalidParameter(err)
27 14
 	}
28 15
 	return nil
29 16
 }
... ...
@@ -12,6 +12,7 @@ import (
12 12
 	"github.com/docker/docker/api/types/filters"
13 13
 	types "github.com/docker/docker/api/types/swarm"
14 14
 	"github.com/docker/docker/api/types/versions"
15
+	"github.com/docker/docker/errdefs"
15 16
 	"github.com/pkg/errors"
16 17
 	"github.com/sirupsen/logrus"
17 18
 	"golang.org/x/net/context"
... ...
@@ -57,20 +58,6 @@ func (sr *swarmRouter) inspectCluster(ctx context.Context, w http.ResponseWriter
57 57
 	return httputils.WriteJSON(w, http.StatusOK, swarm)
58 58
 }
59 59
 
60
-type invalidRequestError struct {
61
-	err error
62
-}
63
-
64
-func (e invalidRequestError) Error() string {
65
-	return e.err.Error()
66
-}
67
-
68
-func (e invalidRequestError) Cause() error {
69
-	return e.err
70
-}
71
-
72
-func (e invalidRequestError) InvalidParameter() {}
73
-
74 60
 func (sr *swarmRouter) updateCluster(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
75 61
 	var swarm types.Spec
76 62
 	if err := json.NewDecoder(r.Body).Decode(&swarm); err != nil {
... ...
@@ -81,7 +68,7 @@ func (sr *swarmRouter) updateCluster(ctx context.Context, w http.ResponseWriter,
81 81
 	version, err := strconv.ParseUint(rawVersion, 10, 64)
82 82
 	if err != nil {
83 83
 		err := fmt.Errorf("invalid swarm version '%s': %v", rawVersion, err)
84
-		return invalidRequestError{err}
84
+		return errdefs.InvalidParameter(err)
85 85
 	}
86 86
 
87 87
 	var flags types.UpdateFlags
... ...
@@ -90,7 +77,7 @@ func (sr *swarmRouter) updateCluster(ctx context.Context, w http.ResponseWriter,
90 90
 		rot, err := strconv.ParseBool(value)
91 91
 		if err != nil {
92 92
 			err := fmt.Errorf("invalid value for rotateWorkerToken: %s", value)
93
-			return invalidRequestError{err}
93
+			return errdefs.InvalidParameter(err)
94 94
 		}
95 95
 
96 96
 		flags.RotateWorkerToken = rot
... ...
@@ -100,7 +87,7 @@ func (sr *swarmRouter) updateCluster(ctx context.Context, w http.ResponseWriter,
100 100
 		rot, err := strconv.ParseBool(value)
101 101
 		if err != nil {
102 102
 			err := fmt.Errorf("invalid value for rotateManagerToken: %s", value)
103
-			return invalidRequestError{err}
103
+			return errdefs.InvalidParameter(err)
104 104
 		}
105 105
 
106 106
 		flags.RotateManagerToken = rot
... ...
@@ -109,7 +96,7 @@ func (sr *swarmRouter) updateCluster(ctx context.Context, w http.ResponseWriter,
109 109
 	if value := r.URL.Query().Get("rotateManagerUnlockKey"); value != "" {
110 110
 		rot, err := strconv.ParseBool(value)
111 111
 		if err != nil {
112
-			return invalidRequestError{fmt.Errorf("invalid value for rotateManagerUnlockKey: %s", value)}
112
+			return errdefs.InvalidParameter(fmt.Errorf("invalid value for rotateManagerUnlockKey: %s", value))
113 113
 		}
114 114
 
115 115
 		flags.RotateManagerUnlockKey = rot
... ...
@@ -153,7 +140,7 @@ func (sr *swarmRouter) getServices(ctx context.Context, w http.ResponseWriter, r
153 153
 	}
154 154
 	filter, err := filters.FromJSON(r.Form.Get("filters"))
155 155
 	if err != nil {
156
-		return invalidRequestError{err}
156
+		return errdefs.InvalidParameter(err)
157 157
 	}
158 158
 
159 159
 	services, err := sr.backend.GetServices(basictypes.ServiceListOptions{Filters: filter})
... ...
@@ -172,7 +159,7 @@ func (sr *swarmRouter) getService(ctx context.Context, w http.ResponseWriter, r
172 172
 		insertDefaults, err = strconv.ParseBool(value)
173 173
 		if err != nil {
174 174
 			err := fmt.Errorf("invalid value for insertDefaults: %s", value)
175
-			return errors.Wrapf(invalidRequestError{err}, "invalid value for insertDefaults: %s", value)
175
+			return errors.Wrapf(errdefs.InvalidParameter(err), "invalid value for insertDefaults: %s", value)
176 176
 		}
177 177
 	}
178 178
 
... ...
@@ -218,7 +205,7 @@ func (sr *swarmRouter) updateService(ctx context.Context, w http.ResponseWriter,
218 218
 	version, err := strconv.ParseUint(rawVersion, 10, 64)
219 219
 	if err != nil {
220 220
 		err := fmt.Errorf("invalid service version '%s': %v", rawVersion, err)
221
-		return invalidRequestError{err}
221
+		return errdefs.InvalidParameter(err)
222 222
 	}
223 223
 
224 224
 	var flags basictypes.ServiceUpdateOptions
... ...
@@ -311,7 +298,7 @@ func (sr *swarmRouter) updateNode(ctx context.Context, w http.ResponseWriter, r
311 311
 	version, err := strconv.ParseUint(rawVersion, 10, 64)
312 312
 	if err != nil {
313 313
 		err := fmt.Errorf("invalid node version '%s': %v", rawVersion, err)
314
-		return invalidRequestError{err}
314
+		return errdefs.InvalidParameter(err)
315 315
 	}
316 316
 
317 317
 	if err := sr.backend.UpdateNode(vars["id"], version, node); err != nil {
... ...
@@ -417,13 +404,13 @@ func (sr *swarmRouter) getSecret(ctx context.Context, w http.ResponseWriter, r *
417 417
 func (sr *swarmRouter) updateSecret(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
418 418
 	var secret types.SecretSpec
419 419
 	if err := json.NewDecoder(r.Body).Decode(&secret); err != nil {
420
-		return invalidRequestError{err}
420
+		return errdefs.InvalidParameter(err)
421 421
 	}
422 422
 
423 423
 	rawVersion := r.URL.Query().Get("version")
424 424
 	version, err := strconv.ParseUint(rawVersion, 10, 64)
425 425
 	if err != nil {
426
-		return invalidRequestError{fmt.Errorf("invalid secret version")}
426
+		return errdefs.InvalidParameter(fmt.Errorf("invalid secret version"))
427 427
 	}
428 428
 
429 429
 	id := vars["id"]
... ...
@@ -484,13 +471,13 @@ func (sr *swarmRouter) getConfig(ctx context.Context, w http.ResponseWriter, r *
484 484
 func (sr *swarmRouter) updateConfig(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
485 485
 	var config types.ConfigSpec
486 486
 	if err := json.NewDecoder(r.Body).Decode(&config); err != nil {
487
-		return invalidRequestError{err}
487
+		return errdefs.InvalidParameter(err)
488 488
 	}
489 489
 
490 490
 	rawVersion := r.URL.Query().Get("version")
491 491
 	version, err := strconv.ParseUint(rawVersion, 10, 64)
492 492
 	if err != nil {
493
-		return invalidRequestError{fmt.Errorf("invalid config version")}
493
+		return errdefs.InvalidParameter(fmt.Errorf("invalid config version"))
494 494
 	}
495 495
 
496 496
 	id := vars["id"]
... ...
@@ -17,6 +17,7 @@ import (
17 17
 	"github.com/docker/docker/builder/dockerfile/parser"
18 18
 	"github.com/docker/docker/builder/fscache"
19 19
 	"github.com/docker/docker/builder/remotecontext"
20
+	"github.com/docker/docker/errdefs"
20 21
 	"github.com/docker/docker/pkg/idtools"
21 22
 	"github.com/docker/docker/pkg/streamformatter"
22 23
 	"github.com/docker/docker/pkg/stringid"
... ...
@@ -225,7 +226,7 @@ func (b *Builder) build(source builder.Source, dockerfile *parser.Result) (*buil
225 225
 		if instructions.IsUnknownInstruction(err) {
226 226
 			buildsFailed.WithValues(metricsUnknownInstructionError).Inc()
227 227
 		}
228
-		return nil, validationError{err}
228
+		return nil, errdefs.InvalidParameter(err)
229 229
 	}
230 230
 	if b.options.Target != "" {
231 231
 		targetIx, found := instructions.HasStage(stages, b.options.Target)
... ...
@@ -363,7 +364,7 @@ func BuildFromConfig(config *container.Config, changes []string) (*container.Con
363 363
 
364 364
 	dockerfile, err := parser.Parse(bytes.NewBufferString(strings.Join(changes, "\n")))
365 365
 	if err != nil {
366
-		return nil, validationError{err}
366
+		return nil, errdefs.InvalidParameter(err)
367 367
 	}
368 368
 
369 369
 	os := runtime.GOOS
... ...
@@ -378,7 +379,7 @@ func BuildFromConfig(config *container.Config, changes []string) (*container.Con
378 378
 	// ensure that the commands are valid
379 379
 	for _, n := range dockerfile.AST.Children {
380 380
 		if !validCommitCommands[n.Value] {
381
-			return nil, validationError{errors.Errorf("%s is not a valid change command", n.Value)}
381
+			return nil, errdefs.InvalidParameter(errors.Errorf("%s is not a valid change command", n.Value))
382 382
 		}
383 383
 	}
384 384
 
... ...
@@ -390,7 +391,7 @@ func BuildFromConfig(config *container.Config, changes []string) (*container.Con
390 390
 	for _, n := range dockerfile.AST.Children {
391 391
 		cmd, err := instructions.ParseCommand(n)
392 392
 		if err != nil {
393
-			return nil, validationError{err}
393
+			return nil, errdefs.InvalidParameter(err)
394 394
 		}
395 395
 		commands = append(commands, cmd)
396 396
 	}
... ...
@@ -402,7 +403,7 @@ func BuildFromConfig(config *container.Config, changes []string) (*container.Con
402 402
 	for _, cmd := range commands {
403 403
 		err := dispatch(dispatchRequest, cmd)
404 404
 		if err != nil {
405
-			return nil, validationError{err}
405
+			return nil, errdefs.InvalidParameter(err)
406 406
 		}
407 407
 		dispatchRequest.state.updateRunConfig()
408 408
 	}
... ...
@@ -20,6 +20,7 @@ import (
20 20
 	"github.com/docker/docker/builder"
21 21
 	"github.com/docker/docker/builder/dockerfile/instructions"
22 22
 	"github.com/docker/docker/builder/dockerfile/parser"
23
+	"github.com/docker/docker/errdefs"
23 24
 	"github.com/docker/docker/image"
24 25
 	"github.com/docker/docker/pkg/jsonmessage"
25 26
 	"github.com/docker/docker/pkg/signal"
... ...
@@ -510,7 +511,7 @@ func dispatchStopSignal(d dispatchRequest, c *instructions.StopSignalCommand) er
510 510
 
511 511
 	_, err := signal.ParseSignal(c.Signal)
512 512
 	if err != nil {
513
-		return validationError{err}
513
+		return errdefs.InvalidParameter(err)
514 514
 	}
515 515
 	d.state.runConfig.StopSignal = c.Signal
516 516
 	return d.builder.commit(d.state, fmt.Sprintf("STOPSIGNAL %v", c.Signal))
517 517
deleted file mode 100644
... ...
@@ -1,15 +0,0 @@
1
-package dockerfile
2
-
3
-type validationError struct {
4
-	err error
5
-}
6
-
7
-func (e validationError) Error() string {
8
-	return e.err.Error()
9
-}
10
-
11
-func (e validationError) InvalidParameter() {}
12
-
13
-func (e validationError) Cause() error {
14
-	return e.err
15
-}
... ...
@@ -27,6 +27,7 @@ import (
27 27
 	"github.com/docker/docker/api/types/container"
28 28
 	"github.com/docker/docker/builder"
29 29
 	"github.com/docker/docker/builder/dockerfile/instructions"
30
+	"github.com/docker/docker/errdefs"
30 31
 	"github.com/docker/docker/pkg/system"
31 32
 	"github.com/docker/docker/runconfig/opts"
32 33
 	"github.com/pkg/errors"
... ...
@@ -37,7 +38,7 @@ func dispatch(d dispatchRequest, cmd instructions.Command) (err error) {
37 37
 		optionsOS := system.ParsePlatform(d.builder.options.Platform).OS
38 38
 		err := c.CheckPlatform(optionsOS)
39 39
 		if err != nil {
40
-			return validationError{err}
40
+			return errdefs.InvalidParameter(err)
41 41
 		}
42 42
 	}
43 43
 	runConfigEnv := d.state.runConfig.Env
... ...
@@ -48,7 +49,7 @@ func dispatch(d dispatchRequest, cmd instructions.Command) (err error) {
48 48
 			return d.shlex.ProcessWord(word, envs)
49 49
 		})
50 50
 		if err != nil {
51
-			return validationError{err}
51
+			return errdefs.InvalidParameter(err)
52 52
 		}
53 53
 	}
54 54
 
55 55
deleted file mode 100644
... ...
@@ -1,75 +0,0 @@
1
-package remotecontext
2
-
3
-type notFoundError string
4
-
5
-func (e notFoundError) Error() string {
6
-	return string(e)
7
-}
8
-
9
-func (notFoundError) NotFound() {}
10
-
11
-type requestError string
12
-
13
-func (e requestError) Error() string {
14
-	return string(e)
15
-}
16
-
17
-func (e requestError) InvalidParameter() {}
18
-
19
-type unauthorizedError string
20
-
21
-func (e unauthorizedError) Error() string {
22
-	return string(e)
23
-}
24
-
25
-func (unauthorizedError) Unauthorized() {}
26
-
27
-type forbiddenError string
28
-
29
-func (e forbiddenError) Error() string {
30
-	return string(e)
31
-}
32
-
33
-func (forbiddenError) Forbidden() {}
34
-
35
-type dnsError struct {
36
-	cause error
37
-}
38
-
39
-func (e dnsError) Error() string {
40
-	return e.cause.Error()
41
-}
42
-
43
-func (e dnsError) NotFound() {}
44
-
45
-func (e dnsError) Cause() error {
46
-	return e.cause
47
-}
48
-
49
-type systemError struct {
50
-	cause error
51
-}
52
-
53
-func (e systemError) Error() string {
54
-	return e.cause.Error()
55
-}
56
-
57
-func (e systemError) SystemError() {}
58
-
59
-func (e systemError) Cause() error {
60
-	return e.cause
61
-}
62
-
63
-type unknownError struct {
64
-	cause error
65
-}
66
-
67
-func (e unknownError) Error() string {
68
-	return e.cause.Error()
69
-}
70
-
71
-func (unknownError) Unknown() {}
72
-
73
-func (e unknownError) Cause() error {
74
-	return e.cause
75
-}
... ...
@@ -10,6 +10,7 @@ import (
10 10
 	"net/url"
11 11
 	"regexp"
12 12
 
13
+	"github.com/docker/docker/errdefs"
13 14
 	"github.com/docker/docker/pkg/ioutils"
14 15
 	"github.com/pkg/errors"
15 16
 )
... ...
@@ -26,7 +27,7 @@ var mimeRe = regexp.MustCompile(acceptableRemoteMIME)
26 26
 func downloadRemote(remoteURL string) (string, io.ReadCloser, error) {
27 27
 	response, err := GetWithStatusError(remoteURL)
28 28
 	if err != nil {
29
-		return "", nil, fmt.Errorf("error downloading remote context %s: %v", remoteURL, err)
29
+		return "", nil, errors.Wrapf(err, "error downloading remote context %s", remoteURL)
30 30
 	}
31 31
 
32 32
 	contentType, contextReader, err := inspectResponse(
... ...
@@ -35,7 +36,7 @@ func downloadRemote(remoteURL string) (string, io.ReadCloser, error) {
35 35
 		response.ContentLength)
36 36
 	if err != nil {
37 37
 		response.Body.Close()
38
-		return "", nil, fmt.Errorf("error detecting content type for remote %s: %v", remoteURL, err)
38
+		return "", nil, errors.Wrapf(err, "error detecting content type for remote %s", remoteURL)
39 39
 	}
40 40
 
41 41
 	return contentType, ioutils.NewReadCloserWrapper(contextReader, response.Body.Close), nil
... ...
@@ -47,10 +48,10 @@ func GetWithStatusError(address string) (resp *http.Response, err error) {
47 47
 	if resp, err = http.Get(address); err != nil {
48 48
 		if uerr, ok := err.(*url.Error); ok {
49 49
 			if derr, ok := uerr.Err.(*net.DNSError); ok && !derr.IsTimeout {
50
-				return nil, dnsError{err}
50
+				return nil, errdefs.NotFound(err)
51 51
 			}
52 52
 		}
53
-		return nil, systemError{err}
53
+		return nil, errdefs.System(err)
54 54
 	}
55 55
 	if resp.StatusCode < 400 {
56 56
 		return resp, nil
... ...
@@ -59,21 +60,21 @@ func GetWithStatusError(address string) (resp *http.Response, err error) {
59 59
 	body, err := ioutil.ReadAll(resp.Body)
60 60
 	resp.Body.Close()
61 61
 	if err != nil {
62
-		return nil, errors.Wrap(systemError{err}, msg+": error reading body")
62
+		return nil, errdefs.System(errors.New(msg + ": error reading body"))
63 63
 	}
64 64
 
65 65
 	msg += ": " + string(bytes.TrimSpace(body))
66 66
 	switch resp.StatusCode {
67 67
 	case http.StatusNotFound:
68
-		return nil, notFoundError(msg)
68
+		return nil, errdefs.NotFound(errors.New(msg))
69 69
 	case http.StatusBadRequest:
70
-		return nil, requestError(msg)
70
+		return nil, errdefs.InvalidParameter(errors.New(msg))
71 71
 	case http.StatusUnauthorized:
72
-		return nil, unauthorizedError(msg)
72
+		return nil, errdefs.Unauthorized(errors.New(msg))
73 73
 	case http.StatusForbidden:
74
-		return nil, forbiddenError(msg)
74
+		return nil, errdefs.Forbidden(errors.New(msg))
75 75
 	}
76
-	return nil, unknownError{errors.New(msg)}
76
+	return nil, errdefs.Unknown(errors.New(msg))
77 77
 }
78 78
 
79 79
 // inspectResponse looks into the http response data at r to determine whether its
... ...
@@ -7,6 +7,7 @@ import (
7 7
 
8 8
 	"github.com/docker/docker/api/types"
9 9
 	"github.com/docker/docker/container"
10
+	"github.com/docker/docker/errdefs"
10 11
 	"github.com/docker/docker/pkg/archive"
11 12
 	"github.com/docker/docker/pkg/chrootarchive"
12 13
 	"github.com/docker/docker/pkg/ioutils"
... ...
@@ -54,7 +55,7 @@ func (daemon *Daemon) ContainerCopy(name string, res string) (io.ReadCloser, err
54 54
 
55 55
 	// Make sure an online file-system operation is permitted.
56 56
 	if err := daemon.isOnlineFSOperationPermitted(container); err != nil {
57
-		return nil, systemError{err}
57
+		return nil, errdefs.System(err)
58 58
 	}
59 59
 
60 60
 	data, err := daemon.containerCopy(container, res)
... ...
@@ -65,7 +66,7 @@ func (daemon *Daemon) ContainerCopy(name string, res string) (io.ReadCloser, err
65 65
 	if os.IsNotExist(err) {
66 66
 		return nil, containerFileNotFound{res, name}
67 67
 	}
68
-	return nil, systemError{err}
68
+	return nil, errdefs.System(err)
69 69
 }
70 70
 
71 71
 // ContainerStatPath stats the filesystem resource at the specified path in the
... ...
@@ -78,7 +79,7 @@ func (daemon *Daemon) ContainerStatPath(name string, path string) (stat *types.C
78 78
 
79 79
 	// Make sure an online file-system operation is permitted.
80 80
 	if err := daemon.isOnlineFSOperationPermitted(container); err != nil {
81
-		return nil, systemError{err}
81
+		return nil, errdefs.System(err)
82 82
 	}
83 83
 
84 84
 	stat, err = daemon.containerStatPath(container, path)
... ...
@@ -89,7 +90,7 @@ func (daemon *Daemon) ContainerStatPath(name string, path string) (stat *types.C
89 89
 	if os.IsNotExist(err) {
90 90
 		return nil, containerFileNotFound{path, name}
91 91
 	}
92
-	return nil, systemError{err}
92
+	return nil, errdefs.System(err)
93 93
 }
94 94
 
95 95
 // ContainerArchivePath creates an archive of the filesystem resource at the
... ...
@@ -103,7 +104,7 @@ func (daemon *Daemon) ContainerArchivePath(name string, path string) (content io
103 103
 
104 104
 	// Make sure an online file-system operation is permitted.
105 105
 	if err := daemon.isOnlineFSOperationPermitted(container); err != nil {
106
-		return nil, nil, systemError{err}
106
+		return nil, nil, errdefs.System(err)
107 107
 	}
108 108
 
109 109
 	content, stat, err = daemon.containerArchivePath(container, path)
... ...
@@ -114,7 +115,7 @@ func (daemon *Daemon) ContainerArchivePath(name string, path string) (content io
114 114
 	if os.IsNotExist(err) {
115 115
 		return nil, nil, containerFileNotFound{path, name}
116 116
 	}
117
-	return nil, nil, systemError{err}
117
+	return nil, nil, errdefs.System(err)
118 118
 }
119 119
 
120 120
 // ContainerExtractToDir extracts the given archive to the specified location
... ...
@@ -131,7 +132,7 @@ func (daemon *Daemon) ContainerExtractToDir(name, path string, copyUIDGID, noOve
131 131
 
132 132
 	// Make sure an online file-system operation is permitted.
133 133
 	if err := daemon.isOnlineFSOperationPermitted(container); err != nil {
134
-		return systemError{err}
134
+		return errdefs.System(err)
135 135
 	}
136 136
 
137 137
 	err = daemon.containerExtractToDir(container, path, copyUIDGID, noOverwriteDirNonDir, content)
... ...
@@ -142,7 +143,7 @@ func (daemon *Daemon) ContainerExtractToDir(name, path string, copyUIDGID, noOve
142 142
 	if os.IsNotExist(err) {
143 143
 		return containerFileNotFound{path, name}
144 144
 	}
145
-	return systemError{err}
145
+	return errdefs.System(err)
146 146
 }
147 147
 
148 148
 // containerStatPath stats the filesystem resource at the specified path in this
... ...
@@ -9,6 +9,7 @@ import (
9 9
 	"github.com/docker/docker/container"
10 10
 	"github.com/docker/docker/container/stream"
11 11
 	"github.com/docker/docker/daemon/logger"
12
+	"github.com/docker/docker/errdefs"
12 13
 	"github.com/docker/docker/pkg/stdcopy"
13 14
 	"github.com/docker/docker/pkg/term"
14 15
 	"github.com/pkg/errors"
... ...
@@ -22,7 +23,7 @@ func (daemon *Daemon) ContainerAttach(prefixOrName string, c *backend.ContainerA
22 22
 	if c.DetachKeys != "" {
23 23
 		keys, err = term.ToBytes(c.DetachKeys)
24 24
 		if err != nil {
25
-			return validationError{errors.Errorf("Invalid detach keys (%s) provided", c.DetachKeys)}
25
+			return errdefs.InvalidParameter(errors.Errorf("Invalid detach keys (%s) provided", c.DetachKeys))
26 26
 		}
27 27
 	}
28 28
 
... ...
@@ -32,11 +33,11 @@ func (daemon *Daemon) ContainerAttach(prefixOrName string, c *backend.ContainerA
32 32
 	}
33 33
 	if container.IsPaused() {
34 34
 		err := fmt.Errorf("container %s is paused, unpause the container before attach", prefixOrName)
35
-		return stateConflictError{err}
35
+		return errdefs.Conflict(err)
36 36
 	}
37 37
 	if container.IsRestarting() {
38 38
 		err := fmt.Errorf("container %s is restarting, wait until the container is running", prefixOrName)
39
-		return stateConflictError{err}
39
+		return errdefs.Conflict(err)
40 40
 	}
41 41
 
42 42
 	cfg := stream.AttachConfig{
... ...
@@ -6,9 +6,9 @@ import (
6 6
 	"net/http"
7 7
 
8 8
 	"github.com/docker/distribution/reference"
9
-	"github.com/docker/docker/api/errdefs"
10 9
 	enginetypes "github.com/docker/docker/api/types"
11 10
 	"github.com/docker/docker/api/types/swarm/runtime"
11
+	"github.com/docker/docker/errdefs"
12 12
 	"github.com/docker/docker/plugin"
13 13
 	"github.com/docker/docker/plugin/v2"
14 14
 	"github.com/docker/swarmkit/api"
... ...
@@ -20,48 +20,6 @@ const (
20 20
 	errSwarmNotManager notAvailableError = "This node is not a swarm manager. Worker nodes can't be used to view or modify cluster state. Please run this command on a manager node or promote the current node to a manager."
21 21
 )
22 22
 
23
-type notFoundError struct {
24
-	cause error
25
-}
26
-
27
-func (e notFoundError) Error() string {
28
-	return e.cause.Error()
29
-}
30
-
31
-func (e notFoundError) NotFound() {}
32
-
33
-func (e notFoundError) Cause() error {
34
-	return e.cause
35
-}
36
-
37
-type ambiguousResultsError struct {
38
-	cause error
39
-}
40
-
41
-func (e ambiguousResultsError) Error() string {
42
-	return e.cause.Error()
43
-}
44
-
45
-func (e ambiguousResultsError) InvalidParameter() {}
46
-
47
-func (e ambiguousResultsError) Cause() error {
48
-	return e.cause
49
-}
50
-
51
-type convertError struct {
52
-	cause error
53
-}
54
-
55
-func (e convertError) Error() string {
56
-	return e.cause.Error()
57
-}
58
-
59
-func (e convertError) InvalidParameter() {}
60
-
61
-func (e convertError) Cause() error {
62
-	return e.cause
63
-}
64
-
65 23
 type notAllowedError string
66 24
 
67 25
 func (e notAllowedError) Error() string {
... ...
@@ -70,20 +28,6 @@ func (e notAllowedError) Error() string {
70 70
 
71 71
 func (e notAllowedError) Forbidden() {}
72 72
 
73
-type validationError struct {
74
-	cause error
75
-}
76
-
77
-func (e validationError) Error() string {
78
-	return e.cause.Error()
79
-}
80
-
81
-func (e validationError) InvalidParameter() {}
82
-
83
-func (e validationError) Cause() error {
84
-	return e.cause
85
-}
86
-
87 73
 type notAvailableError string
88 74
 
89 75
 func (e notAvailableError) Error() string {
... ...
@@ -3,6 +3,7 @@ package cluster
3 3
 import (
4 4
 	"fmt"
5 5
 
6
+	"github.com/docker/docker/errdefs"
6 7
 	swarmapi "github.com/docker/swarmkit/api"
7 8
 	"github.com/pkg/errors"
8 9
 	"golang.org/x/net/context"
... ...
@@ -48,11 +49,11 @@ func getNode(ctx context.Context, c swarmapi.ControlClient, input string) (*swar
48 48
 
49 49
 	if len(rl.Nodes) == 0 {
50 50
 		err := fmt.Errorf("node %s not found", input)
51
-		return nil, notFoundError{err}
51
+		return nil, errdefs.NotFound(err)
52 52
 	}
53 53
 
54 54
 	if l := len(rl.Nodes); l > 1 {
55
-		return nil, ambiguousResultsError{fmt.Errorf("node %s is ambiguous (%d matches found)", input, l)}
55
+		return nil, errdefs.InvalidParameter(fmt.Errorf("node %s is ambiguous (%d matches found)", input, l))
56 56
 	}
57 57
 
58 58
 	return rl.Nodes[0], nil
... ...
@@ -84,11 +85,11 @@ func getService(ctx context.Context, c swarmapi.ControlClient, input string, ins
84 84
 
85 85
 	if len(rl.Services) == 0 {
86 86
 		err := fmt.Errorf("service %s not found", input)
87
-		return nil, notFoundError{err}
87
+		return nil, errdefs.NotFound(err)
88 88
 	}
89 89
 
90 90
 	if l := len(rl.Services); l > 1 {
91
-		return nil, ambiguousResultsError{fmt.Errorf("service %s is ambiguous (%d matches found)", input, l)}
91
+		return nil, errdefs.InvalidParameter(fmt.Errorf("service %s is ambiguous (%d matches found)", input, l))
92 92
 	}
93 93
 
94 94
 	if !insertDefaults {
... ...
@@ -128,11 +129,11 @@ func getTask(ctx context.Context, c swarmapi.ControlClient, input string) (*swar
128 128
 
129 129
 	if len(rl.Tasks) == 0 {
130 130
 		err := fmt.Errorf("task %s not found", input)
131
-		return nil, notFoundError{err}
131
+		return nil, errdefs.NotFound(err)
132 132
 	}
133 133
 
134 134
 	if l := len(rl.Tasks); l > 1 {
135
-		return nil, ambiguousResultsError{fmt.Errorf("task %s is ambiguous (%d matches found)", input, l)}
135
+		return nil, errdefs.InvalidParameter(fmt.Errorf("task %s is ambiguous (%d matches found)", input, l))
136 136
 	}
137 137
 
138 138
 	return rl.Tasks[0], nil
... ...
@@ -164,11 +165,11 @@ func getSecret(ctx context.Context, c swarmapi.ControlClient, input string) (*sw
164 164
 
165 165
 	if len(rl.Secrets) == 0 {
166 166
 		err := fmt.Errorf("secret %s not found", input)
167
-		return nil, notFoundError{err}
167
+		return nil, errdefs.NotFound(err)
168 168
 	}
169 169
 
170 170
 	if l := len(rl.Secrets); l > 1 {
171
-		return nil, ambiguousResultsError{fmt.Errorf("secret %s is ambiguous (%d matches found)", input, l)}
171
+		return nil, errdefs.InvalidParameter(fmt.Errorf("secret %s is ambiguous (%d matches found)", input, l))
172 172
 	}
173 173
 
174 174
 	return rl.Secrets[0], nil
... ...
@@ -200,11 +201,11 @@ func getConfig(ctx context.Context, c swarmapi.ControlClient, input string) (*sw
200 200
 
201 201
 	if len(rl.Configs) == 0 {
202 202
 		err := fmt.Errorf("config %s not found", input)
203
-		return nil, notFoundError{err}
203
+		return nil, errdefs.NotFound(err)
204 204
 	}
205 205
 
206 206
 	if l := len(rl.Configs); l > 1 {
207
-		return nil, ambiguousResultsError{fmt.Errorf("config %s is ambiguous (%d matches found)", input, l)}
207
+		return nil, errdefs.InvalidParameter(fmt.Errorf("config %s is ambiguous (%d matches found)", input, l))
208 208
 	}
209 209
 
210 210
 	return rl.Configs[0], nil
... ...
@@ -238,7 +239,7 @@ func getNetwork(ctx context.Context, c swarmapi.ControlClient, input string) (*s
238 238
 	}
239 239
 
240 240
 	if l := len(rl.Networks); l > 1 {
241
-		return nil, ambiguousResultsError{fmt.Errorf("network %s is ambiguous (%d matches found)", input, l)}
241
+		return nil, errdefs.InvalidParameter(fmt.Errorf("network %s is ambiguous (%d matches found)", input, l))
242 242
 	}
243 243
 
244 244
 	return rl.Networks[0], nil
... ...
@@ -7,6 +7,7 @@ import (
7 7
 	"github.com/docker/docker/api/types/network"
8 8
 	types "github.com/docker/docker/api/types/swarm"
9 9
 	"github.com/docker/docker/daemon/cluster/convert"
10
+	"github.com/docker/docker/errdefs"
10 11
 	"github.com/docker/docker/runconfig"
11 12
 	swarmapi "github.com/docker/swarmkit/api"
12 13
 	"github.com/pkg/errors"
... ...
@@ -298,7 +299,7 @@ func (c *Cluster) populateNetworkID(ctx context.Context, client swarmapi.Control
298 298
 				// and use its id for the request.
299 299
 				apiNetwork, err = getNetwork(ctx, client, ln.Name())
300 300
 				if err != nil {
301
-					return errors.Wrap(notFoundError{err}, "could not find the corresponding predefined swarm network")
301
+					return errors.Wrap(errdefs.NotFound(err), "could not find the corresponding predefined swarm network")
302 302
 				}
303 303
 				goto setid
304 304
 			}
... ...
@@ -4,6 +4,7 @@ import (
4 4
 	apitypes "github.com/docker/docker/api/types"
5 5
 	types "github.com/docker/docker/api/types/swarm"
6 6
 	"github.com/docker/docker/daemon/cluster/convert"
7
+	"github.com/docker/docker/errdefs"
7 8
 	swarmapi "github.com/docker/swarmkit/api"
8 9
 	"golang.org/x/net/context"
9 10
 )
... ...
@@ -64,7 +65,7 @@ func (c *Cluster) UpdateNode(input string, version uint64, spec types.NodeSpec)
64 64
 	return c.lockedManagerAction(func(ctx context.Context, state nodeState) error {
65 65
 		nodeSpec, err := convert.NodeSpecToGRPC(spec)
66 66
 		if err != nil {
67
-			return convertError{err}
67
+			return errdefs.InvalidParameter(err)
68 68
 		}
69 69
 
70 70
 		ctx, cancel := c.getRequestContext()
... ...
@@ -16,6 +16,7 @@ import (
16 16
 	types "github.com/docker/docker/api/types/swarm"
17 17
 	timetypes "github.com/docker/docker/api/types/time"
18 18
 	"github.com/docker/docker/daemon/cluster/convert"
19
+	"github.com/docker/docker/errdefs"
19 20
 	runconfigopts "github.com/docker/docker/runconfig/opts"
20 21
 	swarmapi "github.com/docker/swarmkit/api"
21 22
 	gogotypes "github.com/gogo/protobuf/types"
... ...
@@ -128,7 +129,7 @@ func (c *Cluster) CreateService(s types.ServiceSpec, encodedAuth string, queryRe
128 128
 
129 129
 		serviceSpec, err := convert.ServiceSpecToGRPC(s)
130 130
 		if err != nil {
131
-			return convertError{err}
131
+			return errdefs.InvalidParameter(err)
132 132
 		}
133 133
 
134 134
 		resp = &apitypes.ServiceCreateResponse{}
... ...
@@ -232,7 +233,7 @@ func (c *Cluster) UpdateService(serviceIDOrName string, version uint64, spec typ
232 232
 
233 233
 		serviceSpec, err := convert.ServiceSpecToGRPC(spec)
234 234
 		if err != nil {
235
-			return convertError{err}
235
+			return errdefs.InvalidParameter(err)
236 236
 		}
237 237
 
238 238
 		currentService, err := getService(ctx, state.controlClient, serviceIDOrName, false)
... ...
@@ -10,6 +10,7 @@ import (
10 10
 	"github.com/docker/docker/api/types/filters"
11 11
 	types "github.com/docker/docker/api/types/swarm"
12 12
 	"github.com/docker/docker/daemon/cluster/convert"
13
+	"github.com/docker/docker/errdefs"
13 14
 	"github.com/docker/docker/opts"
14 15
 	"github.com/docker/docker/pkg/signal"
15 16
 	swarmapi "github.com/docker/swarmkit/api"
... ...
@@ -44,7 +45,7 @@ func (c *Cluster) Init(req types.InitRequest) (string, error) {
44 44
 	}
45 45
 
46 46
 	if err := validateAndSanitizeInitRequest(&req); err != nil {
47
-		return "", validationError{err}
47
+		return "", errdefs.InvalidParameter(err)
48 48
 	}
49 49
 
50 50
 	listenHost, listenPort, err := resolveListenAddr(req.ListenAddr)
... ...
@@ -140,7 +141,7 @@ func (c *Cluster) Join(req types.JoinRequest) error {
140 140
 	c.mu.Unlock()
141 141
 
142 142
 	if err := validateAndSanitizeJoinRequest(&req); err != nil {
143
-		return validationError{err}
143
+		return errdefs.InvalidParameter(err)
144 144
 	}
145 145
 
146 146
 	listenHost, listenPort, err := resolveListenAddr(req.ListenAddr)
... ...
@@ -232,7 +233,7 @@ func (c *Cluster) Update(version uint64, spec types.Spec, flags types.UpdateFlag
232 232
 		if spec.Annotations.Name == "" {
233 233
 			spec.Annotations.Name = "default"
234 234
 		} else if spec.Annotations.Name != "default" {
235
-			return validationError{errors.New(`swarm spec must be named "default"`)}
235
+			return errdefs.InvalidParameter(errors.New(`swarm spec must be named "default"`))
236 236
 		}
237 237
 
238 238
 		// In update, client should provide the complete spec of the swarm, including
... ...
@@ -240,7 +241,7 @@ func (c *Cluster) Update(version uint64, spec types.Spec, flags types.UpdateFlag
240 240
 		// will be used to swarmkit.
241 241
 		clusterSpec, err := convert.SwarmSpecToGRPC(spec)
242 242
 		if err != nil {
243
-			return convertError{err}
243
+			return errdefs.InvalidParameter(err)
244 244
 		}
245 245
 
246 246
 		_, err = state.controlClient.UpdateCluster(
... ...
@@ -311,7 +312,7 @@ func (c *Cluster) UnlockSwarm(req types.UnlockRequest) error {
311 311
 
312 312
 	key, err := encryption.ParseHumanReadableKey(req.UnlockKey)
313 313
 	if err != nil {
314
-		return validationError{err}
314
+		return errdefs.InvalidParameter(err)
315 315
 	}
316 316
 
317 317
 	config := nr.config
... ...
@@ -13,6 +13,7 @@ import (
13 13
 	containertypes "github.com/docker/docker/api/types/container"
14 14
 	"github.com/docker/docker/builder/dockerfile"
15 15
 	"github.com/docker/docker/container"
16
+	"github.com/docker/docker/errdefs"
16 17
 	"github.com/docker/docker/image"
17 18
 	"github.com/docker/docker/layer"
18 19
 	"github.com/docker/docker/pkg/ioutils"
... ...
@@ -136,12 +137,12 @@ func (daemon *Daemon) Commit(name string, c *backend.ContainerCommitConfig) (str
136 136
 
137 137
 	if container.IsDead() {
138 138
 		err := fmt.Errorf("You cannot commit container %s which is Dead", container.ID)
139
-		return "", stateConflictError{err}
139
+		return "", errdefs.Conflict(err)
140 140
 	}
141 141
 
142 142
 	if container.IsRemovalInProgress() {
143 143
 		err := fmt.Errorf("You cannot commit container %s which is being removed", container.ID)
144
-		return "", stateConflictError{err}
144
+		return "", errdefs.Conflict(err)
145 145
 	}
146 146
 
147 147
 	if c.Pause && !container.IsPaused() {
... ...
@@ -13,6 +13,7 @@ import (
13 13
 	"github.com/docker/docker/api/types/strslice"
14 14
 	"github.com/docker/docker/container"
15 15
 	"github.com/docker/docker/daemon/network"
16
+	"github.com/docker/docker/errdefs"
16 17
 	"github.com/docker/docker/image"
17 18
 	"github.com/docker/docker/opts"
18 19
 	"github.com/docker/docker/pkg/signal"
... ...
@@ -54,7 +55,7 @@ func (daemon *Daemon) GetContainer(prefixOrName string) (*container.Container, e
54 54
 		if indexError == truncindex.ErrNotExist {
55 55
 			return nil, containerNotFound(prefixOrName)
56 56
 		}
57
-		return nil, systemError{indexError}
57
+		return nil, errdefs.System(indexError)
58 58
 	}
59 59
 	return daemon.containers.Get(containerID), nil
60 60
 }
... ...
@@ -139,7 +140,7 @@ func (daemon *Daemon) newContainer(name string, operatingSystem string, config *
139 139
 		if config.Hostname == "" {
140 140
 			config.Hostname, err = os.Hostname()
141 141
 			if err != nil {
142
-				return nil, systemError{err}
142
+				return nil, errdefs.System(err)
143 143
 			}
144 144
 		}
145 145
 	} else {
... ...
@@ -4,6 +4,7 @@ package daemon
4 4
 
5 5
 import (
6 6
 	"github.com/docker/docker/container"
7
+	"github.com/docker/docker/errdefs"
7 8
 )
8 9
 
9 10
 func (daemon *Daemon) saveApparmorConfig(container *container.Container) error {
... ...
@@ -14,7 +15,7 @@ func (daemon *Daemon) saveApparmorConfig(container *container.Container) error {
14 14
 	}
15 15
 
16 16
 	if err := parseSecurityOpt(container, container.HostConfig); err != nil {
17
-		return validationError{err}
17
+		return errdefs.InvalidParameter(err)
18 18
 	}
19 19
 
20 20
 	if !container.HostConfig.Privileged {
... ...
@@ -14,6 +14,7 @@ import (
14 14
 	networktypes "github.com/docker/docker/api/types/network"
15 15
 	"github.com/docker/docker/container"
16 16
 	"github.com/docker/docker/daemon/network"
17
+	"github.com/docker/docker/errdefs"
17 18
 	"github.com/docker/docker/opts"
18 19
 	"github.com/docker/docker/pkg/stringid"
19 20
 	"github.com/docker/docker/runconfig"
... ...
@@ -922,7 +923,7 @@ func (daemon *Daemon) getNetworkedContainer(containerID, connectedContainerID st
922 922
 	}
923 923
 	if !nc.IsRunning() {
924 924
 		err := fmt.Errorf("cannot join network of a non running container: %s", connectedContainerID)
925
-		return nil, stateConflictError{err}
925
+		return nil, errdefs.Conflict(err)
926 926
 	}
927 927
 	if nc.IsRestarting() {
928 928
 		return nil, errContainerIsRestarting(connectedContainerID)
... ...
@@ -13,6 +13,7 @@ import (
13 13
 
14 14
 	"github.com/docker/docker/container"
15 15
 	"github.com/docker/docker/daemon/links"
16
+	"github.com/docker/docker/errdefs"
16 17
 	"github.com/docker/docker/pkg/idtools"
17 18
 	"github.com/docker/docker/pkg/mount"
18 19
 	"github.com/docker/docker/pkg/stringid"
... ...
@@ -91,7 +92,7 @@ func (daemon *Daemon) getPidContainer(container *container.Container) (*containe
91 91
 
92 92
 func containerIsRunning(c *container.Container) error {
93 93
 	if !c.IsRunning() {
94
-		return stateConflictError{errors.Errorf("container %s is not running", c.ID)}
94
+		return errdefs.Conflict(errors.Errorf("container %s is not running", c.ID))
95 95
 	}
96 96
 	return nil
97 97
 }
... ...
@@ -13,6 +13,7 @@ import (
13 13
 	containertypes "github.com/docker/docker/api/types/container"
14 14
 	networktypes "github.com/docker/docker/api/types/network"
15 15
 	"github.com/docker/docker/container"
16
+	"github.com/docker/docker/errdefs"
16 17
 	"github.com/docker/docker/image"
17 18
 	"github.com/docker/docker/layer"
18 19
 	"github.com/docker/docker/pkg/idtools"
... ...
@@ -36,7 +37,7 @@ func (daemon *Daemon) ContainerCreate(params types.ContainerCreateConfig) (conta
36 36
 func (daemon *Daemon) containerCreate(params types.ContainerCreateConfig, managed bool) (containertypes.ContainerCreateCreatedBody, error) {
37 37
 	start := time.Now()
38 38
 	if params.Config == nil {
39
-		return containertypes.ContainerCreateCreatedBody{}, validationError{errors.New("Config cannot be empty in order to create a container")}
39
+		return containertypes.ContainerCreateCreatedBody{}, errdefs.InvalidParameter(errors.New("Config cannot be empty in order to create a container"))
40 40
 	}
41 41
 
42 42
 	os := runtime.GOOS
... ...
@@ -55,12 +56,12 @@ func (daemon *Daemon) containerCreate(params types.ContainerCreateConfig, manage
55 55
 
56 56
 	warnings, err := daemon.verifyContainerSettings(os, params.HostConfig, params.Config, false)
57 57
 	if err != nil {
58
-		return containertypes.ContainerCreateCreatedBody{Warnings: warnings}, validationError{err}
58
+		return containertypes.ContainerCreateCreatedBody{Warnings: warnings}, errdefs.InvalidParameter(err)
59 59
 	}
60 60
 
61 61
 	err = verifyNetworkingConfig(params.NetworkingConfig)
62 62
 	if err != nil {
63
-		return containertypes.ContainerCreateCreatedBody{Warnings: warnings}, validationError{err}
63
+		return containertypes.ContainerCreateCreatedBody{Warnings: warnings}, errdefs.InvalidParameter(err)
64 64
 	}
65 65
 
66 66
 	if params.HostConfig == nil {
... ...
@@ -68,7 +69,7 @@ func (daemon *Daemon) containerCreate(params types.ContainerCreateConfig, manage
68 68
 	}
69 69
 	err = daemon.adaptContainerSettings(params.HostConfig, params.AdjustCPUShares)
70 70
 	if err != nil {
71
-		return containertypes.ContainerCreateCreatedBody{Warnings: warnings}, validationError{err}
71
+		return containertypes.ContainerCreateCreatedBody{Warnings: warnings}, errdefs.InvalidParameter(err)
72 72
 	}
73 73
 
74 74
 	container, err := daemon.create(params, managed)
... ...
@@ -115,11 +116,11 @@ func (daemon *Daemon) create(params types.ContainerCreateConfig, managed bool) (
115 115
 	}
116 116
 
117 117
 	if err := daemon.mergeAndVerifyConfig(params.Config, img); err != nil {
118
-		return nil, validationError{err}
118
+		return nil, errdefs.InvalidParameter(err)
119 119
 	}
120 120
 
121 121
 	if err := daemon.mergeAndVerifyLogConfig(&params.HostConfig.LogConfig); err != nil {
122
-		return nil, validationError{err}
122
+		return nil, errdefs.InvalidParameter(err)
123 123
 	}
124 124
 
125 125
 	if container, err = daemon.newContainer(params.Name, os, params.Config, params.HostConfig, imgID, managed); err != nil {
... ...
@@ -158,7 +159,7 @@ func (daemon *Daemon) create(params types.ContainerCreateConfig, managed bool) (
158 158
 
159 159
 	// Set RWLayer for container after mount labels have been set
160 160
 	if err := daemon.setRWLayer(container); err != nil {
161
-		return nil, systemError{err}
161
+		return nil, errdefs.System(err)
162 162
 	}
163 163
 
164 164
 	rootIDs := daemon.idMappings.RootPair()
... ...
@@ -18,7 +18,6 @@ import (
18 18
 	"sync"
19 19
 	"time"
20 20
 
21
-	"github.com/docker/docker/api/errdefs"
22 21
 	"github.com/docker/docker/api/types"
23 22
 	containertypes "github.com/docker/docker/api/types/container"
24 23
 	"github.com/docker/docker/api/types/swarm"
... ...
@@ -29,6 +28,7 @@ import (
29 29
 	"github.com/docker/docker/daemon/exec"
30 30
 	"github.com/docker/docker/daemon/logger"
31 31
 	"github.com/docker/docker/daemon/network"
32
+	"github.com/docker/docker/errdefs"
32 33
 	"github.com/sirupsen/logrus"
33 34
 	// register graph drivers
34 35
 	_ "github.com/docker/docker/daemon/graphdriver/register"
... ...
@@ -7,9 +7,9 @@ import (
7 7
 	"runtime"
8 8
 	"testing"
9 9
 
10
-	"github.com/docker/docker/api/errdefs"
11 10
 	containertypes "github.com/docker/docker/api/types/container"
12 11
 	"github.com/docker/docker/container"
12
+	"github.com/docker/docker/errdefs"
13 13
 	_ "github.com/docker/docker/pkg/discovery/memory"
14 14
 	"github.com/docker/docker/pkg/idtools"
15 15
 	"github.com/docker/docker/pkg/truncindex"
... ...
@@ -9,6 +9,7 @@ import (
9 9
 
10 10
 	"github.com/docker/docker/api/types"
11 11
 	"github.com/docker/docker/container"
12
+	"github.com/docker/docker/errdefs"
12 13
 	"github.com/docker/docker/layer"
13 14
 	"github.com/docker/docker/pkg/system"
14 15
 	"github.com/docker/docker/volume"
... ...
@@ -31,7 +32,7 @@ func (daemon *Daemon) ContainerRm(name string, config *types.ContainerRmConfig)
31 31
 	// Container state RemovalInProgress should be used to avoid races.
32 32
 	if inProgress := container.SetRemovalInProgress(); inProgress {
33 33
 		err := fmt.Errorf("removal of container %s is already in progress", name)
34
-		return stateConflictError{err}
34
+		return errdefs.Conflict(err)
35 35
 	}
36 36
 	defer container.ResetRemovalInProgress()
37 37
 
... ...
@@ -87,7 +88,7 @@ func (daemon *Daemon) cleanupContainer(container *container.Container, forceRemo
87 87
 				procedure = "Unpause and then " + strings.ToLower(procedure)
88 88
 			}
89 89
 			err := fmt.Errorf("You cannot remove a %s container %s. %s", state, container.ID, procedure)
90
-			return stateConflictError{err}
90
+			return errdefs.Conflict(err)
91 91
 		}
92 92
 		if err := daemon.Kill(container); err != nil {
93 93
 			return fmt.Errorf("Could not kill running container %s, cannot remove - %v", container.ID, err)
... ...
@@ -164,7 +165,7 @@ func (daemon *Daemon) VolumeRm(name string, force bool) error {
164 164
 
165 165
 	err = daemon.volumeRm(v)
166 166
 	if err != nil && volumestore.IsInUse(err) {
167
-		return stateConflictError{err}
167
+		return errdefs.Conflict(err)
168 168
 	}
169 169
 
170 170
 	if err == nil || force {
... ...
@@ -5,12 +5,13 @@ import (
5 5
 	"strings"
6 6
 	"syscall"
7 7
 
8
+	"github.com/docker/docker/errdefs"
8 9
 	"github.com/pkg/errors"
9 10
 	"google.golang.org/grpc"
10 11
 )
11 12
 
12 13
 func errNotRunning(id string) error {
13
-	return stateConflictError{errors.Errorf("Container %s is not running", id)}
14
+	return errdefs.Conflict(errors.Errorf("Container %s is not running", id))
14 15
 }
15 16
 
16 17
 func containerNotFound(id string) error {
... ...
@@ -32,23 +33,9 @@ func (e objNotFoundError) Error() string {
32 32
 
33 33
 func (e objNotFoundError) NotFound() {}
34 34
 
35
-type stateConflictError struct {
36
-	cause error
37
-}
38
-
39
-func (e stateConflictError) Error() string {
40
-	return e.cause.Error()
41
-}
42
-
43
-func (e stateConflictError) Cause() error {
44
-	return e.cause
45
-}
46
-
47
-func (e stateConflictError) Conflict() {}
48
-
49 35
 func errContainerIsRestarting(containerID string) error {
50 36
 	cause := errors.Errorf("Container %s is restarting, wait until the container is running", containerID)
51
-	return stateConflictError{cause}
37
+	return errdefs.Conflict(cause)
52 38
 }
53 39
 
54 40
 func errExecNotFound(id string) error {
... ...
@@ -57,12 +44,12 @@ func errExecNotFound(id string) error {
57 57
 
58 58
 func errExecPaused(id string) error {
59 59
 	cause := errors.Errorf("Container %s is paused, unpause the container before exec", id)
60
-	return stateConflictError{cause}
60
+	return errdefs.Conflict(cause)
61 61
 }
62 62
 
63 63
 func errNotPaused(id string) error {
64 64
 	cause := errors.Errorf("Container %s is already paused", id)
65
-	return stateConflictError{cause}
65
+	return errdefs.Conflict(cause)
66 66
 }
67 67
 
68 68
 type nameConflictError struct {
... ...
@@ -76,34 +63,6 @@ func (e nameConflictError) Error() string {
76 76
 
77 77
 func (nameConflictError) Conflict() {}
78 78
 
79
-type validationError struct {
80
-	cause error
81
-}
82
-
83
-func (e validationError) Error() string {
84
-	return e.cause.Error()
85
-}
86
-
87
-func (e validationError) InvalidParameter() {}
88
-
89
-func (e validationError) Cause() error {
90
-	return e.cause
91
-}
92
-
93
-type notAllowedError struct {
94
-	cause error
95
-}
96
-
97
-func (e notAllowedError) Error() string {
98
-	return e.cause.Error()
99
-}
100
-
101
-func (e notAllowedError) Forbidden() {}
102
-
103
-func (e notAllowedError) Cause() error {
104
-	return e.cause
105
-}
106
-
107 79
 type containerNotModifiedError struct {
108 80
 	running bool
109 81
 }
... ...
@@ -117,20 +76,6 @@ func (e containerNotModifiedError) Error() string {
117 117
 
118 118
 func (e containerNotModifiedError) NotModified() {}
119 119
 
120
-type systemError struct {
121
-	cause error
122
-}
123
-
124
-func (e systemError) Error() string {
125
-	return e.cause.Error()
126
-}
127
-
128
-func (e systemError) SystemError() {}
129
-
130
-func (e systemError) Cause() error {
131
-	return e.cause
132
-}
133
-
134 120
 type invalidIdentifier string
135 121
 
136 122
 func (e invalidIdentifier) Error() string {
... ...
@@ -172,20 +117,6 @@ func (e invalidFilter) Error() string {
172 172
 
173 173
 func (e invalidFilter) InvalidParameter() {}
174 174
 
175
-type unknownError struct {
176
-	cause error
177
-}
178
-
179
-func (e unknownError) Error() string {
180
-	return e.cause.Error()
181
-}
182
-
183
-func (unknownError) Unknown() {}
184
-
185
-func (e unknownError) Cause() error {
186
-	return e.cause
187
-}
188
-
189 175
 type startInvalidConfigError string
190 176
 
191 177
 func (e startInvalidConfigError) Error() string {
... ...
@@ -199,7 +130,7 @@ func translateContainerdStartErr(cmd string, setExitCode func(int), err error) e
199 199
 	contains := func(s1, s2 string) bool {
200 200
 		return strings.Contains(strings.ToLower(s1), s2)
201 201
 	}
202
-	var retErr error = unknownError{errors.New(errDesc)}
202
+	var retErr = errdefs.Unknown(errors.New(errDesc))
203 203
 	// if we receive an internal error from the initial start of a container then lets
204 204
 	// return it instead of entering the restart loop
205 205
 	// set to 127 for container cmd not found/does not exist)
... ...
@@ -13,6 +13,7 @@ import (
13 13
 	"github.com/docker/docker/container"
14 14
 	"github.com/docker/docker/container/stream"
15 15
 	"github.com/docker/docker/daemon/exec"
16
+	"github.com/docker/docker/errdefs"
16 17
 	"github.com/docker/docker/pkg/pools"
17 18
 	"github.com/docker/docker/pkg/signal"
18 19
 	"github.com/docker/docker/pkg/term"
... ...
@@ -161,12 +162,12 @@ func (d *Daemon) ContainerExecStart(ctx context.Context, name string, stdin io.R
161 161
 	if ec.ExitCode != nil {
162 162
 		ec.Unlock()
163 163
 		err := fmt.Errorf("Error: Exec command %s has already run", ec.ID)
164
-		return stateConflictError{err}
164
+		return errdefs.Conflict(err)
165 165
 	}
166 166
 
167 167
 	if ec.Running {
168 168
 		ec.Unlock()
169
-		return stateConflictError{fmt.Errorf("Error: Exec command %s is already running", ec.ID)}
169
+		return errdefs.Conflict(fmt.Errorf("Error: Exec command %s is already running", ec.ID))
170 170
 	}
171 171
 	ec.Running = true
172 172
 	ec.Unlock()
... ...
@@ -267,7 +268,7 @@ func (d *Daemon) ContainerExecStart(ctx context.Context, name string, stdin io.R
267 267
 	case err := <-attachErr:
268 268
 		if err != nil {
269 269
 			if _, ok := err.(term.EscapeError); !ok {
270
-				return errors.Wrap(systemError{err}, "exec attach failed")
270
+				return errdefs.System(errors.Wrap(err, "exec attach failed"))
271 271
 			}
272 272
 			d.LogContainerEvent(c, "exec_detach")
273 273
 		}
... ...
@@ -6,6 +6,7 @@ import (
6 6
 	"runtime"
7 7
 
8 8
 	"github.com/docker/docker/container"
9
+	"github.com/docker/docker/errdefs"
9 10
 	"github.com/docker/docker/pkg/archive"
10 11
 	"github.com/docker/docker/pkg/ioutils"
11 12
 )
... ...
@@ -24,12 +25,12 @@ func (daemon *Daemon) ContainerExport(name string, out io.Writer) error {
24 24
 
25 25
 	if container.IsDead() {
26 26
 		err := fmt.Errorf("You cannot export container %s which is Dead", container.ID)
27
-		return stateConflictError{err}
27
+		return errdefs.Conflict(err)
28 28
 	}
29 29
 
30 30
 	if container.IsRemovalInProgress() {
31 31
 		err := fmt.Errorf("You cannot export container %s which is being removed", container.ID)
32
-		return stateConflictError{err}
32
+		return errdefs.Conflict(err)
33 33
 	}
34 34
 
35 35
 	data, err := daemon.containerExport(container)
... ...
@@ -1,6 +1,6 @@
1 1
 package quota
2 2
 
3
-import "github.com/docker/docker/api/errdefs"
3
+import "github.com/docker/docker/errdefs"
4 4
 
5 5
 var (
6 6
 	_ errdefs.ErrNotImplemented = (*errQuotaNotSupported)(nil)
... ...
@@ -5,6 +5,7 @@ import (
5 5
 	"runtime"
6 6
 
7 7
 	"github.com/docker/distribution/reference"
8
+	"github.com/docker/docker/errdefs"
8 9
 	"github.com/docker/docker/image"
9 10
 )
10 11
 
... ...
@@ -28,7 +29,7 @@ func (e errImageDoesNotExist) NotFound() {}
28 28
 func (daemon *Daemon) GetImageIDAndOS(refOrID string) (image.ID, string, error) {
29 29
 	ref, err := reference.ParseAnyReference(refOrID)
30 30
 	if err != nil {
31
-		return "", "", validationError{err}
31
+		return "", "", errdefs.InvalidParameter(err)
32 32
 	}
33 33
 	namedRef, ok := ref.(reference.Named)
34 34
 	if !ok {
... ...
@@ -8,6 +8,7 @@ import (
8 8
 	"github.com/docker/distribution/reference"
9 9
 	"github.com/docker/docker/api/types"
10 10
 	"github.com/docker/docker/container"
11
+	"github.com/docker/docker/errdefs"
11 12
 	"github.com/docker/docker/image"
12 13
 	"github.com/docker/docker/pkg/stringid"
13 14
 	"github.com/pkg/errors"
... ...
@@ -85,7 +86,7 @@ func (daemon *Daemon) ImageDelete(imageRef string, force, prune bool) ([]types.I
85 85
 				// we really want to avoid that the client must
86 86
 				// explicitly force its removal.
87 87
 				err := errors.Errorf("conflict: unable to remove repository reference %q (must force) - container %s is using its referenced image %s", imageRef, stringid.TruncateID(container.ID), stringid.TruncateID(imgID.String()))
88
-				return nil, stateConflictError{err}
88
+				return nil, errdefs.Conflict(err)
89 89
 			}
90 90
 		}
91 91
 
... ...
@@ -10,6 +10,7 @@ import (
10 10
 	"github.com/docker/docker/api/types"
11 11
 	"github.com/docker/docker/distribution"
12 12
 	progressutils "github.com/docker/docker/distribution/utils"
13
+	"github.com/docker/docker/errdefs"
13 14
 	"github.com/docker/docker/pkg/progress"
14 15
 	"github.com/docker/docker/registry"
15 16
 	"github.com/opencontainers/go-digest"
... ...
@@ -26,7 +27,7 @@ func (daemon *Daemon) PullImage(ctx context.Context, image, tag, platform string
26 26
 
27 27
 	ref, err := reference.ParseNormalizedNamed(image)
28 28
 	if err != nil {
29
-		return validationError{err}
29
+		return errdefs.InvalidParameter(err)
30 30
 	}
31 31
 
32 32
 	if tag != "" {
... ...
@@ -39,7 +40,7 @@ func (daemon *Daemon) PullImage(ctx context.Context, image, tag, platform string
39 39
 			ref, err = reference.WithTag(ref, tag)
40 40
 		}
41 41
 		if err != nil {
42
-			return validationError{err}
42
+			return errdefs.InvalidParameter(err)
43 43
 		}
44 44
 	}
45 45
 
... ...
@@ -96,7 +97,7 @@ func (daemon *Daemon) GetRepository(ctx context.Context, ref reference.Named, au
96 96
 	}
97 97
 	// makes sure name is not empty or `scratch`
98 98
 	if err := distribution.ValidateRepoName(repoInfo.Name); err != nil {
99
-		return nil, false, validationError{err}
99
+		return nil, false, errdefs.InvalidParameter(err)
100 100
 	}
101 101
 
102 102
 	// get endpoints
... ...
@@ -14,6 +14,7 @@ import (
14 14
 	"github.com/docker/docker/builder/dockerfile"
15 15
 	"github.com/docker/docker/builder/remotecontext"
16 16
 	"github.com/docker/docker/dockerversion"
17
+	"github.com/docker/docker/errdefs"
17 18
 	"github.com/docker/docker/image"
18 19
 	"github.com/docker/docker/layer"
19 20
 	"github.com/docker/docker/pkg/archive"
... ...
@@ -42,16 +43,16 @@ func (daemon *Daemon) ImportImage(src string, repository, os string, tag string,
42 42
 		var err error
43 43
 		newRef, err = reference.ParseNormalizedNamed(repository)
44 44
 		if err != nil {
45
-			return validationError{err}
45
+			return errdefs.InvalidParameter(err)
46 46
 		}
47 47
 		if _, isCanonical := newRef.(reference.Canonical); isCanonical {
48
-			return validationError{errors.New("cannot import digest reference")}
48
+			return errdefs.InvalidParameter(errors.New("cannot import digest reference"))
49 49
 		}
50 50
 
51 51
 		if tag != "" {
52 52
 			newRef, err = reference.WithTag(newRef, tag)
53 53
 			if err != nil {
54
-				return validationError{err}
54
+				return errdefs.InvalidParameter(err)
55 55
 			}
56 56
 		}
57 57
 	}
... ...
@@ -69,7 +70,7 @@ func (daemon *Daemon) ImportImage(src string, repository, os string, tag string,
69 69
 		}
70 70
 		u, err := url.Parse(src)
71 71
 		if err != nil {
72
-			return validationError{err}
72
+			return errdefs.InvalidParameter(err)
73 73
 		}
74 74
 
75 75
 		resp, err = remotecontext.GetWithStatusError(u.String())
... ...
@@ -11,6 +11,7 @@ import (
11 11
 	"github.com/docker/docker/api/types/versions/v1p20"
12 12
 	"github.com/docker/docker/container"
13 13
 	"github.com/docker/docker/daemon/network"
14
+	"github.com/docker/docker/errdefs"
14 15
 	volumestore "github.com/docker/docker/volume/store"
15 16
 	"github.com/docker/go-connections/nat"
16 17
 )
... ...
@@ -188,7 +189,7 @@ func (daemon *Daemon) getInspectData(container *container.Container) (*types.Con
188 188
 	// could have been removed, it will cause error if we try to get the metadata,
189 189
 	// we can ignore the error if the container is dead.
190 190
 	if err != nil && !container.Dead {
191
-		return nil, systemError{err}
191
+		return nil, errdefs.System(err)
192 192
 	}
193 193
 	contJSONBase.GraphDriver.Data = graphDriverData
194 194
 
... ...
@@ -232,7 +233,7 @@ func (daemon *Daemon) VolumeInspect(name string) (*types.Volume, error) {
232 232
 		if volumestore.IsNotExist(err) {
233 233
 			return nil, volumeNotFound(name)
234 234
 		}
235
-		return nil, systemError{err}
235
+		return nil, errdefs.System(err)
236 236
 	}
237 237
 	apiV := volumeToAPIType(v)
238 238
 	apiV.Mountpoint = v.Path()
... ...
@@ -7,8 +7,8 @@ import (
7 7
 	"syscall"
8 8
 	"time"
9 9
 
10
-	"github.com/docker/docker/api/errdefs"
11 10
 	containerpkg "github.com/docker/docker/container"
11
+	"github.com/docker/docker/errdefs"
12 12
 	"github.com/docker/docker/libcontainerd"
13 13
 	"github.com/docker/docker/pkg/signal"
14 14
 	"github.com/pkg/errors"
... ...
@@ -9,6 +9,7 @@ import (
9 9
 	"github.com/docker/docker/api/types"
10 10
 	"github.com/docker/docker/api/types/filters"
11 11
 	"github.com/docker/docker/container"
12
+	"github.com/docker/docker/errdefs"
12 13
 	"github.com/docker/docker/image"
13 14
 	"github.com/docker/docker/volume"
14 15
 	"github.com/docker/go-connections/nat"
... ...
@@ -290,7 +291,7 @@ func (daemon *Daemon) foldFilter(view container.View, config *types.ContainerLis
290 290
 
291 291
 	err = psFilters.WalkValues("health", func(value string) error {
292 292
 		if !container.IsValidHealthString(value) {
293
-			return validationError{errors.Errorf("Unrecognised filter value for health: %s", value)}
293
+			return errdefs.InvalidParameter(errors.Errorf("Unrecognised filter value for health: %s", value))
294 294
 		}
295 295
 
296 296
 		return nil
... ...
@@ -13,6 +13,7 @@ import (
13 13
 	timetypes "github.com/docker/docker/api/types/time"
14 14
 	"github.com/docker/docker/container"
15 15
 	"github.com/docker/docker/daemon/logger"
16
+	"github.com/docker/docker/errdefs"
16 17
 	"github.com/sirupsen/logrus"
17 18
 )
18 19
 
... ...
@@ -30,7 +31,7 @@ func (daemon *Daemon) ContainerLogs(ctx context.Context, containerName string, c
30 30
 	})
31 31
 
32 32
 	if !(config.ShowStdout || config.ShowStderr) {
33
-		return nil, false, validationError{errors.New("You must choose at least one stream")}
33
+		return nil, false, errdefs.InvalidParameter(errors.New("You must choose at least one stream"))
34 34
 	}
35 35
 	container, err := daemon.GetContainer(containerName)
36 36
 	if err != nil {
... ...
@@ -38,7 +39,7 @@ func (daemon *Daemon) ContainerLogs(ctx context.Context, containerName string, c
38 38
 	}
39 39
 
40 40
 	if container.RemovalInProgress || container.Dead {
41
-		return nil, false, stateConflictError{errors.New("can not get logs from container which is dead or marked for removal")}
41
+		return nil, false, errdefs.Conflict(errors.New("can not get logs from container which is dead or marked for removal"))
42 42
 	}
43 43
 
44 44
 	if container.HostConfig.LogConfig.Type == "none" {
... ...
@@ -6,6 +6,7 @@ import (
6 6
 
7 7
 	"github.com/docker/docker/container"
8 8
 	"github.com/docker/docker/daemon/names"
9
+	"github.com/docker/docker/errdefs"
9 10
 	"github.com/docker/docker/pkg/namesgenerator"
10 11
 	"github.com/docker/docker/pkg/stringid"
11 12
 	"github.com/pkg/errors"
... ...
@@ -56,7 +57,7 @@ func (daemon *Daemon) generateIDAndName(name string) (string, string, error) {
56 56
 
57 57
 func (daemon *Daemon) reserveName(id, name string) (string, error) {
58 58
 	if !validContainerNamePattern.MatchString(strings.TrimPrefix(name, "/")) {
59
-		return "", validationError{errors.Errorf("Invalid container name (%s), only %s are allowed", name, validContainerNameChars)}
59
+		return "", errdefs.InvalidParameter(errors.Errorf("Invalid container name (%s), only %s are allowed", name, validContainerNameChars))
60 60
 	}
61 61
 	if name[0] != '/' {
62 62
 		name = "/" + name
... ...
@@ -11,6 +11,7 @@ import (
11 11
 	"github.com/docker/docker/api/types"
12 12
 	"github.com/docker/docker/api/types/network"
13 13
 	clustertypes "github.com/docker/docker/daemon/cluster/provider"
14
+	"github.com/docker/docker/errdefs"
14 15
 	"github.com/docker/docker/pkg/plugingetter"
15 16
 	"github.com/docker/docker/runconfig"
16 17
 	"github.com/docker/libnetwork"
... ...
@@ -52,13 +53,17 @@ func (daemon *Daemon) FindUniqueNetwork(term string) (libnetwork.Network, error)
52 52
 	case len(listByFullName) == 1:
53 53
 		return listByFullName[0], nil
54 54
 	case len(listByFullName) > 1:
55
-		return nil, fmt.Errorf("network %s is ambiguous (%d matches found based on name)", term, len(listByFullName))
55
+		return nil, errdefs.InvalidParameter(errors.Errorf("network %s is ambiguous (%d matches found on name)", term, len(listByFullName)))
56 56
 	case len(listByPartialID) == 1:
57 57
 		return listByPartialID[0], nil
58 58
 	case len(listByPartialID) > 1:
59
-		return nil, fmt.Errorf("network %s is ambiguous (%d matches found based on ID prefix)", term, len(listByPartialID))
59
+		return nil, errdefs.InvalidParameter(errors.Errorf("network %s is ambiguous (%d matches found based on ID prefix)", term, len(listByPartialID)))
60 60
 	}
61
-	return nil, libnetwork.ErrNoSuchNetwork(term)
61
+
62
+	// Be very careful to change the error type here, the
63
+	// libnetwork.ErrNoSuchNetwork error is used by the controller
64
+	// to retry the creation of the network as managed through the swarm manager
65
+	return nil, errdefs.NotFound(libnetwork.ErrNoSuchNetwork(term))
62 66
 }
63 67
 
64 68
 // GetNetworkByID function returns a network whose ID matches the given ID.
... ...
@@ -264,7 +269,7 @@ func (daemon *Daemon) CreateNetwork(create types.NetworkCreateRequest) (*types.N
264 264
 func (daemon *Daemon) createNetwork(create types.NetworkCreateRequest, id string, agent bool) (*types.NetworkCreateResponse, error) {
265 265
 	if runconfig.IsPreDefinedNetwork(create.Name) && !agent {
266 266
 		err := fmt.Errorf("%s is a pre-defined network and cannot be created", create.Name)
267
-		return nil, notAllowedError{err}
267
+		return nil, errdefs.Forbidden(err)
268 268
 	}
269 269
 
270 270
 	var warning string
... ...
@@ -522,7 +527,7 @@ func (daemon *Daemon) deleteLoadBalancerSandbox(n libnetwork.Network) {
522 522
 func (daemon *Daemon) deleteNetwork(nw libnetwork.Network, dynamic bool) error {
523 523
 	if runconfig.IsPreDefinedNetwork(nw.Name()) && !dynamic {
524 524
 		err := fmt.Errorf("%s is a pre-defined network and cannot be removed", nw.Name())
525
-		return notAllowedError{err}
525
+		return errdefs.Forbidden(err)
526 526
 	}
527 527
 
528 528
 	if dynamic && !nw.Info().Dynamic() {
... ...
@@ -532,7 +537,7 @@ func (daemon *Daemon) deleteNetwork(nw libnetwork.Network, dynamic bool) error {
532 532
 			return nil
533 533
 		}
534 534
 		err := fmt.Errorf("%s is not a dynamic network", nw.Name())
535
-		return notAllowedError{err}
535
+		return errdefs.Forbidden(err)
536 536
 	}
537 537
 
538 538
 	if err := nw.Delete(); err != nil {
... ...
@@ -4,6 +4,7 @@ import (
4 4
 	"strings"
5 5
 
6 6
 	dockercontainer "github.com/docker/docker/container"
7
+	"github.com/docker/docker/errdefs"
7 8
 	"github.com/docker/libnetwork"
8 9
 	"github.com/pkg/errors"
9 10
 	"github.com/sirupsen/logrus"
... ...
@@ -19,7 +20,7 @@ func (daemon *Daemon) ContainerRename(oldName, newName string) error {
19 19
 	)
20 20
 
21 21
 	if oldName == "" || newName == "" {
22
-		return validationError{errors.New("Neither old nor new names may be empty")}
22
+		return errdefs.InvalidParameter(errors.New("Neither old nor new names may be empty"))
23 23
 	}
24 24
 
25 25
 	if newName[0] != '/' {
... ...
@@ -38,13 +39,13 @@ func (daemon *Daemon) ContainerRename(oldName, newName string) error {
38 38
 	oldIsAnonymousEndpoint := container.NetworkSettings.IsAnonymousEndpoint
39 39
 
40 40
 	if oldName == newName {
41
-		return validationError{errors.New("Renaming a container with the same name as its current name")}
41
+		return errdefs.InvalidParameter(errors.New("Renaming a container with the same name as its current name"))
42 42
 	}
43 43
 
44 44
 	links := map[string]*dockercontainer.Container{}
45 45
 	for k, v := range daemon.linkIndex.children(container) {
46 46
 		if !strings.HasPrefix(k, oldName) {
47
-			return validationError{errors.Errorf("Linked container %s does not match parent %s", k, oldName)}
47
+			return errdefs.InvalidParameter(errors.Errorf("Linked container %s does not match parent %s", k, oldName))
48 48
 		}
49 49
 		links[strings.TrimPrefix(k, oldName)] = v
50 50
 	}
... ...
@@ -8,6 +8,7 @@ import (
8 8
 	"github.com/docker/docker/api/types"
9 9
 	containertypes "github.com/docker/docker/api/types/container"
10 10
 	"github.com/docker/docker/container"
11
+	"github.com/docker/docker/errdefs"
11 12
 	"github.com/pkg/errors"
12 13
 	"github.com/sirupsen/logrus"
13 14
 )
... ...
@@ -15,7 +16,7 @@ import (
15 15
 // ContainerStart starts a container.
16 16
 func (daemon *Daemon) ContainerStart(name string, hostConfig *containertypes.HostConfig, checkpoint string, checkpointDir string) error {
17 17
 	if checkpoint != "" && !daemon.HasExperimental() {
18
-		return validationError{errors.New("checkpoint is only supported in experimental mode")}
18
+		return errdefs.InvalidParameter(errors.New("checkpoint is only supported in experimental mode"))
19 19
 	}
20 20
 
21 21
 	container, err := daemon.GetContainer(name)
... ...
@@ -28,7 +29,7 @@ func (daemon *Daemon) ContainerStart(name string, hostConfig *containertypes.Hos
28 28
 		defer container.Unlock()
29 29
 
30 30
 		if container.Paused {
31
-			return stateConflictError{errors.New("cannot start a paused container, try unpause instead")}
31
+			return errdefs.Conflict(errors.New("cannot start a paused container, try unpause instead"))
32 32
 		}
33 33
 
34 34
 		if container.Running {
... ...
@@ -36,7 +37,7 @@ func (daemon *Daemon) ContainerStart(name string, hostConfig *containertypes.Hos
36 36
 		}
37 37
 
38 38
 		if container.RemovalInProgress || container.Dead {
39
-			return stateConflictError{errors.New("container is marked for removal and cannot be started")}
39
+			return errdefs.Conflict(errors.New("container is marked for removal and cannot be started"))
40 40
 		}
41 41
 		return nil
42 42
 	}
... ...
@@ -53,13 +54,13 @@ func (daemon *Daemon) ContainerStart(name string, hostConfig *containertypes.Hos
53 53
 			logrus.Warn("DEPRECATED: Setting host configuration options when the container starts is deprecated and has been removed in Docker 1.12")
54 54
 			oldNetworkMode := container.HostConfig.NetworkMode
55 55
 			if err := daemon.setSecurityOptions(container, hostConfig); err != nil {
56
-				return validationError{err}
56
+				return errdefs.InvalidParameter(err)
57 57
 			}
58 58
 			if err := daemon.mergeAndVerifyLogConfig(&hostConfig.LogConfig); err != nil {
59
-				return validationError{err}
59
+				return errdefs.InvalidParameter(err)
60 60
 			}
61 61
 			if err := daemon.setHostConfig(container, hostConfig); err != nil {
62
-				return validationError{err}
62
+				return errdefs.InvalidParameter(err)
63 63
 			}
64 64
 			newNetworkMode := container.HostConfig.NetworkMode
65 65
 			if string(oldNetworkMode) != string(newNetworkMode) {
... ...
@@ -67,27 +68,27 @@ func (daemon *Daemon) ContainerStart(name string, hostConfig *containertypes.Hos
67 67
 				// old networks. It is a deprecated feature and has been removed in Docker 1.12
68 68
 				container.NetworkSettings.Networks = nil
69 69
 				if err := container.CheckpointTo(daemon.containersReplica); err != nil {
70
-					return systemError{err}
70
+					return errdefs.System(err)
71 71
 				}
72 72
 			}
73 73
 			container.InitDNSHostConfig()
74 74
 		}
75 75
 	} else {
76 76
 		if hostConfig != nil {
77
-			return validationError{errors.New("Supplying a hostconfig on start is not supported. It should be supplied on create")}
77
+			return errdefs.InvalidParameter(errors.New("Supplying a hostconfig on start is not supported. It should be supplied on create"))
78 78
 		}
79 79
 	}
80 80
 
81 81
 	// check if hostConfig is in line with the current system settings.
82 82
 	// It may happen cgroups are umounted or the like.
83 83
 	if _, err = daemon.verifyContainerSettings(container.OS, container.HostConfig, nil, false); err != nil {
84
-		return validationError{err}
84
+		return errdefs.InvalidParameter(err)
85 85
 	}
86 86
 	// Adapt for old containers in case we have updates in this function and
87 87
 	// old containers never have chance to call the new function in create stage.
88 88
 	if hostConfig != nil {
89 89
 		if err := daemon.adaptContainerSettings(container.HostConfig, false); err != nil {
90
-			return validationError{err}
90
+			return errdefs.InvalidParameter(err)
91 91
 		}
92 92
 	}
93 93
 	return daemon.containerStart(container, checkpoint, checkpointDir, true)
... ...
@@ -107,12 +108,12 @@ func (daemon *Daemon) containerStart(container *container.Container, checkpoint
107 107
 	}
108 108
 
109 109
 	if container.RemovalInProgress || container.Dead {
110
-		return stateConflictError{errors.New("container is marked for removal and cannot be started")}
110
+		return errdefs.Conflict(errors.New("container is marked for removal and cannot be started"))
111 111
 	}
112 112
 
113 113
 	if checkpointDir != "" {
114 114
 		// TODO(mlaventure): how would we support that?
115
-		return notAllowedError{errors.New("custom checkpointdir is not supported")}
115
+		return errdefs.Forbidden(errors.New("custom checkpointdir is not supported"))
116 116
 	}
117 117
 
118 118
 	// if we encounter an error during start we need to ensure that any other
... ...
@@ -151,7 +152,7 @@ func (daemon *Daemon) containerStart(container *container.Container, checkpoint
151 151
 
152 152
 	spec, err := daemon.createSpec(container)
153 153
 	if err != nil {
154
-		return systemError{err}
154
+		return errdefs.System(err)
155 155
 	}
156 156
 
157 157
 	if resetRestartManager {
... ...
@@ -9,6 +9,7 @@ import (
9 9
 
10 10
 	"github.com/containerd/containerd/linux/runctypes"
11 11
 	"github.com/docker/docker/container"
12
+	"github.com/docker/docker/errdefs"
12 13
 	"github.com/pkg/errors"
13 14
 )
14 15
 
... ...
@@ -16,7 +17,7 @@ func (daemon *Daemon) getRuntimeScript(container *container.Container) (string,
16 16
 	name := container.HostConfig.Runtime
17 17
 	rt := daemon.configStore.GetRuntime(name)
18 18
 	if rt == nil {
19
-		return "", validationError{errors.Errorf("no such runtime '%s'", name)}
19
+		return "", errdefs.InvalidParameter(errors.Errorf("no such runtime '%s'", name))
20 20
 	}
21 21
 
22 22
 	if len(rt.Args) > 0 {
... ...
@@ -5,6 +5,7 @@ import (
5 5
 	"time"
6 6
 
7 7
 	containerpkg "github.com/docker/docker/container"
8
+	"github.com/docker/docker/errdefs"
8 9
 	"github.com/pkg/errors"
9 10
 	"github.com/sirupsen/logrus"
10 11
 )
... ...
@@ -28,7 +29,7 @@ func (daemon *Daemon) ContainerStop(name string, seconds *int) error {
28 28
 		seconds = &stopTimeout
29 29
 	}
30 30
 	if err := daemon.containerStop(container, *seconds); err != nil {
31
-		return errors.Wrapf(systemError{err}, "cannot stop container: %s", name)
31
+		return errdefs.System(errors.Wrapf(err, "cannot stop container: %s", name))
32 32
 	}
33 33
 	return nil
34 34
 }
... ...
@@ -5,6 +5,7 @@ import (
5 5
 	"fmt"
6 6
 
7 7
 	"github.com/docker/docker/api/types/container"
8
+	"github.com/docker/docker/errdefs"
8 9
 	"github.com/pkg/errors"
9 10
 )
10 11
 
... ...
@@ -19,7 +20,7 @@ func (daemon *Daemon) ContainerUpdate(name string, hostConfig *container.HostCon
19 19
 
20 20
 	warnings, err = daemon.verifyContainerSettings(c.OS, hostConfig, nil, true)
21 21
 	if err != nil {
22
-		return container.ContainerUpdateOKBody{Warnings: warnings}, validationError{err}
22
+		return container.ContainerUpdateOKBody{Warnings: warnings}, errdefs.InvalidParameter(err)
23 23
 	}
24 24
 
25 25
 	if err := daemon.update(name, hostConfig); err != nil {
... ...
@@ -80,7 +81,7 @@ func (daemon *Daemon) update(name string, hostConfig *container.HostConfig) erro
80 80
 		if err := daemon.containerd.UpdateResources(context.Background(), container.ID, toContainerdResources(hostConfig.Resources)); err != nil {
81 81
 			restoreConfig = true
82 82
 			// TODO: it would be nice if containerd responded with better errors here so we can classify this better.
83
-			return errCannotUpdate(container.ID, systemError{err})
83
+			return errCannotUpdate(container.ID, errdefs.System(err))
84 84
 		}
85 85
 	}
86 86
 
... ...
@@ -12,6 +12,7 @@ import (
12 12
 	containertypes "github.com/docker/docker/api/types/container"
13 13
 	mounttypes "github.com/docker/docker/api/types/mount"
14 14
 	"github.com/docker/docker/container"
15
+	"github.com/docker/docker/errdefs"
15 16
 	"github.com/docker/docker/volume"
16 17
 	"github.com/docker/docker/volume/drivers"
17 18
 	"github.com/pkg/errors"
... ...
@@ -175,7 +176,7 @@ func (daemon *Daemon) registerMountPoints(container *container.Container, hostCo
175 175
 	for _, cfg := range hostConfig.Mounts {
176 176
 		mp, err := parser.ParseMountSpec(cfg)
177 177
 		if err != nil {
178
-			return validationError{err}
178
+			return errdefs.InvalidParameter(err)
179 179
 		}
180 180
 
181 181
 		if binds[mp.Destination] {
... ...
@@ -13,6 +13,7 @@ import (
13 13
 	"github.com/docker/distribution/registry/client"
14 14
 	"github.com/docker/distribution/registry/client/auth"
15 15
 	"github.com/docker/docker/distribution/xfer"
16
+	"github.com/docker/docker/errdefs"
16 17
 	"github.com/sirupsen/logrus"
17 18
 )
18 19
 
... ...
@@ -85,20 +86,6 @@ func (e notFoundError) Cause() error {
85 85
 	return e.cause
86 86
 }
87 87
 
88
-type unknownError struct {
89
-	cause error
90
-}
91
-
92
-func (e unknownError) Error() string {
93
-	return e.cause.Error()
94
-}
95
-
96
-func (e unknownError) Cause() error {
97
-	return e.cause
98
-}
99
-
100
-func (e unknownError) Unknown() {}
101
-
102 88
 // TranslatePullError is used to convert an error from a registry pull
103 89
 // operation to an error representing the entire pull operation. Any error
104 90
 // information which is not used by the returned error gets output to
... ...
@@ -121,7 +108,7 @@ func TranslatePullError(err error, ref reference.Named) error {
121 121
 		return TranslatePullError(v.Err, ref)
122 122
 	}
123 123
 
124
-	return unknownError{err}
124
+	return errdefs.Unknown(err)
125 125
 }
126 126
 
127 127
 // continueOnError returns true if we should fallback to the next endpoint
128 128
new file mode 100644
... ...
@@ -0,0 +1,74 @@
0
+package errdefs
1
+
2
+// ErrNotFound signals that the requested object doesn't exist
3
+type ErrNotFound interface {
4
+	NotFound()
5
+}
6
+
7
+// ErrInvalidParameter signals that the user input is invalid
8
+type ErrInvalidParameter interface {
9
+	InvalidParameter()
10
+}
11
+
12
+// ErrConflict signals that some internal state conflicts with the requested action and can't be performed.
13
+// A change in state should be able to clear this error.
14
+type ErrConflict interface {
15
+	Conflict()
16
+}
17
+
18
+// ErrUnauthorized is used to signify that the user is not authorized to perform a specific action
19
+type ErrUnauthorized interface {
20
+	Unauthorized()
21
+}
22
+
23
+// ErrUnavailable signals that the requested action/subsystem is not available.
24
+type ErrUnavailable interface {
25
+	Unavailable()
26
+}
27
+
28
+// ErrForbidden signals that the requested action cannot be performed under any circumstances.
29
+// When a ErrForbidden is returned, the caller should never retry the action.
30
+type ErrForbidden interface {
31
+	Forbidden()
32
+}
33
+
34
+// ErrSystem signals that some internal error occurred.
35
+// An example of this would be a failed mount request.
36
+type ErrSystem interface {
37
+	ErrSystem()
38
+}
39
+
40
+// ErrNotModified signals that an action can't be performed because it's already in the desired state
41
+type ErrNotModified interface {
42
+	NotModified()
43
+}
44
+
45
+// ErrAlreadyExists is a special case of ErrConflict which signals that the desired object already exists
46
+type ErrAlreadyExists interface {
47
+	AlreadyExists()
48
+}
49
+
50
+// ErrNotImplemented signals that the requested action/feature is not implemented on the system as configured.
51
+type ErrNotImplemented interface {
52
+	NotImplemented()
53
+}
54
+
55
+// ErrUnknown signals that the kind of error that occurred is not known.
56
+type ErrUnknown interface {
57
+	Unknown()
58
+}
59
+
60
+// ErrCancelled signals that the action was cancelled.
61
+type ErrCancelled interface {
62
+	Cancelled()
63
+}
64
+
65
+// ErrDeadline signals that the deadline was reached before the action completed.
66
+type ErrDeadline interface {
67
+	DeadlineExceeded()
68
+}
69
+
70
+// ErrDataLoss indicates that data was lost or there is data corruption.
71
+type ErrDataLoss interface {
72
+	DataLoss()
73
+}
0 74
new file mode 100644
... ...
@@ -0,0 +1,8 @@
0
+// Package errdefs defines a set of error interfaces that packages should use for communicating classes of errors.
1
+// Errors that cross the package boundary should implement one (and only one) of these interfaces.
2
+//
3
+// Packages should not reference these interfaces directly, only implement them.
4
+// To check if a particular error implements one of these interfaces, there are helper
5
+// functions provided (e.g. `Is<SomeError>`) which can be used rather than asserting the interfaces directly.
6
+// If you must assert on these interfaces, be sure to check the causal chain (`err.Cause()`).
7
+package errdefs
0 8
new file mode 100644
... ...
@@ -0,0 +1,240 @@
0
+package errdefs
1
+
2
+import "context"
3
+
4
+type errNotFound struct{ error }
5
+
6
+func (errNotFound) NotFound() {}
7
+
8
+func (e errNotFound) Cause() error {
9
+	return e.error
10
+}
11
+
12
+// NotFound is a helper to create an error of the class with the same name from any error type
13
+func NotFound(err error) error {
14
+	if err == nil {
15
+		return nil
16
+	}
17
+	return errNotFound{err}
18
+}
19
+
20
+type errInvalidParameter struct{ error }
21
+
22
+func (errInvalidParameter) InvalidParameter() {}
23
+
24
+func (e errInvalidParameter) Cause() error {
25
+	return e.error
26
+}
27
+
28
+// InvalidParameter is a helper to create an error of the class with the same name from any error type
29
+func InvalidParameter(err error) error {
30
+	if err == nil {
31
+		return nil
32
+	}
33
+	return errInvalidParameter{err}
34
+}
35
+
36
+type errConflict struct{ error }
37
+
38
+func (errConflict) Conflict() {}
39
+
40
+func (e errConflict) Cause() error {
41
+	return e.error
42
+}
43
+
44
+// Conflict is a helper to create an error of the class with the same name from any error type
45
+func Conflict(err error) error {
46
+	if err == nil {
47
+		return nil
48
+	}
49
+	return errConflict{err}
50
+}
51
+
52
+type errUnauthorized struct{ error }
53
+
54
+func (errUnauthorized) Unauthorized() {}
55
+
56
+func (e errUnauthorized) Cause() error {
57
+	return e.error
58
+}
59
+
60
+// Unauthorized is a helper to create an error of the class with the same name from any error type
61
+func Unauthorized(err error) error {
62
+	if err == nil {
63
+		return nil
64
+	}
65
+	return errUnauthorized{err}
66
+}
67
+
68
+type errUnavailable struct{ error }
69
+
70
+func (errUnavailable) Unavailable() {}
71
+
72
+func (e errUnavailable) Cause() error {
73
+	return e.error
74
+}
75
+
76
+// Unavailable is a helper to create an error of the class with the same name from any error type
77
+func Unavailable(err error) error {
78
+	return errUnavailable{err}
79
+}
80
+
81
+type errForbidden struct{ error }
82
+
83
+func (errForbidden) Forbidden() {}
84
+
85
+func (e errForbidden) Cause() error {
86
+	return e.error
87
+}
88
+
89
+// Forbidden is a helper to create an error of the class with the same name from any error type
90
+func Forbidden(err error) error {
91
+	if err == nil {
92
+		return nil
93
+	}
94
+	return errForbidden{err}
95
+}
96
+
97
+type errSystem struct{ error }
98
+
99
+func (errSystem) System() {}
100
+
101
+func (e errSystem) Cause() error {
102
+	return e.error
103
+}
104
+
105
+// System is a helper to create an error of the class with the same name from any error type
106
+func System(err error) error {
107
+	if err == nil {
108
+		return nil
109
+	}
110
+	return errSystem{err}
111
+}
112
+
113
+type errNotModified struct{ error }
114
+
115
+func (errNotModified) NotModified() {}
116
+
117
+func (e errNotModified) Cause() error {
118
+	return e.error
119
+}
120
+
121
+// NotModified is a helper to create an error of the class with the same name from any error type
122
+func NotModified(err error) error {
123
+	if err == nil {
124
+		return nil
125
+	}
126
+	return errNotModified{err}
127
+}
128
+
129
+type errAlreadyExists struct{ error }
130
+
131
+func (errAlreadyExists) AlreadyExists() {}
132
+
133
+func (e errAlreadyExists) Cause() error {
134
+	return e.error
135
+}
136
+
137
+// AlreadyExists is a helper to create an error of the class with the same name from any error type
138
+func AlreadyExists(err error) error {
139
+	if err == nil {
140
+		return nil
141
+	}
142
+	return errAlreadyExists{err}
143
+}
144
+
145
+type errNotImplemented struct{ error }
146
+
147
+func (errNotImplemented) NotImplemented() {}
148
+
149
+func (e errNotImplemented) Cause() error {
150
+	return e.error
151
+}
152
+
153
+// NotImplemented is a helper to create an error of the class with the same name from any error type
154
+func NotImplemented(err error) error {
155
+	if err == nil {
156
+		return nil
157
+	}
158
+	return errNotImplemented{err}
159
+}
160
+
161
+type errUnknown struct{ error }
162
+
163
+func (errUnknown) Unknown() {}
164
+
165
+func (e errUnknown) Cause() error {
166
+	return e.error
167
+}
168
+
169
+// Unknown is a helper to create an error of the class with the same name from any error type
170
+func Unknown(err error) error {
171
+	if err == nil {
172
+		return nil
173
+	}
174
+	return errUnknown{err}
175
+}
176
+
177
+type errCancelled struct{ error }
178
+
179
+func (errCancelled) Cancelled() {}
180
+
181
+func (e errCancelled) Cause() error {
182
+	return e.error
183
+}
184
+
185
+// Cancelled is a helper to create an error of the class with the same name from any error type
186
+func Cancelled(err error) error {
187
+	if err == nil {
188
+		return nil
189
+	}
190
+	return errCancelled{err}
191
+}
192
+
193
+type errDeadline struct{ error }
194
+
195
+func (errDeadline) DeadlineExceeded() {}
196
+
197
+func (e errDeadline) Cause() error {
198
+	return e.error
199
+}
200
+
201
+// Deadline is a helper to create an error of the class with the same name from any error type
202
+func Deadline(err error) error {
203
+	if err == nil {
204
+		return nil
205
+	}
206
+	return errDeadline{err}
207
+}
208
+
209
+type errDataLoss struct{ error }
210
+
211
+func (errDataLoss) DataLoss() {}
212
+
213
+func (e errDataLoss) Cause() error {
214
+	return e.error
215
+}
216
+
217
+// DataLoss is a helper to create an error of the class with the same name from any error type
218
+func DataLoss(err error) error {
219
+	if err == nil {
220
+		return nil
221
+	}
222
+	return errDataLoss{err}
223
+}
224
+
225
+// FromContext returns the error class from the passed in context
226
+func FromContext(ctx context.Context) error {
227
+	e := ctx.Err()
228
+	if e == nil {
229
+		return nil
230
+	}
231
+
232
+	if e == context.Canceled {
233
+		return Cancelled(e)
234
+	}
235
+	if e == context.DeadlineExceeded {
236
+		return Deadline(e)
237
+	}
238
+	return Unknown(e)
239
+}
0 240
new file mode 100644
... ...
@@ -0,0 +1,132 @@
0
+package errdefs
1
+
2
+import (
3
+	"errors"
4
+	"testing"
5
+)
6
+
7
+var errTest = errors.New("this is a test")
8
+
9
+type causal interface {
10
+	Cause() error
11
+}
12
+
13
+func TestNotFound(t *testing.T) {
14
+	e := NotFound(errTest)
15
+	if !IsNotFound(e) {
16
+		t.Fatalf("expected not found error, got: %T", e)
17
+	}
18
+	if cause := e.(causal).Cause(); cause != errTest {
19
+		t.Fatalf("causual should be errTest, got: %v", cause)
20
+	}
21
+}
22
+
23
+func TestConflict(t *testing.T) {
24
+	e := Conflict(errTest)
25
+	if !IsConflict(e) {
26
+		t.Fatalf("expected conflcit error, got: %T", e)
27
+	}
28
+	if cause := e.(causal).Cause(); cause != errTest {
29
+		t.Fatalf("causual should be errTest, got: %v", cause)
30
+	}
31
+}
32
+
33
+func TestForbidden(t *testing.T) {
34
+	e := Forbidden(errTest)
35
+	if !IsForbidden(e) {
36
+		t.Fatalf("expected forbidden error, got: %T", e)
37
+	}
38
+	if cause := e.(causal).Cause(); cause != errTest {
39
+		t.Fatalf("causual should be errTest, got: %v", cause)
40
+	}
41
+}
42
+
43
+func TestInvalidParameter(t *testing.T) {
44
+	e := InvalidParameter(errTest)
45
+	if !IsInvalidParameter(e) {
46
+		t.Fatalf("expected invalid argument error, got %T", e)
47
+	}
48
+	if cause := e.(causal).Cause(); cause != errTest {
49
+		t.Fatalf("causual should be errTest, got: %v", cause)
50
+	}
51
+}
52
+
53
+func TestNotImplemented(t *testing.T) {
54
+	e := NotImplemented(errTest)
55
+	if !IsNotImplemented(e) {
56
+		t.Fatalf("expected not implemented error, got %T", e)
57
+	}
58
+	if cause := e.(causal).Cause(); cause != errTest {
59
+		t.Fatalf("causual should be errTest, got: %v", cause)
60
+	}
61
+}
62
+
63
+func TestNotModified(t *testing.T) {
64
+	e := NotModified(errTest)
65
+	if !IsNotModified(e) {
66
+		t.Fatalf("expected not modified error, got %T", e)
67
+	}
68
+	if cause := e.(causal).Cause(); cause != errTest {
69
+		t.Fatalf("causual should be errTest, got: %v", cause)
70
+	}
71
+}
72
+
73
+func TestAlreadyExists(t *testing.T) {
74
+	e := AlreadyExists(errTest)
75
+	if !IsAlreadyExists(e) {
76
+		t.Fatalf("expected already exists error, got %T", e)
77
+	}
78
+	if cause := e.(causal).Cause(); cause != errTest {
79
+		t.Fatalf("causual should be errTest, got: %v", cause)
80
+	}
81
+}
82
+
83
+func TestUnauthorized(t *testing.T) {
84
+	e := Unauthorized(errTest)
85
+	if !IsUnauthorized(e) {
86
+		t.Fatalf("expected unauthorized error, got %T", e)
87
+	}
88
+	if cause := e.(causal).Cause(); cause != errTest {
89
+		t.Fatalf("causual should be errTest, got: %v", cause)
90
+	}
91
+}
92
+
93
+func TestUnknown(t *testing.T) {
94
+	e := Unknown(errTest)
95
+	if !IsUnknown(e) {
96
+		t.Fatalf("expected unknown error, got %T", e)
97
+	}
98
+	if cause := e.(causal).Cause(); cause != errTest {
99
+		t.Fatalf("causual should be errTest, got: %v", cause)
100
+	}
101
+}
102
+
103
+func TestCancelled(t *testing.T) {
104
+	e := Cancelled(errTest)
105
+	if !IsCancelled(e) {
106
+		t.Fatalf("expected canclled error, got %T", e)
107
+	}
108
+	if cause := e.(causal).Cause(); cause != errTest {
109
+		t.Fatalf("causual should be errTest, got: %v", cause)
110
+	}
111
+}
112
+
113
+func TestDeadline(t *testing.T) {
114
+	e := Deadline(errTest)
115
+	if !IsDeadline(e) {
116
+		t.Fatalf("expected deadline error, got %T", e)
117
+	}
118
+	if cause := e.(causal).Cause(); cause != errTest {
119
+		t.Fatalf("causual should be errTest, got: %v", cause)
120
+	}
121
+}
122
+
123
+func TestIsDataLoss(t *testing.T) {
124
+	e := DataLoss(errTest)
125
+	if !IsDataLoss(e) {
126
+		t.Fatalf("expected data loss error, got %T", e)
127
+	}
128
+	if cause := e.(causal).Cause(); cause != errTest {
129
+		t.Fatalf("causual should be errTest, got: %v", cause)
130
+	}
131
+}
0 132
new file mode 100644
... ...
@@ -0,0 +1,114 @@
0
+package errdefs
1
+
2
+type causer interface {
3
+	Cause() error
4
+}
5
+
6
+func getImplementer(err error) error {
7
+	switch e := err.(type) {
8
+	case
9
+		ErrNotFound,
10
+		ErrInvalidParameter,
11
+		ErrConflict,
12
+		ErrUnauthorized,
13
+		ErrUnavailable,
14
+		ErrForbidden,
15
+		ErrSystem,
16
+		ErrNotModified,
17
+		ErrAlreadyExists,
18
+		ErrNotImplemented,
19
+		ErrCancelled,
20
+		ErrDeadline,
21
+		ErrDataLoss,
22
+		ErrUnknown:
23
+		return e
24
+	case causer:
25
+		return getImplementer(e.Cause())
26
+	default:
27
+		return err
28
+	}
29
+}
30
+
31
+// IsNotFound returns if the passed in error is an ErrNotFound
32
+func IsNotFound(err error) bool {
33
+	_, ok := getImplementer(err).(ErrNotFound)
34
+	return ok
35
+}
36
+
37
+// IsInvalidParameter returns if the passed in error is an ErrInvalidParameter
38
+func IsInvalidParameter(err error) bool {
39
+	_, ok := getImplementer(err).(ErrInvalidParameter)
40
+	return ok
41
+}
42
+
43
+// IsConflict returns if the passed in error is an ErrConflict
44
+func IsConflict(err error) bool {
45
+	_, ok := getImplementer(err).(ErrConflict)
46
+	return ok
47
+}
48
+
49
+// IsUnauthorized returns if the the passed in error is an ErrUnauthorized
50
+func IsUnauthorized(err error) bool {
51
+	_, ok := getImplementer(err).(ErrUnauthorized)
52
+	return ok
53
+}
54
+
55
+// IsUnavailable returns if the passed in error is an ErrUnavailable
56
+func IsUnavailable(err error) bool {
57
+	_, ok := getImplementer(err).(ErrUnavailable)
58
+	return ok
59
+}
60
+
61
+// IsForbidden returns if the passed in error is an ErrForbidden
62
+func IsForbidden(err error) bool {
63
+	_, ok := getImplementer(err).(ErrForbidden)
64
+	return ok
65
+}
66
+
67
+// IsSystem returns if the passed in error is an ErrSystem
68
+func IsSystem(err error) bool {
69
+	_, ok := getImplementer(err).(ErrSystem)
70
+	return ok
71
+}
72
+
73
+// IsNotModified returns if the passed in error is a NotModified error
74
+func IsNotModified(err error) bool {
75
+	_, ok := getImplementer(err).(ErrNotModified)
76
+	return ok
77
+}
78
+
79
+// IsAlreadyExists returns if the passed in error is a AlreadyExists error
80
+func IsAlreadyExists(err error) bool {
81
+	_, ok := getImplementer(err).(ErrAlreadyExists)
82
+	return ok
83
+}
84
+
85
+// IsNotImplemented returns if the passed in error is an ErrNotImplemented
86
+func IsNotImplemented(err error) bool {
87
+	_, ok := getImplementer(err).(ErrNotImplemented)
88
+	return ok
89
+}
90
+
91
+// IsUnknown returns if the passed in error is an ErrUnknown
92
+func IsUnknown(err error) bool {
93
+	_, ok := getImplementer(err).(ErrUnknown)
94
+	return ok
95
+}
96
+
97
+// IsCancelled returns if the passed in error is an ErrCancelled
98
+func IsCancelled(err error) bool {
99
+	_, ok := getImplementer(err).(ErrCancelled)
100
+	return ok
101
+}
102
+
103
+// IsDeadline returns if the passed in error is an ErrDeadline
104
+func IsDeadline(err error) bool {
105
+	_, ok := getImplementer(err).(ErrDeadline)
106
+	return ok
107
+}
108
+
109
+// IsDataLoss returns if the passed in error is an ErrDataLoss
110
+func IsDataLoss(err error) bool {
111
+	_, ok := getImplementer(err).(ErrDataLoss)
112
+	return ok
113
+}
... ...
@@ -27,10 +27,11 @@ import (
27 27
 	"github.com/containerd/containerd/archive"
28 28
 	"github.com/containerd/containerd/cio"
29 29
 	"github.com/containerd/containerd/content"
30
-	"github.com/containerd/containerd/errdefs"
30
+	containerderrors "github.com/containerd/containerd/errdefs"
31 31
 	"github.com/containerd/containerd/images"
32 32
 	"github.com/containerd/containerd/linux/runctypes"
33 33
 	"github.com/containerd/typeurl"
34
+	"github.com/docker/docker/errdefs"
34 35
 	"github.com/docker/docker/pkg/ioutils"
35 36
 	"github.com/opencontainers/image-spec/specs-go/v1"
36 37
 	specs "github.com/opencontainers/runtime-spec/specs-go"
... ...
@@ -181,7 +182,7 @@ func (c *client) Create(ctx context.Context, id string, ociSpec *specs.Spec, run
181 181
 
182 182
 	bdir, err := prepareBundleDir(filepath.Join(c.stateDir, id), ociSpec)
183 183
 	if err != nil {
184
-		return wrapSystemError(errors.Wrap(err, "prepare bundle dir failed"))
184
+		return errdefs.System(errors.Wrap(err, "prepare bundle dir failed"))
185 185
 	}
186 186
 
187 187
 	c.logger.WithField("bundle", bdir).WithField("root", ociSpec.Root.Path).Debug("bundle dir created")
... ...
@@ -536,11 +537,11 @@ func (c *client) CreateCheckpoint(ctx context.Context, containerID, checkpointDi
536 536
 
537 537
 	b, err := content.ReadBlob(ctx, c.remote.ContentStore(), img.Target().Digest)
538 538
 	if err != nil {
539
-		return wrapSystemError(errors.Wrapf(err, "failed to retrieve checkpoint data"))
539
+		return errdefs.System(errors.Wrapf(err, "failed to retrieve checkpoint data"))
540 540
 	}
541 541
 	var index v1.Index
542 542
 	if err := json.Unmarshal(b, &index); err != nil {
543
-		return wrapSystemError(errors.Wrapf(err, "failed to decode checkpoint data"))
543
+		return errdefs.System(errors.Wrapf(err, "failed to decode checkpoint data"))
544 544
 	}
545 545
 
546 546
 	var cpDesc *v1.Descriptor
... ...
@@ -551,17 +552,17 @@ func (c *client) CreateCheckpoint(ctx context.Context, containerID, checkpointDi
551 551
 		}
552 552
 	}
553 553
 	if cpDesc == nil {
554
-		return wrapSystemError(errors.Wrapf(err, "invalid checkpoint"))
554
+		return errdefs.System(errors.Wrapf(err, "invalid checkpoint"))
555 555
 	}
556 556
 
557 557
 	rat, err := c.remote.ContentStore().ReaderAt(ctx, cpDesc.Digest)
558 558
 	if err != nil {
559
-		return wrapSystemError(errors.Wrapf(err, "failed to get checkpoint reader"))
559
+		return errdefs.System(errors.Wrapf(err, "failed to get checkpoint reader"))
560 560
 	}
561 561
 	defer rat.Close()
562 562
 	_, err = archive.Apply(ctx, checkpointDir, content.NewReader(rat))
563 563
 	if err != nil {
564
-		return wrapSystemError(errors.Wrapf(err, "failed to read checkpoint reader"))
564
+		return errdefs.System(errors.Wrapf(err, "failed to read checkpoint reader"))
565 565
 	}
566 566
 
567 567
 	return err
... ...
@@ -847,14 +848,14 @@ func wrapError(err error) error {
847 847
 	switch {
848 848
 	case err == nil:
849 849
 		return nil
850
-	case errdefs.IsNotFound(err):
851
-		return wrapNotFoundError(err)
850
+	case containerderrors.IsNotFound(err):
851
+		return errdefs.NotFound(err)
852 852
 	}
853 853
 
854 854
 	msg := err.Error()
855 855
 	for _, s := range []string{"container does not exist", "not found", "no such container"} {
856 856
 		if strings.Contains(msg, s) {
857
-			return wrapNotFoundError(err)
857
+			return errdefs.NotFound(err)
858 858
 		}
859 859
 	}
860 860
 	return err
... ...
@@ -1,46 +1,13 @@
1 1
 package libcontainerd
2 2
 
3
-import "errors"
3
+import (
4
+	"errors"
4 5
 
5
-type liberr struct {
6
-	err error
7
-}
6
+	"github.com/docker/docker/errdefs"
7
+)
8 8
 
9
-func (e liberr) Error() string {
10
-	return e.err.Error()
11
-}
9
+func newNotFoundError(err string) error { return errdefs.NotFound(errors.New(err)) }
12 10
 
13
-func (e liberr) Cause() error {
14
-	return e.err
15
-}
11
+func newInvalidParameterError(err string) error { return errdefs.InvalidParameter(errors.New(err)) }
16 12
 
17
-type notFoundErr struct {
18
-	liberr
19
-}
20
-
21
-func (notFoundErr) NotFound() {}
22
-
23
-func newNotFoundError(err string) error { return notFoundErr{liberr{errors.New(err)}} }
24
-func wrapNotFoundError(err error) error { return notFoundErr{liberr{err}} }
25
-
26
-type invalidParamErr struct {
27
-	liberr
28
-}
29
-
30
-func (invalidParamErr) InvalidParameter() {}
31
-
32
-func newInvalidParameterError(err string) error { return invalidParamErr{liberr{errors.New(err)}} }
33
-
34
-type conflictErr struct {
35
-	liberr
36
-}
37
-
38
-func (conflictErr) ConflictErr() {}
39
-
40
-func newConflictError(err string) error { return conflictErr{liberr{errors.New(err)}} }
41
-
42
-type sysErr struct {
43
-	liberr
44
-}
45
-
46
-func wrapSystemError(err error) error { return sysErr{liberr{err}} }
13
+func newConflictError(err string) error { return errdefs.Conflict(errors.New(err)) }
... ...
@@ -20,6 +20,7 @@ import (
20 20
 	progressutils "github.com/docker/docker/distribution/utils"
21 21
 	"github.com/docker/docker/distribution/xfer"
22 22
 	"github.com/docker/docker/dockerversion"
23
+	"github.com/docker/docker/errdefs"
23 24
 	"github.com/docker/docker/image"
24 25
 	"github.com/docker/docker/layer"
25 26
 	"github.com/docker/docker/pkg/authorization"
... ...
@@ -233,7 +234,7 @@ func (pm *Manager) Privileges(ctx context.Context, ref reference.Named, metaHead
233 233
 	}
234 234
 	var config types.PluginConfig
235 235
 	if err := json.Unmarshal(cs.config, &config); err != nil {
236
-		return nil, systemError{err}
236
+		return nil, errdefs.System(err)
237 237
 	}
238 238
 
239 239
 	return computePrivileges(config), nil
... ...
@@ -255,12 +256,12 @@ func (pm *Manager) Upgrade(ctx context.Context, ref reference.Named, name string
255 255
 
256 256
 	// revalidate because Pull is public
257 257
 	if _, err := reference.ParseNormalizedNamed(name); err != nil {
258
-		return errors.Wrapf(validationError{err}, "failed to parse %q", name)
258
+		return errors.Wrapf(errdefs.InvalidParameter(err), "failed to parse %q", name)
259 259
 	}
260 260
 
261 261
 	tmpRootFSDir, err := ioutil.TempDir(pm.tmpDir(), ".rootfs")
262 262
 	if err != nil {
263
-		return errors.Wrap(systemError{err}, "error preparing upgrade")
263
+		return errors.Wrap(errdefs.System(err), "error preparing upgrade")
264 264
 	}
265 265
 	defer os.RemoveAll(tmpRootFSDir)
266 266
 
... ...
@@ -302,17 +303,17 @@ func (pm *Manager) Pull(ctx context.Context, ref reference.Named, name string, m
302 302
 	// revalidate because Pull is public
303 303
 	nameref, err := reference.ParseNormalizedNamed(name)
304 304
 	if err != nil {
305
-		return errors.Wrapf(validationError{err}, "failed to parse %q", name)
305
+		return errors.Wrapf(errdefs.InvalidParameter(err), "failed to parse %q", name)
306 306
 	}
307 307
 	name = reference.FamiliarString(reference.TagNameOnly(nameref))
308 308
 
309 309
 	if err := pm.config.Store.validateName(name); err != nil {
310
-		return validationError{err}
310
+		return errdefs.InvalidParameter(err)
311 311
 	}
312 312
 
313 313
 	tmpRootFSDir, err := ioutil.TempDir(pm.tmpDir(), ".rootfs")
314 314
 	if err != nil {
315
-		return errors.Wrap(systemError{err}, "error preparing pull")
315
+		return errors.Wrap(errdefs.System(err), "error preparing pull")
316 316
 	}
317 317
 	defer os.RemoveAll(tmpRootFSDir)
318 318
 
... ...
@@ -26,34 +26,6 @@ func (name errDisabled) Error() string {
26 26
 
27 27
 func (name errDisabled) Conflict() {}
28 28
 
29
-type validationError struct {
30
-	cause error
31
-}
32
-
33
-func (e validationError) Error() string {
34
-	return e.cause.Error()
35
-}
36
-
37
-func (validationError) Conflict() {}
38
-
39
-func (e validationError) Cause() error {
40
-	return e.cause
41
-}
42
-
43
-type systemError struct {
44
-	cause error
45
-}
46
-
47
-func (e systemError) Error() string {
48
-	return e.cause.Error()
49
-}
50
-
51
-func (systemError) SystemError() {}
52
-
53
-func (e systemError) Cause() error {
54
-	return e.cause
55
-}
56
-
57 29
 type invalidFilter struct {
58 30
 	filter string
59 31
 	value  []string
... ...
@@ -8,7 +8,7 @@ import (
8 8
 
9 9
 	"github.com/containerd/containerd/cio"
10 10
 	"github.com/containerd/containerd/linux/runctypes"
11
-	"github.com/docker/docker/api/errdefs"
11
+	"github.com/docker/docker/errdefs"
12 12
 	"github.com/docker/docker/libcontainerd"
13 13
 	"github.com/opencontainers/runtime-spec/specs-go"
14 14
 	"github.com/pkg/errors"
... ...
@@ -9,6 +9,7 @@ import (
9 9
 
10 10
 	"github.com/docker/docker/api/types"
11 11
 	"github.com/docker/docker/daemon/initlayer"
12
+	"github.com/docker/docker/errdefs"
12 13
 	"github.com/docker/docker/pkg/containerfs"
13 14
 	"github.com/docker/docker/pkg/idtools"
14 15
 	"github.com/docker/docker/pkg/mount"
... ...
@@ -217,12 +218,12 @@ func (pm *Manager) upgradePlugin(p *v2.Plugin, configDigest digest.Digest, blobs
217 217
 	// This could happen if the plugin was disabled with `-f` with active mounts.
218 218
 	// If there is anything in `orig` is still mounted, this should error out.
219 219
 	if err := mount.RecursiveUnmount(orig); err != nil {
220
-		return systemError{err}
220
+		return errdefs.System(err)
221 221
 	}
222 222
 
223 223
 	backup := orig + "-old"
224 224
 	if err := os.Rename(orig, backup); err != nil {
225
-		return errors.Wrap(systemError{err}, "error backing up plugin data before upgrade")
225
+		return errors.Wrap(errdefs.System(err), "error backing up plugin data before upgrade")
226 226
 	}
227 227
 
228 228
 	defer func() {
... ...
@@ -248,7 +249,7 @@ func (pm *Manager) upgradePlugin(p *v2.Plugin, configDigest digest.Digest, blobs
248 248
 	}()
249 249
 
250 250
 	if err := os.Rename(tmpRootFSDir, orig); err != nil {
251
-		return errors.Wrap(systemError{err}, "error upgrading")
251
+		return errors.Wrap(errdefs.System(err), "error upgrading")
252 252
 	}
253 253
 
254 254
 	p.PluginObj.Config = config
... ...
@@ -288,7 +289,7 @@ func (pm *Manager) setupNewPlugin(configDigest digest.Digest, blobsums []digest.
288 288
 // createPlugin creates a new plugin. take lock before calling.
289 289
 func (pm *Manager) createPlugin(name string, configDigest digest.Digest, blobsums []digest.Digest, rootFSDir string, privileges *types.PluginPrivileges, opts ...CreateOpt) (p *v2.Plugin, err error) {
290 290
 	if err := pm.config.Store.validateName(name); err != nil { // todo: this check is wrong. remove store
291
-		return nil, validationError{err}
291
+		return nil, errdefs.InvalidParameter(err)
292 292
 	}
293 293
 
294 294
 	config, err := pm.setupNewPlugin(configDigest, blobsums, privileges)
... ...
@@ -5,6 +5,7 @@ import (
5 5
 	"strings"
6 6
 
7 7
 	"github.com/docker/distribution/reference"
8
+	"github.com/docker/docker/errdefs"
8 9
 	"github.com/docker/docker/pkg/plugingetter"
9 10
 	"github.com/docker/docker/pkg/plugins"
10 11
 	"github.com/docker/docker/plugin/v2"
... ...
@@ -144,7 +145,7 @@ func (ps *Store) Get(name, capability string, mode int) (plugingetter.CompatPlug
144 144
 	if errors.Cause(err) == plugins.ErrNotFound {
145 145
 		return nil, errNotFound(name)
146 146
 	}
147
-	return nil, errors.Wrap(systemError{err}, "legacy plugin")
147
+	return nil, errors.Wrap(errdefs.System(err), "legacy plugin")
148 148
 }
149 149
 
150 150
 // GetAllManagedPluginsByCap returns a list of managed plugins matching the given capability.
... ...
@@ -172,7 +173,7 @@ func (ps *Store) GetAllByCap(capability string) ([]plugingetter.CompatPlugin, er
172 172
 	if allowV1PluginsFallback {
173 173
 		pl, err := plugins.GetAll(capability)
174 174
 		if err != nil {
175
-			return nil, errors.Wrap(systemError{err}, "legacy plugin")
175
+			return nil, errors.Wrap(errdefs.System(err), "legacy plugin")
176 176
 		}
177 177
 		for _, p := range pl {
178 178
 			result = append(result, p)
... ...
@@ -12,6 +12,7 @@ import (
12 12
 	"github.com/docker/distribution/registry/client/transport"
13 13
 	"github.com/docker/docker/api/types"
14 14
 	registrytypes "github.com/docker/docker/api/types/registry"
15
+	"github.com/docker/docker/errdefs"
15 16
 	"github.com/pkg/errors"
16 17
 	"github.com/sirupsen/logrus"
17 18
 )
... ...
@@ -29,7 +30,7 @@ func loginV1(authConfig *types.AuthConfig, apiEndpoint APIEndpoint, userAgent st
29 29
 	logrus.Debugf("attempting v1 login to registry endpoint %s", serverAddress)
30 30
 
31 31
 	if serverAddress == "" {
32
-		return "", "", systemError{errors.New("server Error: Server Address not set")}
32
+		return "", "", errdefs.System(errors.New("server Error: Server Address not set"))
33 33
 	}
34 34
 
35 35
 	req, err := http.NewRequest("GET", serverAddress+"users/", nil)
... ...
@@ -47,23 +48,23 @@ func loginV1(authConfig *types.AuthConfig, apiEndpoint APIEndpoint, userAgent st
47 47
 	defer resp.Body.Close()
48 48
 	body, err := ioutil.ReadAll(resp.Body)
49 49
 	if err != nil {
50
-		return "", "", systemError{err}
50
+		return "", "", errdefs.System(err)
51 51
 	}
52 52
 
53 53
 	switch resp.StatusCode {
54 54
 	case http.StatusOK:
55 55
 		return "Login Succeeded", "", nil
56 56
 	case http.StatusUnauthorized:
57
-		return "", "", unauthorizedError{errors.New("Wrong login/password, please try again")}
57
+		return "", "", errdefs.Unauthorized(errors.New("Wrong login/password, please try again"))
58 58
 	case http.StatusForbidden:
59 59
 		// *TODO: Use registry configuration to determine what this says, if anything?
60
-		return "", "", notActivatedError{errors.Errorf("Login: Account is not active. Please see the documentation of the registry %s for instructions how to activate it.", serverAddress)}
60
+		return "", "", errdefs.Forbidden(errors.Errorf("Login: Account is not active. Please see the documentation of the registry %s for instructions how to activate it.", serverAddress))
61 61
 	case http.StatusInternalServerError:
62 62
 		logrus.Errorf("%s returned status code %d. Response Body :\n%s", req.URL.String(), resp.StatusCode, body)
63
-		return "", "", systemError{errors.New("Internal Server Error")}
63
+		return "", "", errdefs.System(errors.New("Internal Server Error"))
64 64
 	}
65
-	return "", "", systemError{errors.Errorf("Login: %s (Code: %d; Headers: %s)", body,
66
-		resp.StatusCode, resp.Header)}
65
+	return "", "", errdefs.System(errors.Errorf("Login: %s (Code: %d; Headers: %s)", body,
66
+		resp.StatusCode, resp.Header))
67 67
 }
68 68
 
69 69
 type loginCredentialStore struct {
... ...
@@ -4,6 +4,7 @@ import (
4 4
 	"net/url"
5 5
 
6 6
 	"github.com/docker/distribution/registry/api/errcode"
7
+	"github.com/docker/docker/errdefs"
7 8
 )
8 9
 
9 10
 type notFoundError string
... ...
@@ -14,62 +15,6 @@ func (e notFoundError) Error() string {
14 14
 
15 15
 func (notFoundError) NotFound() {}
16 16
 
17
-type validationError struct {
18
-	cause error
19
-}
20
-
21
-func (e validationError) Error() string {
22
-	return e.cause.Error()
23
-}
24
-
25
-func (e validationError) InvalidParameter() {}
26
-
27
-func (e validationError) Cause() error {
28
-	return e.cause
29
-}
30
-
31
-type unauthorizedError struct {
32
-	cause error
33
-}
34
-
35
-func (e unauthorizedError) Error() string {
36
-	return e.cause.Error()
37
-}
38
-
39
-func (e unauthorizedError) Unauthorized() {}
40
-
41
-func (e unauthorizedError) Cause() error {
42
-	return e.cause
43
-}
44
-
45
-type systemError struct {
46
-	cause error
47
-}
48
-
49
-func (e systemError) Error() string {
50
-	return e.cause.Error()
51
-}
52
-
53
-func (e systemError) SystemError() {}
54
-
55
-func (e systemError) Cause() error {
56
-	return e.cause
57
-}
58
-
59
-type notActivatedError struct {
60
-	cause error
61
-}
62
-
63
-func (e notActivatedError) Error() string {
64
-	return e.cause.Error()
65
-}
66
-
67
-func (e notActivatedError) Forbidden() {}
68
-
69
-func (e notActivatedError) Cause() error {
70
-	return e.cause
71
-}
72
-
73 17
 func translateV2AuthError(err error) error {
74 18
 	switch e := err.(type) {
75 19
 	case *url.Error:
... ...
@@ -77,7 +22,7 @@ func translateV2AuthError(err error) error {
77 77
 		case errcode.Error:
78 78
 			switch e2.Code {
79 79
 			case errcode.ErrorCodeUnauthorized:
80
-				return unauthorizedError{err}
80
+				return errdefs.Unauthorized(err)
81 81
 			}
82 82
 		}
83 83
 	}
... ...
@@ -13,6 +13,7 @@ import (
13 13
 	"github.com/docker/distribution/registry/client/auth"
14 14
 	"github.com/docker/docker/api/types"
15 15
 	registrytypes "github.com/docker/docker/api/types/registry"
16
+	"github.com/docker/docker/errdefs"
16 17
 	"github.com/pkg/errors"
17 18
 	"github.com/sirupsen/logrus"
18 19
 )
... ...
@@ -117,12 +118,12 @@ func (s *DefaultService) Auth(ctx context.Context, authConfig *types.AuthConfig,
117 117
 	}
118 118
 	u, err := url.Parse(serverAddress)
119 119
 	if err != nil {
120
-		return "", "", validationError{errors.Errorf("unable to parse server address: %v", err)}
120
+		return "", "", errdefs.InvalidParameter(errors.Errorf("unable to parse server address: %v", err))
121 121
 	}
122 122
 
123 123
 	endpoints, err := s.LookupPushEndpoints(u.Host)
124 124
 	if err != nil {
125
-		return "", "", validationError{err}
125
+		return "", "", errdefs.InvalidParameter(err)
126 126
 	}
127 127
 
128 128
 	for _, endpoint := range endpoints {
... ...
@@ -21,6 +21,7 @@ import (
21 21
 	"github.com/docker/distribution/registry/api/errcode"
22 22
 	"github.com/docker/docker/api/types"
23 23
 	registrytypes "github.com/docker/docker/api/types/registry"
24
+	"github.com/docker/docker/errdefs"
24 25
 	"github.com/docker/docker/pkg/ioutils"
25 26
 	"github.com/docker/docker/pkg/jsonmessage"
26 27
 	"github.com/docker/docker/pkg/stringid"
... ...
@@ -734,20 +735,20 @@ func shouldRedirect(response *http.Response) bool {
734 734
 // SearchRepositories performs a search against the remote repository
735 735
 func (r *Session) SearchRepositories(term string, limit int) (*registrytypes.SearchResults, error) {
736 736
 	if limit < 1 || limit > 100 {
737
-		return nil, validationError{errors.Errorf("Limit %d is outside the range of [1, 100]", limit)}
737
+		return nil, errdefs.InvalidParameter(errors.Errorf("Limit %d is outside the range of [1, 100]", limit))
738 738
 	}
739 739
 	logrus.Debugf("Index server: %s", r.indexEndpoint)
740 740
 	u := r.indexEndpoint.String() + "search?q=" + url.QueryEscape(term) + "&n=" + url.QueryEscape(fmt.Sprintf("%d", limit))
741 741
 
742 742
 	req, err := http.NewRequest("GET", u, nil)
743 743
 	if err != nil {
744
-		return nil, errors.Wrap(validationError{err}, "Error building request")
744
+		return nil, errors.Wrap(errdefs.InvalidParameter(err), "Error building request")
745 745
 	}
746 746
 	// Have the AuthTransport send authentication, when logged in.
747 747
 	req.Header.Set("X-Docker-Token", "true")
748 748
 	res, err := r.client.Do(req)
749 749
 	if err != nil {
750
-		return nil, systemError{err}
750
+		return nil, errdefs.System(err)
751 751
 	}
752 752
 	defer res.Body.Close()
753 753
 	if res.StatusCode != 200 {
... ...
@@ -14,6 +14,7 @@ import (
14 14
 	"sync"
15 15
 
16 16
 	"github.com/docker/docker/daemon/names"
17
+	"github.com/docker/docker/errdefs"
17 18
 	"github.com/docker/docker/pkg/idtools"
18 19
 	"github.com/docker/docker/pkg/mount"
19 20
 	"github.com/docker/docker/volume"
... ...
@@ -139,20 +140,6 @@ func (r *Root) Name() string {
139 139
 	return volume.DefaultDriverName
140 140
 }
141 141
 
142
-type systemError struct {
143
-	err error
144
-}
145
-
146
-func (e systemError) Error() string {
147
-	return e.err.Error()
148
-}
149
-
150
-func (e systemError) SystemError() {}
151
-
152
-func (e systemError) Cause() error {
153
-	return e.err
154
-}
155
-
156 142
 // Create creates a new volume.Volume with the provided name, creating
157 143
 // the underlying directory tree required for this volume in the
158 144
 // process.
... ...
@@ -171,7 +158,7 @@ func (r *Root) Create(name string, opts map[string]string) (volume.Volume, error
171 171
 
172 172
 	path := r.DataPath(name)
173 173
 	if err := idtools.MkdirAllAndChown(path, 0755, r.rootIDs); err != nil {
174
-		return nil, errors.Wrapf(systemError{err}, "error while creating volume path '%s'", path)
174
+		return nil, errors.Wrapf(errdefs.System(err), "error while creating volume path '%s'", path)
175 175
 	}
176 176
 
177 177
 	var err error
... ...
@@ -197,7 +184,7 @@ func (r *Root) Create(name string, opts map[string]string) (volume.Volume, error
197 197
 			return nil, err
198 198
 		}
199 199
 		if err = ioutil.WriteFile(filepath.Join(filepath.Dir(path), "opts.json"), b, 600); err != nil {
200
-			return nil, errors.Wrap(systemError{err}, "error while persisting volume options")
200
+			return nil, errdefs.System(errors.Wrap(err, "error while persisting volume options"))
201 201
 		}
202 202
 	}
203 203
 
... ...
@@ -215,11 +202,11 @@ func (r *Root) Remove(v volume.Volume) error {
215 215
 
216 216
 	lv, ok := v.(*localVolume)
217 217
 	if !ok {
218
-		return systemError{errors.Errorf("unknown volume type %T", v)}
218
+		return errdefs.System(errors.Errorf("unknown volume type %T", v))
219 219
 	}
220 220
 
221 221
 	if lv.active.count > 0 {
222
-		return systemError{errors.Errorf("volume has active mounts")}
222
+		return errdefs.System(errors.Errorf("volume has active mounts"))
223 223
 	}
224 224
 
225 225
 	if err := lv.unmount(); err != nil {
... ...
@@ -235,7 +222,7 @@ func (r *Root) Remove(v volume.Volume) error {
235 235
 	}
236 236
 
237 237
 	if !r.scopedPath(realPath) {
238
-		return systemError{errors.Errorf("Unable to remove a directory of out the Docker root %s: %s", r.scope, realPath)}
238
+		return errdefs.System(errors.Errorf("Unable to remove a directory of out the Docker root %s: %s", r.scope, realPath))
239 239
 	}
240 240
 
241 241
 	if err := removePath(realPath); err != nil {
... ...
@@ -251,7 +238,7 @@ func removePath(path string) error {
251 251
 		if os.IsNotExist(err) {
252 252
 			return nil
253 253
 		}
254
-		return errors.Wrapf(systemError{err}, "error removing volume path '%s'", path)
254
+		return errdefs.System(errors.Wrapf(err, "error removing volume path '%s'", path))
255 255
 	}
256 256
 	return nil
257 257
 }
... ...
@@ -334,7 +321,7 @@ func (v *localVolume) Mount(id string) (string, error) {
334 334
 	if v.opts != nil {
335 335
 		if !v.active.mounted {
336 336
 			if err := v.mount(); err != nil {
337
-				return "", systemError{err}
337
+				return "", errdefs.System(err)
338 338
 			}
339 339
 			v.active.mounted = true
340 340
 		}
... ...
@@ -368,7 +355,7 @@ func (v *localVolume) unmount() error {
368 368
 	if v.opts != nil {
369 369
 		if err := mount.Unmount(v.path); err != nil {
370 370
 			if mounted, mErr := mount.Mounted(v.path); mounted || mErr != nil {
371
-				return errors.Wrapf(systemError{err}, "error while unmounting volume path '%s'", v.path)
371
+				return errdefs.System(errors.Wrapf(err, "error while unmounting volume path '%s'", v.path))
372 372
 			}
373 373
 		}
374 374
 		v.active.mounted = false