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 }