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  }