github.com/rentongzhang/docker@v1.8.2-rc1/graph/registry.go (about)

     1  package graph
     2  
     3  import (
     4  	"errors"
     5  	"net"
     6  	"net/http"
     7  	"net/url"
     8  	"time"
     9  
    10  	"github.com/Sirupsen/logrus"
    11  	"github.com/docker/distribution"
    12  	"github.com/docker/distribution/digest"
    13  	"github.com/docker/distribution/manifest"
    14  	"github.com/docker/distribution/registry/client"
    15  	"github.com/docker/distribution/registry/client/auth"
    16  	"github.com/docker/distribution/registry/client/transport"
    17  	"github.com/docker/docker/cliconfig"
    18  	"github.com/docker/docker/registry"
    19  	"golang.org/x/net/context"
    20  )
    21  
    22  type dumbCredentialStore struct {
    23  	auth *cliconfig.AuthConfig
    24  }
    25  
    26  func (dcs dumbCredentialStore) Basic(*url.URL) (string, string) {
    27  	return dcs.auth.Username, dcs.auth.Password
    28  }
    29  
    30  // v2 only
    31  func NewV2Repository(repoInfo *registry.RepositoryInfo, endpoint registry.APIEndpoint, metaHeaders http.Header, authConfig *cliconfig.AuthConfig) (distribution.Repository, error) {
    32  	ctx := context.Background()
    33  
    34  	repoName := repoInfo.CanonicalName
    35  	// If endpoint does not support CanonicalName, use the RemoteName instead
    36  	if endpoint.TrimHostname {
    37  		repoName = repoInfo.RemoteName
    38  	}
    39  
    40  	// TODO(dmcgowan): Call close idle connections when complete, use keep alive
    41  	base := &http.Transport{
    42  		Proxy: http.ProxyFromEnvironment,
    43  		Dial: (&net.Dialer{
    44  			Timeout:   30 * time.Second,
    45  			KeepAlive: 30 * time.Second,
    46  			DualStack: true,
    47  		}).Dial,
    48  		TLSHandshakeTimeout: 10 * time.Second,
    49  		TLSClientConfig:     endpoint.TLSConfig,
    50  		// TODO(dmcgowan): Call close idle connections when complete and use keep alive
    51  		DisableKeepAlives: true,
    52  	}
    53  
    54  	modifiers := registry.DockerHeaders(metaHeaders)
    55  	authTransport := transport.NewTransport(base, modifiers...)
    56  	pingClient := &http.Client{
    57  		Transport: authTransport,
    58  		Timeout:   5 * time.Second,
    59  	}
    60  	endpointStr := endpoint.URL + "/v2/"
    61  	req, err := http.NewRequest("GET", endpointStr, nil)
    62  	if err != nil {
    63  		return nil, err
    64  	}
    65  	resp, err := pingClient.Do(req)
    66  	if err != nil {
    67  		return nil, err
    68  	}
    69  	defer resp.Body.Close()
    70  
    71  	versions := auth.APIVersions(resp, endpoint.VersionHeader)
    72  	if endpoint.VersionHeader != "" && len(endpoint.Versions) > 0 {
    73  		var foundVersion bool
    74  		for _, version := range endpoint.Versions {
    75  			for _, pingVersion := range versions {
    76  				if version == pingVersion {
    77  					foundVersion = true
    78  				}
    79  			}
    80  		}
    81  		if !foundVersion {
    82  			return nil, errors.New("endpoint does not support v2 API")
    83  		}
    84  	}
    85  
    86  	challengeManager := auth.NewSimpleChallengeManager()
    87  	if err := challengeManager.AddResponse(resp); err != nil {
    88  		return nil, err
    89  	}
    90  
    91  	creds := dumbCredentialStore{auth: authConfig}
    92  	tokenHandler := auth.NewTokenHandler(authTransport, creds, repoName, "push", "pull")
    93  	basicHandler := auth.NewBasicHandler(creds)
    94  	modifiers = append(modifiers, auth.NewAuthorizer(challengeManager, tokenHandler, basicHandler))
    95  	tr := transport.NewTransport(base, modifiers...)
    96  
    97  	return client.NewRepository(ctx, repoName, endpoint.URL, tr)
    98  }
    99  
   100  func digestFromManifest(m *manifest.SignedManifest, localName string) (digest.Digest, int, error) {
   101  	payload, err := m.Payload()
   102  	if err != nil {
   103  		logrus.Debugf("could not retrieve manifest payload: %v", err)
   104  		return "", 0, err
   105  	}
   106  	manifestDigest, err := digest.FromBytes(payload)
   107  	if err != nil {
   108  		logrus.Infof("Could not compute manifest digest for %s:%s : %v", localName, m.Tag, err)
   109  	}
   110  	return manifestDigest, len(payload), nil
   111  }