1
0
Fork 0

Migrate Sirupsen to sirupsen.

This commit is contained in:
Ludovic Fernandez 2018-01-22 12:16:03 +01:00 committed by Traefiker
parent c134dcd6fe
commit fb4ba7af2b
684 changed files with 92394 additions and 33943 deletions

View file

@ -1,19 +1,19 @@
package registry
import (
"fmt"
"io/ioutil"
"net/http"
"net/url"
"strings"
"time"
"github.com/Sirupsen/logrus"
"github.com/docker/distribution/registry/client/auth"
"github.com/docker/distribution/registry/client/auth/challenge"
"github.com/docker/distribution/registry/client/transport"
"github.com/docker/docker/api/types"
registrytypes "github.com/docker/docker/api/types/registry"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
const (
@ -23,21 +23,15 @@ const (
// loginV1 tries to register/login to the v1 registry server.
func loginV1(authConfig *types.AuthConfig, apiEndpoint APIEndpoint, userAgent string) (string, string, error) {
registryEndpoint, err := apiEndpoint.ToV1Endpoint(userAgent, nil)
if err != nil {
return "", "", err
}
registryEndpoint := apiEndpoint.ToV1Endpoint(userAgent, nil)
serverAddress := registryEndpoint.String()
logrus.Debugf("attempting v1 login to registry endpoint %s", serverAddress)
if serverAddress == "" {
return "", "", fmt.Errorf("Server Error: Server Address not set.")
return "", "", systemError{errors.New("server Error: Server Address not set")}
}
loginAgainstOfficialIndex := serverAddress == IndexServer
req, err := http.NewRequest("GET", serverAddress+"users/", nil)
if err != nil {
return "", "", err
@ -53,27 +47,23 @@ func loginV1(authConfig *types.AuthConfig, apiEndpoint APIEndpoint, userAgent st
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "", "", err
return "", "", systemError{err}
}
if resp.StatusCode == http.StatusOK {
switch resp.StatusCode {
case http.StatusOK:
return "Login Succeeded", "", nil
} else if resp.StatusCode == http.StatusUnauthorized {
if loginAgainstOfficialIndex {
return "", "", fmt.Errorf("Wrong login/password, please try again. Haven't got a Docker ID? Create one at https://hub.docker.com")
}
return "", "", fmt.Errorf("Wrong login/password, please try again")
} else if resp.StatusCode == http.StatusForbidden {
if loginAgainstOfficialIndex {
return "", "", fmt.Errorf("Login: Account is not active. Please check your e-mail for a confirmation link.")
}
case http.StatusUnauthorized:
return "", "", unauthorizedError{errors.New("Wrong login/password, please try again")}
case http.StatusForbidden:
// *TODO: Use registry configuration to determine what this says, if anything?
return "", "", fmt.Errorf("Login: Account is not active. Please see the documentation of the registry %s for instructions how to activate it.", serverAddress)
} else if resp.StatusCode == http.StatusInternalServerError { // Issue #14326
return "", "", notActivatedError{errors.Errorf("Login: Account is not active. Please see the documentation of the registry %s for instructions how to activate it.", serverAddress)}
case http.StatusInternalServerError:
logrus.Errorf("%s returned status code %d. Response Body :\n%s", req.URL.String(), resp.StatusCode, body)
return "", "", fmt.Errorf("Internal Server Error")
return "", "", systemError{errors.New("Internal Server Error")}
}
return "", "", fmt.Errorf("Login: %s (Code: %d; Headers: %s)", body,
resp.StatusCode, resp.Header)
return "", "", systemError{errors.Errorf("Login: %s (Code: %d; Headers: %s)", body,
resp.StatusCode, resp.Header)}
}
type loginCredentialStore struct {
@ -159,24 +149,25 @@ func loginV2(authConfig *types.AuthConfig, endpoint APIEndpoint, userAgent strin
resp, err := loginClient.Do(req)
if err != nil {
err = translateV2AuthError(err)
if !foundV2 {
err = fallbackError{err: err}
}
return "", "", err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
// TODO(dmcgowan): Attempt to further interpret result, status code and error code string
err := fmt.Errorf("login attempt to %s failed with status: %d %s", endpointStr, resp.StatusCode, http.StatusText(resp.StatusCode))
if !foundV2 {
err = fallbackError{err: err}
}
return "", "", err
if resp.StatusCode == http.StatusOK {
return "Login Succeeded", credentialAuthConfig.IdentityToken, nil
}
return "Login Succeeded", credentialAuthConfig.IdentityToken, nil
// TODO(dmcgowan): Attempt to further interpret result, status code and error code string
err = errors.Errorf("login attempt to %s failed with status: %d %s", endpointStr, resp.StatusCode, http.StatusText(resp.StatusCode))
if !foundV2 {
err = fallbackError{err: err}
}
return "", "", err
}
func v2AuthHTTPClient(endpoint *url.URL, authTransport http.RoundTripper, modifiers []transport.RequestModifier, creds auth.CredentialStore, scopes []auth.Scope) (*http.Client, bool, error) {
@ -256,6 +247,7 @@ func (err PingResponseError) Error() string {
// challenge manager for the supported authentication types and
// whether v2 was confirmed by the response. If a response is received but
// cannot be interpreted a PingResponseError will be returned.
// nolint: interfacer
func PingV2Registry(endpoint *url.URL, transport http.RoundTripper) (challenge.Manager, bool, error) {
var (
foundV2 = false

View file

@ -8,12 +8,10 @@ import (
"strconv"
"strings"
"github.com/Sirupsen/logrus"
"github.com/docker/distribution/reference"
registrytypes "github.com/docker/docker/api/types/registry"
"github.com/docker/docker/opts"
"github.com/pkg/errors"
"github.com/spf13/pflag"
"github.com/sirupsen/logrus"
)
// ServiceOptions holds command line options.
@ -62,7 +60,7 @@ var (
// not have the correct form
ErrInvalidRepositoryName = errors.New("Invalid repository name (ex: \"registry.domain.tld/myrepos\")")
emptyServiceConfig = newServiceConfig(ServiceOptions{})
emptyServiceConfig, _ = newServiceConfig(ServiceOptions{})
)
var (
@ -72,37 +70,28 @@ var (
// for mocking in unit tests
var lookupIP = net.LookupIP
// InstallCliFlags adds command-line options to the top-level flag parser for
// the current process.
func (options *ServiceOptions) InstallCliFlags(flags *pflag.FlagSet) {
ana := opts.NewNamedListOptsRef("allow-nondistributable-artifacts", &options.AllowNondistributableArtifacts, ValidateIndexName)
mirrors := opts.NewNamedListOptsRef("registry-mirrors", &options.Mirrors, ValidateMirror)
insecureRegistries := opts.NewNamedListOptsRef("insecure-registries", &options.InsecureRegistries, ValidateIndexName)
flags.Var(ana, "allow-nondistributable-artifacts", "Allow push of nondistributable artifacts to registry")
flags.Var(mirrors, "registry-mirror", "Preferred Docker registry mirror")
flags.Var(insecureRegistries, "insecure-registry", "Enable insecure registry communication")
options.installCliPlatformFlags(flags)
}
// newServiceConfig returns a new instance of ServiceConfig
func newServiceConfig(options ServiceOptions) *serviceConfig {
func newServiceConfig(options ServiceOptions) (*serviceConfig, error) {
config := &serviceConfig{
ServiceConfig: registrytypes.ServiceConfig{
InsecureRegistryCIDRs: make([]*registrytypes.NetIPNet, 0),
IndexConfigs: make(map[string]*registrytypes.IndexInfo, 0),
IndexConfigs: make(map[string]*registrytypes.IndexInfo),
// Hack: Bypass setting the mirrors to IndexConfigs since they are going away
// and Mirrors are only for the official registry anyways.
},
V2Only: options.V2Only,
}
if err := config.LoadAllowNondistributableArtifacts(options.AllowNondistributableArtifacts); err != nil {
return nil, err
}
if err := config.LoadMirrors(options.Mirrors); err != nil {
return nil, err
}
if err := config.LoadInsecureRegistries(options.InsecureRegistries); err != nil {
return nil, err
}
config.LoadAllowNondistributableArtifacts(options.AllowNondistributableArtifacts)
config.LoadMirrors(options.Mirrors)
config.LoadInsecureRegistries(options.InsecureRegistries)
return config
return config, nil
}
// LoadAllowNondistributableArtifacts loads allow-nondistributable-artifacts registries into config.
@ -187,7 +176,7 @@ func (config *serviceConfig) LoadInsecureRegistries(registries []string) error {
originalIndexInfos := config.ServiceConfig.IndexConfigs
config.ServiceConfig.InsecureRegistryCIDRs = make([]*registrytypes.NetIPNet, 0)
config.ServiceConfig.IndexConfigs = make(map[string]*registrytypes.IndexInfo, 0)
config.ServiceConfig.IndexConfigs = make(map[string]*registrytypes.IndexInfo)
skip:
for _, r := range registries {
@ -252,7 +241,7 @@ skip:
return nil
}
// allowNondistributableArtifacts returns true if the provided hostname is part of the list of regsitries
// allowNondistributableArtifacts returns true if the provided hostname is part of the list of registries
// that allow push of nondistributable artifacts.
//
// The list can contain elements with CIDR notation to specify a whole subnet. If the subnet contains an IP
@ -354,7 +343,7 @@ func ValidateIndexName(val string) (string, error) {
val = "docker.io"
}
if strings.HasPrefix(val, "-") || strings.HasSuffix(val, "-") {
return "", fmt.Errorf("Invalid index name (%s). Cannot begin or end with a hyphen.", val)
return "", fmt.Errorf("invalid index name (%s). Cannot begin or end with a hyphen", val)
}
return val, nil
}

View file

@ -2,10 +2,6 @@
package registry
import (
"github.com/spf13/pflag"
)
var (
// CertsDir is the directory where certificates are stored
CertsDir = "/etc/docker/certs.d"
@ -18,8 +14,3 @@ var (
func cleanPath(s string) string {
return s
}
// installCliPlatformFlags handles any platform specific flags for the service.
func (options *ServiceOptions) installCliPlatformFlags(flags *pflag.FlagSet) {
flags.BoolVar(&options.V2Only, "disable-legacy-registry", false, "Disable contacting legacy registries")
}

View file

@ -4,8 +4,6 @@ import (
"os"
"path/filepath"
"strings"
"github.com/spf13/pflag"
)
// CertsDir is the directory where certificates are stored
@ -18,8 +16,3 @@ var CertsDir = os.Getenv("programdata") + `\docker\certs.d`
func cleanPath(s string) string {
return filepath.FromSlash(strings.Replace(s, ":", "", -1))
}
// installCliPlatformFlags handles any platform specific flags for the service.
func (options *ServiceOptions) installCliPlatformFlags(flags *pflag.FlagSet) {
// No Windows specific flags.
}

View file

@ -9,9 +9,9 @@ import (
"net/url"
"strings"
"github.com/Sirupsen/logrus"
"github.com/docker/distribution/registry/client/transport"
registrytypes "github.com/docker/docker/api/types/registry"
"github.com/sirupsen/logrus"
)
// V1Endpoint stores basic information about a V1 registry endpoint.
@ -67,7 +67,7 @@ func validateEndpoint(endpoint *V1Endpoint) error {
return nil
}
func newV1Endpoint(address url.URL, tlsConfig *tls.Config, userAgent string, metaHeaders http.Header) (*V1Endpoint, error) {
func newV1Endpoint(address url.URL, tlsConfig *tls.Config, userAgent string, metaHeaders http.Header) *V1Endpoint {
endpoint := &V1Endpoint{
IsSecure: (tlsConfig == nil || !tlsConfig.InsecureSkipVerify),
URL: new(url.URL),
@ -78,7 +78,7 @@ func newV1Endpoint(address url.URL, tlsConfig *tls.Config, userAgent string, met
// TODO(tiborvass): make sure a ConnectTimeout transport is used
tr := NewTransport(tlsConfig)
endpoint.client = HTTPClient(transport.NewTransport(tr, DockerHeaders(userAgent, metaHeaders)...))
return endpoint, nil
return endpoint
}
// trimV1Address trims the version off the address and returns the
@ -123,7 +123,7 @@ func newV1EndpointFromStr(address string, tlsConfig *tls.Config, userAgent strin
return nil, err
}
endpoint, err := newV1Endpoint(*uri, tlsConfig, userAgent, metaHeaders)
endpoint := newV1Endpoint(*uri, tlsConfig, userAgent, metaHeaders)
if err != nil {
return nil, err
}
@ -175,7 +175,7 @@ func (e *V1Endpoint) Ping() (PingResult, error) {
Standalone: true,
}
if err := json.Unmarshal(jsonString, &info); err != nil {
logrus.Debugf("Error unmarshalling the _ping PingResult: %s", err)
logrus.Debugf("Error unmarshaling the _ping PingResult: %s", err)
// don't stop here. Just assume sane defaults
}
if hdr := resp.Header.Get("X-Docker-Registry-Version"); hdr != "" {

86
vendor/github.com/docker/docker/registry/errors.go generated vendored Normal file
View file

@ -0,0 +1,86 @@
package registry
import (
"net/url"
"github.com/docker/distribution/registry/api/errcode"
)
type notFoundError string
func (e notFoundError) Error() string {
return string(e)
}
func (notFoundError) NotFound() {}
type validationError struct {
cause error
}
func (e validationError) Error() string {
return e.cause.Error()
}
func (e validationError) InvalidParameter() {}
func (e validationError) Cause() error {
return e.cause
}
type unauthorizedError struct {
cause error
}
func (e unauthorizedError) Error() string {
return e.cause.Error()
}
func (e unauthorizedError) Unauthorized() {}
func (e unauthorizedError) Cause() error {
return e.cause
}
type systemError struct {
cause error
}
func (e systemError) Error() string {
return e.cause.Error()
}
func (e systemError) SystemError() {}
func (e systemError) Cause() error {
return e.cause
}
type notActivatedError struct {
cause error
}
func (e notActivatedError) Error() string {
return e.cause.Error()
}
func (e notActivatedError) Forbidden() {}
func (e notActivatedError) Cause() error {
return e.cause
}
func translateV2AuthError(err error) error {
switch e := err.(type) {
case *url.Error:
switch e2 := e.Err.(type) {
case errcode.Error:
switch e2.Code {
case errcode.ErrorCodeUnauthorized:
return unauthorizedError{err}
}
}
}
return err
}

View file

@ -13,10 +13,10 @@ import (
"strings"
"time"
"github.com/Sirupsen/logrus"
"github.com/docker/distribution/registry/client/transport"
"github.com/docker/go-connections/sockets"
"github.com/docker/go-connections/tlsconfig"
"github.com/sirupsen/logrus"
)
var (
@ -81,7 +81,7 @@ func ReadCertsDirectory(tlsConfig *tls.Config, directory string) error {
keyName := certName[:len(certName)-5] + ".key"
logrus.Debugf("cert: %s", filepath.Join(directory, f.Name()))
if !hasFile(fs, keyName) {
return fmt.Errorf("Missing key %s for client certificate %s. Note that CA certificates should use the extension .crt.", keyName, certName)
return fmt.Errorf("missing key %s for client certificate %s. Note that CA certificates should use the extension .crt", keyName, certName)
}
cert, err := tls.LoadX509KeyPair(filepath.Join(directory, certName), filepath.Join(directory, keyName))
if err != nil {

View file

@ -0,0 +1,96 @@
package resumable
import (
"fmt"
"io"
"net/http"
"time"
"github.com/sirupsen/logrus"
)
type requestReader struct {
client *http.Client
request *http.Request
lastRange int64
totalSize int64
currentResponse *http.Response
failures uint32
maxFailures uint32
waitDuration time.Duration
}
// NewRequestReader makes it possible to resume reading a request's body transparently
// maxfail is the number of times we retry to make requests again (not resumes)
// totalsize is the total length of the body; auto detect if not provided
func NewRequestReader(c *http.Client, r *http.Request, maxfail uint32, totalsize int64) io.ReadCloser {
return &requestReader{client: c, request: r, maxFailures: maxfail, totalSize: totalsize, waitDuration: 5 * time.Second}
}
// NewRequestReaderWithInitialResponse makes it possible to resume
// reading the body of an already initiated request.
func NewRequestReaderWithInitialResponse(c *http.Client, r *http.Request, maxfail uint32, totalsize int64, initialResponse *http.Response) io.ReadCloser {
return &requestReader{client: c, request: r, maxFailures: maxfail, totalSize: totalsize, currentResponse: initialResponse, waitDuration: 5 * time.Second}
}
func (r *requestReader) Read(p []byte) (n int, err error) {
if r.client == nil || r.request == nil {
return 0, fmt.Errorf("client and request can't be nil")
}
isFreshRequest := false
if r.lastRange != 0 && r.currentResponse == nil {
readRange := fmt.Sprintf("bytes=%d-%d", r.lastRange, r.totalSize)
r.request.Header.Set("Range", readRange)
time.Sleep(r.waitDuration)
}
if r.currentResponse == nil {
r.currentResponse, err = r.client.Do(r.request)
isFreshRequest = true
}
if err != nil && r.failures+1 != r.maxFailures {
r.cleanUpResponse()
r.failures++
time.Sleep(time.Duration(r.failures) * r.waitDuration)
return 0, nil
} else if err != nil {
r.cleanUpResponse()
return 0, err
}
if r.currentResponse.StatusCode == 416 && r.lastRange == r.totalSize && r.currentResponse.ContentLength == 0 {
r.cleanUpResponse()
return 0, io.EOF
} else if r.currentResponse.StatusCode != 206 && r.lastRange != 0 && isFreshRequest {
r.cleanUpResponse()
return 0, fmt.Errorf("the server doesn't support byte ranges")
}
if r.totalSize == 0 {
r.totalSize = r.currentResponse.ContentLength
} else if r.totalSize <= 0 {
r.cleanUpResponse()
return 0, fmt.Errorf("failed to auto detect content length")
}
n, err = r.currentResponse.Body.Read(p)
r.lastRange += int64(n)
if err != nil {
r.cleanUpResponse()
}
if err != nil && err != io.EOF {
logrus.Infof("encountered error during pull and clearing it before resume: %s", err)
err = nil
}
return n, err
}
func (r *requestReader) Close() error {
r.cleanUpResponse()
r.client = nil
r.request = nil
return nil
}
func (r *requestReader) cleanUpResponse() {
if r.currentResponse != nil {
r.currentResponse.Body.Close()
r.currentResponse = nil
}
}

View file

@ -2,7 +2,6 @@ package registry
import (
"crypto/tls"
"fmt"
"net/http"
"net/url"
"strings"
@ -10,11 +9,12 @@ import (
"golang.org/x/net/context"
"github.com/Sirupsen/logrus"
"github.com/docker/distribution/reference"
"github.com/docker/distribution/registry/client/auth"
"github.com/docker/docker/api/types"
registrytypes "github.com/docker/docker/api/types/registry"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
const (
@ -45,10 +45,10 @@ type DefaultService struct {
// NewService returns a new instance of DefaultService ready to be
// installed into an engine.
func NewService(options ServiceOptions) *DefaultService {
return &DefaultService{
config: newServiceConfig(options),
}
func NewService(options ServiceOptions) (*DefaultService, error) {
config, err := newServiceConfig(options)
return &DefaultService{config: config}, err
}
// ServiceConfig returns the public registry service configuration.
@ -117,12 +117,12 @@ func (s *DefaultService) Auth(ctx context.Context, authConfig *types.AuthConfig,
}
u, err := url.Parse(serverAddress)
if err != nil {
return "", "", fmt.Errorf("unable to parse server address: %v", err)
return "", "", validationError{errors.Errorf("unable to parse server address: %v", err)}
}
endpoints, err := s.LookupPushEndpoints(u.Host)
if err != nil {
return "", "", err
return "", "", validationError{err}
}
for _, endpoint := range endpoints {
@ -140,6 +140,7 @@ func (s *DefaultService) Auth(ctx context.Context, authConfig *types.AuthConfig,
logrus.Infof("Error logging in to %s endpoint, trying next endpoint: %v", endpoint.Version, err)
continue
}
return "", "", err
}
@ -258,7 +259,7 @@ type APIEndpoint struct {
}
// ToV1Endpoint returns a V1 API endpoint based on the APIEndpoint
func (e APIEndpoint) ToV1Endpoint(userAgent string, metaHeaders http.Header) (*V1Endpoint, error) {
func (e APIEndpoint) ToV1Endpoint(userAgent string, metaHeaders http.Header) *V1Endpoint {
return newV1Endpoint(*e.URL, e.TLSConfig, userAgent, metaHeaders)
}

View file

@ -3,7 +3,6 @@ package registry
import (
"bytes"
"crypto/sha256"
"errors"
"sync"
// this is required for some certificates
_ "crypto/sha512"
@ -18,21 +17,23 @@ import (
"strconv"
"strings"
"github.com/Sirupsen/logrus"
"github.com/docker/distribution/reference"
"github.com/docker/distribution/registry/api/errcode"
"github.com/docker/docker/api/types"
registrytypes "github.com/docker/docker/api/types/registry"
"github.com/docker/docker/pkg/httputils"
"github.com/docker/docker/pkg/ioutils"
"github.com/docker/docker/pkg/jsonmessage"
"github.com/docker/docker/pkg/stringid"
"github.com/docker/docker/pkg/tarsum"
"github.com/docker/docker/registry/resumable"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
var (
// ErrRepoNotFound is returned if the repository didn't exist on the
// remote side
ErrRepoNotFound = errors.New("Repository not found")
ErrRepoNotFound notFoundError = "Repository not found"
)
// A Session is used to communicate with a V1 registry
@ -226,7 +227,7 @@ func (r *Session) GetRemoteHistory(imgID, registry string) ([]string, error) {
if res.StatusCode == 401 {
return nil, errcode.ErrorCodeUnauthorized.WithArgs()
}
return nil, httputils.NewHTTPRequestError(fmt.Sprintf("Server error: %d trying to fetch remote history for %s", res.StatusCode, imgID), res)
return nil, newJSONError(fmt.Sprintf("Server error: %d trying to fetch remote history for %s", res.StatusCode, imgID), res)
}
var history []string
@ -246,7 +247,7 @@ func (r *Session) LookupRemoteImage(imgID, registry string) error {
}
res.Body.Close()
if res.StatusCode != 200 {
return httputils.NewHTTPRequestError(fmt.Sprintf("HTTP code %d", res.StatusCode), res)
return newJSONError(fmt.Sprintf("HTTP code %d", res.StatusCode), res)
}
return nil
}
@ -259,7 +260,7 @@ func (r *Session) GetRemoteImageJSON(imgID, registry string) ([]byte, int64, err
}
defer res.Body.Close()
if res.StatusCode != 200 {
return nil, -1, httputils.NewHTTPRequestError(fmt.Sprintf("HTTP code %d", res.StatusCode), res)
return nil, -1, newJSONError(fmt.Sprintf("HTTP code %d", res.StatusCode), res)
}
// if the size header is not present, then set it to '-1'
imageSize := int64(-1)
@ -313,7 +314,7 @@ func (r *Session) GetRemoteImageLayer(imgID, registry string, imgSize int64) (io
if res.Header.Get("Accept-Ranges") == "bytes" && imgSize > 0 {
logrus.Debug("server supports resume")
return httputils.ResumableRequestReaderWithInitialResponse(r.client, req, 5, imgSize, res), nil
return resumable.NewRequestReaderWithInitialResponse(r.client, req, 5, imgSize, res), nil
}
logrus.Debug("server doesn't support resume")
return res.Body, nil
@ -433,7 +434,7 @@ func (r *Session) GetRepositoryData(name reference.Named) (*RepositoryData, erro
// "Get https://index.docker.io/v1/repositories/library/busybox/images: i/o timeout"
// was a top search on the docker user forum
if isTimeout(err) {
return nil, fmt.Errorf("Network timed out while trying to connect to %s. You may want to check your internet connection or if you are behind a proxy.", repositoryTarget)
return nil, fmt.Errorf("network timed out while trying to connect to %s. You may want to check your internet connection or if you are behind a proxy", repositoryTarget)
}
return nil, fmt.Errorf("Error while pulling image: %v", err)
}
@ -444,13 +445,13 @@ func (r *Session) GetRepositoryData(name reference.Named) (*RepositoryData, erro
// TODO: Right now we're ignoring checksums in the response body.
// In the future, we need to use them to check image validity.
if res.StatusCode == 404 {
return nil, httputils.NewHTTPRequestError(fmt.Sprintf("HTTP code: %d", res.StatusCode), res)
return nil, newJSONError(fmt.Sprintf("HTTP code: %d", res.StatusCode), res)
} else if res.StatusCode != 200 {
errBody, err := ioutil.ReadAll(res.Body)
if err != nil {
logrus.Debugf("Error reading response body: %s", err)
}
return nil, httputils.NewHTTPRequestError(fmt.Sprintf("Error: Status %d trying to pull repository %s: %q", res.StatusCode, reference.Path(name), errBody), res)
return nil, newJSONError(fmt.Sprintf("Error: Status %d trying to pull repository %s: %q", res.StatusCode, reference.Path(name), errBody), res)
}
var endpoints []string
@ -537,12 +538,12 @@ func (r *Session) PushImageJSONRegistry(imgData *ImgData, jsonRaw []byte, regist
}
defer res.Body.Close()
if res.StatusCode == 401 && strings.HasPrefix(registry, "http://") {
return httputils.NewHTTPRequestError("HTTP code 401, Docker will not send auth headers over HTTP.", res)
return newJSONError("HTTP code 401, Docker will not send auth headers over HTTP.", res)
}
if res.StatusCode != 200 {
errBody, err := ioutil.ReadAll(res.Body)
if err != nil {
return httputils.NewHTTPRequestError(fmt.Sprintf("HTTP code %d while uploading metadata and error when trying to parse response body: %s", res.StatusCode, err), res)
return newJSONError(fmt.Sprintf("HTTP code %d while uploading metadata and error when trying to parse response body: %s", res.StatusCode, err), res)
}
var jsonBody map[string]string
if err := json.Unmarshal(errBody, &jsonBody); err != nil {
@ -550,7 +551,7 @@ func (r *Session) PushImageJSONRegistry(imgData *ImgData, jsonRaw []byte, regist
} else if jsonBody["error"] == "Image already exists" {
return ErrAlreadyExists
}
return httputils.NewHTTPRequestError(fmt.Sprintf("HTTP code %d while uploading metadata: %q", res.StatusCode, errBody), res)
return newJSONError(fmt.Sprintf("HTTP code %d while uploading metadata: %q", res.StatusCode, errBody), res)
}
return nil
}
@ -591,9 +592,9 @@ func (r *Session) PushImageLayerRegistry(imgID string, layer io.Reader, registry
if res.StatusCode != 200 {
errBody, err := ioutil.ReadAll(res.Body)
if err != nil {
return "", "", httputils.NewHTTPRequestError(fmt.Sprintf("HTTP code %d while uploading metadata and error when trying to parse response body: %s", res.StatusCode, err), res)
return "", "", newJSONError(fmt.Sprintf("HTTP code %d while uploading metadata and error when trying to parse response body: %s", res.StatusCode, err), res)
}
return "", "", httputils.NewHTTPRequestError(fmt.Sprintf("Received HTTP code %d while uploading layer: %q", res.StatusCode, errBody), res)
return "", "", newJSONError(fmt.Sprintf("Received HTTP code %d while uploading layer: %q", res.StatusCode, errBody), res)
}
checksumPayload = "sha256:" + hex.EncodeToString(h.Sum(nil))
@ -619,7 +620,7 @@ func (r *Session) PushRegistryTag(remote reference.Named, revision, tag, registr
}
res.Body.Close()
if res.StatusCode != 200 && res.StatusCode != 201 {
return httputils.NewHTTPRequestError(fmt.Sprintf("Internal server error: %d trying to push tag %s on %s", res.StatusCode, tag, reference.Path(remote)), res)
return newJSONError(fmt.Sprintf("Internal server error: %d trying to push tag %s on %s", res.StatusCode, tag, reference.Path(remote)), res)
}
return nil
}
@ -683,7 +684,7 @@ func (r *Session) PushImageJSONIndex(remote reference.Named, imgList []*ImgData,
if err != nil {
logrus.Debugf("Error reading response body: %s", err)
}
return nil, httputils.NewHTTPRequestError(fmt.Sprintf("Error: Status %d trying to push repository %s: %q", res.StatusCode, reference.Path(remote), errBody), res)
return nil, newJSONError(fmt.Sprintf("Error: Status %d trying to push repository %s: %q", res.StatusCode, reference.Path(remote), errBody), res)
}
tokens = res.Header["X-Docker-Token"]
logrus.Debugf("Auth token: %v", tokens)
@ -701,7 +702,7 @@ func (r *Session) PushImageJSONIndex(remote reference.Named, imgList []*ImgData,
if err != nil {
logrus.Debugf("Error reading response body: %s", err)
}
return nil, httputils.NewHTTPRequestError(fmt.Sprintf("Error: Status %d trying to push checksums %s: %q", res.StatusCode, reference.Path(remote), errBody), res)
return nil, newJSONError(fmt.Sprintf("Error: Status %d trying to push checksums %s: %q", res.StatusCode, reference.Path(remote), errBody), res)
}
}
@ -733,40 +734,27 @@ func shouldRedirect(response *http.Response) bool {
// SearchRepositories performs a search against the remote repository
func (r *Session) SearchRepositories(term string, limit int) (*registrytypes.SearchResults, error) {
if limit < 1 || limit > 100 {
return nil, fmt.Errorf("Limit %d is outside the range of [1, 100]", limit)
return nil, validationError{errors.Errorf("Limit %d is outside the range of [1, 100]", limit)}
}
logrus.Debugf("Index server: %s", r.indexEndpoint)
u := r.indexEndpoint.String() + "search?q=" + url.QueryEscape(term) + "&n=" + url.QueryEscape(fmt.Sprintf("%d", limit))
req, err := http.NewRequest("GET", u, nil)
if err != nil {
return nil, fmt.Errorf("Error while getting from the server: %v", err)
return nil, errors.Wrap(validationError{err}, "Error building request")
}
// Have the AuthTransport send authentication, when logged in.
req.Header.Set("X-Docker-Token", "true")
res, err := r.client.Do(req)
if err != nil {
return nil, err
return nil, systemError{err}
}
defer res.Body.Close()
if res.StatusCode != 200 {
return nil, httputils.NewHTTPRequestError(fmt.Sprintf("Unexpected status code %d", res.StatusCode), res)
return nil, newJSONError(fmt.Sprintf("Unexpected status code %d", res.StatusCode), res)
}
result := new(registrytypes.SearchResults)
return result, json.NewDecoder(res.Body).Decode(result)
}
// GetAuthConfig returns the authentication settings for a session
// TODO(tiborvass): remove this once registry client v2 is vendored
func (r *Session) GetAuthConfig(withPasswd bool) *types.AuthConfig {
password := ""
if withPasswd {
password = r.authConfig.Password
}
return &types.AuthConfig{
Username: r.authConfig.Username,
Password: password,
}
return result, errors.Wrap(json.NewDecoder(res.Body).Decode(result), "error decoding registry search results")
}
func isTimeout(err error) bool {
@ -781,3 +769,10 @@ func isTimeout(err error) bool {
t, ok := e.(timeout)
return ok && t.Timeout()
}
func newJSONError(msg string, res *http.Response) error {
return &jsonmessage.JSONError{
Message: msg,
Code: res.StatusCode,
}
}