diff --git a/docker/docker_client.go b/docker/docker_client.go index b13d8c7466..a7c626f27a 100644 --- a/docker/docker_client.go +++ b/docker/docker_client.go @@ -591,7 +591,7 @@ func (c *dockerClient) getBearerToken(ctx context.Context, challenge challenge, case http.StatusUnauthorized: err := clientLib.HandleErrorResponse(res) logrus.Debugf("Server response when trying to obtain an access token: \n%q", err.Error()) - return nil, ErrUnauthorizedForCredentials + return nil, ErrUnauthorizedForCredentials{Err: err} case http.StatusOK: break default: diff --git a/docker/errors.go b/docker/errors.go index b8d2f44772..860868f415 100644 --- a/docker/errors.go +++ b/docker/errors.go @@ -2,8 +2,10 @@ package docker import ( "errors" + "fmt" "net/http" + "github.com/docker/distribution/registry/client" perrors "github.com/pkg/errors" ) @@ -11,12 +13,19 @@ var ( // ErrV1NotSupported is returned when we're trying to talk to a // docker V1 registry. ErrV1NotSupported = errors.New("can't talk to a V1 docker registry") - // ErrUnauthorizedForCredentials is returned when the status code returned is 401 - ErrUnauthorizedForCredentials = errors.New("unable to retrieve auth token: invalid username/password") // ErrTooManyRequests is returned when the status code returned is 429 ErrTooManyRequests = errors.New("too many request to registry") ) +// ErrUnauthorizedForCredentials is returned when the status code returned is 401 +type ErrUnauthorizedForCredentials struct { // We only use a struct to allow a type assertion, without limiting the contents of the error otherwise. + Err error +} + +func (e ErrUnauthorizedForCredentials) Error() string { + return fmt.Sprintf("unable to retrieve auth token: invalid username/password: %s", e.Err.Error()) +} + // httpResponseToError translates the https.Response into an error. It returns // nil if the response is not considered an error. func httpResponseToError(res *http.Response) error { @@ -26,7 +35,8 @@ func httpResponseToError(res *http.Response) error { case http.StatusTooManyRequests: return ErrTooManyRequests case http.StatusUnauthorized: - return ErrUnauthorizedForCredentials + err := client.HandleErrorResponse(res) + return ErrUnauthorizedForCredentials{Err: err} default: return perrors.Errorf("invalid status code from registry %d (%s)", res.StatusCode, http.StatusText(res.StatusCode)) }