@@ -29,64 +29,314 @@ package errdefs
2929import (
3030 "context"
3131 "errors"
32+ "fmt"
3233)
3334
3435// Definitions of common error types used throughout containerd. All containerd
3536// errors returned by most packages will map into one of these errors classes.
3637// Packages should return errors of these types when they want to instruct a
3738// client to take a particular action.
3839//
39- // For the most part, we just try to provide local grpc errors. Most conditions
40- // map very well to those defined by grpc.
40+ // These errors map closely to grpc errors.
4141var (
42- ErrUnknown = errors .New ("unknown" ) // used internally to represent a missed mapping.
43- ErrInvalidArgument = errors .New ("invalid argument" )
44- ErrNotFound = errors .New ("not found" )
45- ErrAlreadyExists = errors .New ("already exists" )
46- ErrFailedPrecondition = errors .New ("failed precondition" )
47- ErrUnavailable = errors .New ("unavailable" )
48- ErrNotImplemented = errors .New ("not implemented" ) // represents not supported and unimplemented
42+ ErrUnknown = errUnknown {}
43+ ErrInvalidArgument = errInvalidArgument {}
44+ ErrNotFound = errNotFound {}
45+ ErrAlreadyExists = errAlreadyExists {}
46+ ErrPermissionDenied = errPermissionDenied {}
47+ ErrResourceExhausted = errResourceExhausted {}
48+ ErrFailedPrecondition = errFailedPrecondition {}
49+ ErrConflict = errConflict {}
50+ ErrNotModified = errNotModified {}
51+ ErrAborted = errAborted {}
52+ ErrOutOfRange = errOutOfRange {}
53+ ErrNotImplemented = errNotImplemented {}
54+ ErrInternal = errInternal {}
55+ ErrUnavailable = errUnavailable {}
56+ ErrDataLoss = errDataLoss {}
57+ ErrUnauthenticated = errUnauthorized {}
4958)
5059
60+ // cancelled maps to Moby's "ErrCancelled"
61+ type cancelled interface {
62+ ErrCancelled ()
63+ }
64+
65+ // IsCanceled returns true if the error is due to `context.Canceled`.
66+ func IsCanceled (err error ) bool {
67+ return errors .Is (err , context .Canceled ) || isInterface [cancelled ](err )
68+ }
69+
70+ type errUnknown struct {}
71+
72+ func (errUnknown ) Error () string { return "unknown" }
73+
74+ func (errUnknown ) Unknown () {}
75+
76+ type errUnexpectedStatus struct {
77+ status int
78+ }
79+
80+ const unexpectedStatusPrefix = "unexpected status "
81+
82+ func (e errUnexpectedStatus ) Error () string {
83+ return fmt .Sprintf ("%s%d" , unexpectedStatusPrefix , e .status )
84+ }
85+
86+ func (errUnexpectedStatus ) Unknown () {}
87+
88+ // unknown maps to Moby's "ErrUnknown"
89+ type unknown interface {
90+ Unknown ()
91+ }
92+
93+ // IsUnknown returns true if the error is due to an unknown error,
94+ // unhandled condition or unexpected response.
95+ func IsUnknown (err error ) bool {
96+ return errors .Is (err , errUnknown {}) || isInterface [unknown ](err )
97+ }
98+
99+ type errInvalidArgument struct {}
100+
101+ func (errInvalidArgument ) Error () string { return "invalid argument" }
102+
103+ func (errInvalidArgument ) InvalidParameter () {}
104+
105+ // invalidParameter maps to Moby's "ErrInvalidParameter"
106+ type invalidParameter interface {
107+ InvalidParameter ()
108+ }
109+
51110// IsInvalidArgument returns true if the error is due to an invalid argument
52111func IsInvalidArgument (err error ) bool {
53- return errors .Is (err , ErrInvalidArgument )
112+ return errors .Is (err , ErrInvalidArgument ) || isInterface [invalidParameter ](err )
113+ }
114+
115+ // deadlineExceed maps to Moby's "ErrDeadline"
116+ type deadlineExceeded interface {
117+ DeadlineExceeded ()
118+ }
119+
120+ // IsDeadlineExceeded returns true if the error is due to
121+ // `context.DeadlineExceeded`.
122+ func IsDeadlineExceeded (err error ) bool {
123+ return errors .Is (err , context .DeadlineExceeded ) || isInterface [deadlineExceeded ](err )
124+ }
125+
126+ type errNotFound struct {}
127+
128+ func (errNotFound ) Error () string { return "not found" }
129+
130+ func (errNotFound ) NotFound () {}
131+
132+ // notFound maps to Moby's "ErrNotFound"
133+ type notFound interface {
134+ NotFound ()
54135}
55136
56137// IsNotFound returns true if the error is due to a missing object
57138func IsNotFound (err error ) bool {
58- return errors .Is (err , ErrNotFound )
139+ return errors .Is (err , ErrNotFound ) || isInterface [ notFound ]( err )
59140}
60141
142+ type errAlreadyExists struct {}
143+
144+ func (errAlreadyExists ) Error () string { return "already exists" }
145+
61146// IsAlreadyExists returns true if the error is due to an already existing
62147// metadata item
63148func IsAlreadyExists (err error ) bool {
64149 return errors .Is (err , ErrAlreadyExists )
65150}
66151
67- // IsFailedPrecondition returns true if an operation could not proceed to the
68- // lack of a particular condition
152+ type errPermissionDenied struct {}
153+
154+ func (errPermissionDenied ) Error () string { return "permission denied" }
155+
156+ // forbidden maps to Moby's "ErrForbidden"
157+ type forbidden interface {
158+ Forbidden ()
159+ }
160+
161+ // IsPermissionDenied returns true if the error is due to permission denied
162+ // or forbidden (403) response
163+ func IsPermissionDenied (err error ) bool {
164+ return errors .Is (err , ErrPermissionDenied ) || isInterface [forbidden ](err )
165+ }
166+
167+ type errResourceExhausted struct {}
168+
169+ func (errResourceExhausted ) Error () string { return "resource exhausted" }
170+
171+ // IsResourceExhausted returns true if the error is due to
172+ // a lack of resources or too many attempts.
173+ func IsResourceExhausted (err error ) bool {
174+ return errors .Is (err , errResourceExhausted {})
175+ }
176+
177+ type errFailedPrecondition struct {}
178+
179+ func (e errFailedPrecondition ) Error () string { return "failed precondition" }
180+
181+ // IsFailedPrecondition returns true if an operation could not proceed due to
182+ // the lack of a particular condition
69183func IsFailedPrecondition (err error ) bool {
70- return errors .Is (err , ErrFailedPrecondition )
184+ return errors .Is (err , errFailedPrecondition {} )
71185}
72186
73- // IsUnavailable returns true if the error is due to a resource being unavailable
74- func IsUnavailable (err error ) bool {
75- return errors .Is (err , ErrUnavailable )
187+ type errConflict struct {}
188+
189+ func (errConflict ) Error () string { return "conflict" }
190+
191+ func (errConflict ) Conflict () {}
192+
193+ // conflict maps to Moby's "ErrConflict"
194+ type conflict interface {
195+ Conflict ()
196+ }
197+
198+ // IsConflict returns true if an operation could not proceed due to
199+ // a conflict.
200+ func IsConflict (err error ) bool {
201+ return errors .Is (err , errConflict {}) || isInterface [conflict ](err )
202+ }
203+
204+ type errNotModified struct {}
205+
206+ func (errNotModified ) Error () string { return "not modified" }
207+
208+ func (errNotModified ) NotModified () {}
209+
210+ // notModified maps to Moby's "ErrNotModified"
211+ type notModified interface {
212+ NotModified ()
213+ }
214+
215+ // IsNotModified returns true if an operation could not proceed due
216+ // to an object not modified from a previous state.
217+ func IsNotModified (err error ) bool {
218+ return errors .Is (err , errNotModified {}) || isInterface [notModified ](err )
219+ }
220+
221+ type errAborted struct {}
222+
223+ func (errAborted ) Error () string { return "aborted" }
224+
225+ // IsAborted returns true if an operation was aborted.
226+ func IsAborted (err error ) bool {
227+ return errors .Is (err , errAborted {})
228+ }
229+
230+ type errOutOfRange struct {}
231+
232+ func (errOutOfRange ) Error () string { return "out of range" }
233+
234+ // IsOutOfRange returns true if an operation could not proceed due
235+ // to data being out of the expected range.
236+ func IsOutOfRange (err error ) bool {
237+ return errors .Is (err , errOutOfRange {})
238+ }
239+
240+ type errNotImplemented struct {}
241+
242+ func (errNotImplemented ) Error () string { return "not implemented" }
243+
244+ func (errNotImplemented ) NotImplemented () {}
245+
246+ // notImplemented maps to Moby's "ErrNotImplemented"
247+ type notImplemented interface {
248+ NotImplemented ()
76249}
77250
78251// IsNotImplemented returns true if the error is due to not being implemented
79252func IsNotImplemented (err error ) bool {
80- return errors .Is (err , ErrNotImplemented )
253+ return errors .Is (err , errNotImplemented {}) || isInterface [ notImplemented ]( err )
81254}
82255
83- // IsCanceled returns true if the error is due to `context.Canceled`.
84- func IsCanceled (err error ) bool {
85- return errors .Is (err , context .Canceled )
256+ type errInternal struct {}
257+
258+ func (errInternal ) Error () string { return "internal" }
259+
260+ func (errInternal ) System () {}
261+
262+ // system maps to Moby's "ErrSystem"
263+ type system interface {
264+ System ()
86265}
87266
88- // IsDeadlineExceeded returns true if the error is due to
89- // `context.DeadlineExceeded`.
90- func IsDeadlineExceeded (err error ) bool {
91- return errors .Is (err , context .DeadlineExceeded )
267+ // IsInternal returns true if the error returns to an internal or system error
268+ func IsInternal (err error ) bool {
269+ return errors .Is (err , errInternal {}) || isInterface [system ](err )
270+ }
271+
272+ type errUnavailable struct {}
273+
274+ func (errUnavailable ) Error () string { return "unavailable" }
275+
276+ func (errUnavailable ) Unavailable () {}
277+
278+ // unavailable maps to Moby's "ErrUnavailable"
279+ type unavailable interface {
280+ Unavailable ()
281+ }
282+
283+ // IsUnavailable returns true if the error is due to a resource being unavailable
284+ func IsUnavailable (err error ) bool {
285+ return errors .Is (err , errUnavailable {}) || isInterface [unavailable ](err )
286+ }
287+
288+ type errDataLoss struct {}
289+
290+ func (errDataLoss ) Error () string { return "data loss" }
291+
292+ func (errDataLoss ) DataLoss () {}
293+
294+ // dataLoss maps to Moby's "ErrDataLoss"
295+ type dataLoss interface {
296+ DataLoss ()
297+ }
298+
299+ // IsDataLoss returns true if data during an operation was lost or corrupted
300+ func IsDataLoss (err error ) bool {
301+ return errors .Is (err , errDataLoss {}) || isInterface [dataLoss ](err )
302+ }
303+
304+ type errUnauthorized struct {}
305+
306+ func (errUnauthorized ) Error () string { return "unauthorized" }
307+
308+ func (errUnauthorized ) Unauthorized () {}
309+
310+ // unauthorized maps to Moby's "ErrUnauthorized"
311+ type unauthorized interface {
312+ Unauthorized ()
313+ }
314+
315+ // IsUnauthorized returns true if the error indicates that the user was
316+ // unauthenticated or unauthorized.
317+ func IsUnauthorized (err error ) bool {
318+ return errors .Is (err , errUnauthorized {}) || isInterface [unauthorized ](err )
319+ }
320+
321+ func isInterface [T any ](err error ) bool {
322+ for {
323+ switch x := err .(type ) {
324+ case T :
325+ return true
326+ case interface { Unwrap () error }:
327+ err = x .Unwrap ()
328+ if err == nil {
329+ return false
330+ }
331+ case interface { Unwrap () []error }:
332+ for _ , err := range x .Unwrap () {
333+ if isInterface [T ](err ) {
334+ return true
335+ }
336+ }
337+ return false
338+ default :
339+ return false
340+ }
341+ }
92342}
0 commit comments