-
Notifications
You must be signed in to change notification settings - Fork 18.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #20247 from aaronlehmann/distribution-errors
Push/pull errors improvement and cleanup
- Loading branch information
Showing
8 changed files
with
128 additions
and
108 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
package distribution | ||
|
||
import ( | ||
"net/url" | ||
"strings" | ||
"syscall" | ||
|
||
"github.com/docker/distribution/registry/api/errcode" | ||
"github.com/docker/distribution/registry/api/v2" | ||
"github.com/docker/distribution/registry/client" | ||
"github.com/docker/docker/distribution/xfer" | ||
) | ||
|
||
// ErrNoSupport is an error type used for errors indicating that an operation | ||
// is not supported. It encapsulates a more specific error. | ||
type ErrNoSupport struct{ Err error } | ||
|
||
func (e ErrNoSupport) Error() string { | ||
if e.Err == nil { | ||
return "not supported" | ||
} | ||
return e.Err.Error() | ||
} | ||
|
||
// fallbackError wraps an error that can possibly allow fallback to a different | ||
// endpoint. | ||
type fallbackError struct { | ||
// err is the error being wrapped. | ||
err error | ||
// confirmedV2 is set to true if it was confirmed that the registry | ||
// supports the v2 protocol. This is used to limit fallbacks to the v1 | ||
// protocol. | ||
confirmedV2 bool | ||
} | ||
|
||
// Error renders the FallbackError as a string. | ||
func (f fallbackError) Error() string { | ||
return f.err.Error() | ||
} | ||
|
||
// shouldV2Fallback returns true if this error is a reason to fall back to v1. | ||
func shouldV2Fallback(err errcode.Error) bool { | ||
switch err.Code { | ||
case errcode.ErrorCodeUnauthorized, v2.ErrorCodeManifestUnknown, v2.ErrorCodeNameUnknown: | ||
return true | ||
} | ||
return false | ||
} | ||
|
||
// continueOnError returns true if we should fallback to the next endpoint | ||
// as a result of this error. | ||
func continueOnError(err error) bool { | ||
switch v := err.(type) { | ||
case errcode.Errors: | ||
if len(v) == 0 { | ||
return true | ||
} | ||
return continueOnError(v[0]) | ||
case ErrNoSupport: | ||
return continueOnError(v.Err) | ||
case errcode.Error: | ||
return shouldV2Fallback(v) | ||
case *client.UnexpectedHTTPResponseError: | ||
return true | ||
case ImageConfigPullError: | ||
return false | ||
case error: | ||
return !strings.Contains(err.Error(), strings.ToLower(syscall.ENOSPC.Error())) | ||
} | ||
// let's be nice and fallback if the error is a completely | ||
// unexpected one. | ||
// If new errors have to be handled in some way, please | ||
// add them to the switch above. | ||
return true | ||
} | ||
|
||
// retryOnError wraps the error in xfer.DoNotRetry if we should not retry the | ||
// operation after this error. | ||
func retryOnError(err error) error { | ||
switch v := err.(type) { | ||
case errcode.Errors: | ||
return retryOnError(v[0]) | ||
case errcode.Error: | ||
switch v.Code { | ||
case errcode.ErrorCodeUnauthorized, errcode.ErrorCodeUnsupported, errcode.ErrorCodeDenied: | ||
return xfer.DoNotRetry{Err: err} | ||
} | ||
case *url.Error: | ||
return retryOnError(v.Err) | ||
case *client.UnexpectedHTTPResponseError: | ||
return xfer.DoNotRetry{Err: err} | ||
case error: | ||
if strings.Contains(err.Error(), strings.ToLower(syscall.ENOSPC.Error())) { | ||
return xfer.DoNotRetry{Err: err} | ||
} | ||
} | ||
// let's be nice and fallback if the error is a completely | ||
// unexpected one. | ||
// If new errors have to be handled in some way, please | ||
// add them to the switch above. | ||
return err | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters