github.com/clintkitson/docker@v1.9.1/registry/service.go (about) 1 package registry 2 3 import ( 4 "crypto/tls" 5 "net/http" 6 "net/url" 7 8 "github.com/docker/distribution/registry/client/auth" 9 "github.com/docker/docker/cliconfig" 10 ) 11 12 // Service is a registry service. It tracks configuration data such as a list 13 // of mirrors. 14 type Service struct { 15 Config *ServiceConfig 16 } 17 18 // NewService returns a new instance of Service ready to be 19 // installed into an engine. 20 func NewService(options *Options) *Service { 21 return &Service{ 22 Config: NewServiceConfig(options), 23 } 24 } 25 26 // Auth contacts the public registry with the provided credentials, 27 // and returns OK if authentication was successful. 28 // It can be used to verify the validity of a client's credentials. 29 func (s *Service) Auth(authConfig *cliconfig.AuthConfig) (string, error) { 30 addr := authConfig.ServerAddress 31 if addr == "" { 32 // Use the official registry address if not specified. 33 addr = IndexServer 34 } 35 index, err := s.ResolveIndex(addr) 36 if err != nil { 37 return "", err 38 } 39 40 endpointVersion := APIVersion(APIVersionUnknown) 41 if V2Only { 42 // Override the endpoint to only attempt a v2 ping 43 endpointVersion = APIVersion2 44 } 45 46 endpoint, err := NewEndpoint(index, nil, endpointVersion) 47 if err != nil { 48 return "", err 49 } 50 authConfig.ServerAddress = endpoint.String() 51 return Login(authConfig, endpoint) 52 } 53 54 // Search queries the public registry for images matching the specified 55 // search terms, and returns the results. 56 func (s *Service) Search(term string, authConfig *cliconfig.AuthConfig, headers map[string][]string) (*SearchResults, error) { 57 58 repoInfo, err := s.ResolveRepositoryBySearch(term) 59 if err != nil { 60 return nil, err 61 } 62 63 // *TODO: Search multiple indexes. 64 endpoint, err := NewEndpoint(repoInfo.Index, http.Header(headers), APIVersionUnknown) 65 if err != nil { 66 return nil, err 67 } 68 69 r, err := NewSession(endpoint.client, authConfig, endpoint) 70 if err != nil { 71 return nil, err 72 } 73 return r.SearchRepositories(repoInfo.GetSearchTerm()) 74 } 75 76 // ResolveRepository splits a repository name into its components 77 // and configuration of the associated registry. 78 func (s *Service) ResolveRepository(name string) (*RepositoryInfo, error) { 79 return s.Config.NewRepositoryInfo(name, false) 80 } 81 82 // ResolveRepositoryBySearch splits a repository name into its components 83 // and configuration of the associated registry. 84 func (s *Service) ResolveRepositoryBySearch(name string) (*RepositoryInfo, error) { 85 return s.Config.NewRepositoryInfo(name, true) 86 } 87 88 // ResolveIndex takes indexName and returns index info 89 func (s *Service) ResolveIndex(name string) (*IndexInfo, error) { 90 return s.Config.NewIndexInfo(name) 91 } 92 93 // APIEndpoint represents a remote API endpoint 94 type APIEndpoint struct { 95 Mirror bool 96 URL string 97 Version APIVersion 98 Official bool 99 TrimHostname bool 100 TLSConfig *tls.Config 101 VersionHeader string 102 Versions []auth.APIVersion 103 } 104 105 // ToV1Endpoint returns a V1 API endpoint based on the APIEndpoint 106 func (e APIEndpoint) ToV1Endpoint(metaHeaders http.Header) (*Endpoint, error) { 107 return newEndpoint(e.URL, e.TLSConfig, metaHeaders) 108 } 109 110 // TLSConfig constructs a client TLS configuration based on server defaults 111 func (s *Service) TLSConfig(hostname string) (*tls.Config, error) { 112 return newTLSConfig(hostname, s.Config.isSecureIndex(hostname)) 113 } 114 115 func (s *Service) tlsConfigForMirror(mirror string) (*tls.Config, error) { 116 mirrorURL, err := url.Parse(mirror) 117 if err != nil { 118 return nil, err 119 } 120 return s.TLSConfig(mirrorURL.Host) 121 } 122 123 // LookupPullEndpoints creates an list of endpoints to try to pull from, in order of preference. 124 // It gives preference to v2 endpoints over v1, mirrors over the actual 125 // registry, and HTTPS over plain HTTP. 126 func (s *Service) LookupPullEndpoints(repoName string) (endpoints []APIEndpoint, err error) { 127 return s.lookupEndpoints(repoName) 128 } 129 130 // LookupPushEndpoints creates an list of endpoints to try to push to, in order of preference. 131 // It gives preference to v2 endpoints over v1, and HTTPS over plain HTTP. 132 // Mirrors are not included. 133 func (s *Service) LookupPushEndpoints(repoName string) (endpoints []APIEndpoint, err error) { 134 allEndpoints, err := s.lookupEndpoints(repoName) 135 if err == nil { 136 for _, endpoint := range allEndpoints { 137 if !endpoint.Mirror { 138 endpoints = append(endpoints, endpoint) 139 } 140 } 141 } 142 return endpoints, err 143 } 144 145 func (s *Service) lookupEndpoints(repoName string) (endpoints []APIEndpoint, err error) { 146 endpoints, err = s.lookupV2Endpoints(repoName) 147 if err != nil { 148 return nil, err 149 } 150 151 if V2Only { 152 return endpoints, nil 153 } 154 155 legacyEndpoints, err := s.lookupV1Endpoints(repoName) 156 if err != nil { 157 return nil, err 158 } 159 endpoints = append(endpoints, legacyEndpoints...) 160 161 return endpoints, nil 162 }