فهرست منبع

Improve documentation and golint compliance of registry package

* Add godoc documentation where it was missing

* Change identifier names that don't match Go style, such as INDEX_NAME

* Rename RegistryInfo to PingResult, which more accurately describes
  what this structure is for. It also has the benefit of making the name
  not stutter if used outside the package.

Updates #14756

Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>
Aaron Lehmann 10 سال پیش
والد
کامیت
4fcb9ac40c

+ 2 - 2
api/client/login.go

@@ -22,7 +22,7 @@ import (
 //
 //
 // Usage: docker login SERVER
 // Usage: docker login SERVER
 func (cli *DockerCli) CmdLogin(args ...string) error {
 func (cli *DockerCli) CmdLogin(args ...string) error {
-	cmd := Cli.Subcmd("login", []string{"[SERVER]"}, "Register or log in to a Docker registry server, if no server is\nspecified \""+registry.INDEXSERVER+"\" is the default.", true)
+	cmd := Cli.Subcmd("login", []string{"[SERVER]"}, "Register or log in to a Docker registry server, if no server is\nspecified \""+registry.IndexServer+"\" is the default.", true)
 	cmd.Require(flag.Max, 1)
 	cmd.Require(flag.Max, 1)
 
 
 	var username, password, email string
 	var username, password, email string
@@ -33,7 +33,7 @@ func (cli *DockerCli) CmdLogin(args ...string) error {
 
 
 	cmd.ParseFlags(args, true)
 	cmd.ParseFlags(args, true)
 
 
-	serverAddress := registry.INDEXSERVER
+	serverAddress := registry.IndexServer
 	if len(cmd.Args()) > 0 {
 	if len(cmd.Args()) > 0 {
 		serverAddress = cmd.Arg(0)
 		serverAddress = cmd.Arg(0)
 	}
 	}

+ 2 - 2
api/client/logout.go

@@ -14,12 +14,12 @@ import (
 //
 //
 // Usage: docker logout [SERVER]
 // Usage: docker logout [SERVER]
 func (cli *DockerCli) CmdLogout(args ...string) error {
 func (cli *DockerCli) CmdLogout(args ...string) error {
-	cmd := Cli.Subcmd("logout", []string{"[SERVER]"}, "Log out from a Docker registry, if no server is\nspecified \""+registry.INDEXSERVER+"\" is the default.", true)
+	cmd := Cli.Subcmd("logout", []string{"[SERVER]"}, "Log out from a Docker registry, if no server is\nspecified \""+registry.IndexServer+"\" is the default.", true)
 	cmd.Require(flag.Max, 1)
 	cmd.Require(flag.Max, 1)
 
 
 	cmd.ParseFlags(args, true)
 	cmd.ParseFlags(args, true)
 
 
-	serverAddress := registry.INDEXSERVER
+	serverAddress := registry.IndexServer
 	if len(cmd.Args()) > 0 {
 	if len(cmd.Args()) > 0 {
 		serverAddress = cmd.Arg(0)
 		serverAddress = cmd.Arg(0)
 	}
 	}

+ 1 - 1
daemon/info.go

@@ -74,7 +74,7 @@ func (daemon *Daemon) SystemInfo() (*types.Info, error) {
 		NEventsListener:    daemon.EventsService.SubscribersCount(),
 		NEventsListener:    daemon.EventsService.SubscribersCount(),
 		KernelVersion:      kernelVersion,
 		KernelVersion:      kernelVersion,
 		OperatingSystem:    operatingSystem,
 		OperatingSystem:    operatingSystem,
-		IndexServerAddress: registry.INDEXSERVER,
+		IndexServerAddress: registry.IndexServer,
 		RegistryConfig:     daemon.RegistryService.Config,
 		RegistryConfig:     daemon.RegistryService.Config,
 		InitSha1:           dockerversion.INITSHA1,
 		InitSha1:           dockerversion.INITSHA1,
 		InitPath:           initPath,
 		InitPath:           initPath,

+ 1 - 1
graph/pull_v1.go

@@ -33,7 +33,7 @@ func (p *v1Puller) Pull(tag string) (fallback bool, err error) {
 		return true, registry.ErrNoSupport{errors.New("Cannot pull by digest with v1 registry")}
 		return true, registry.ErrNoSupport{errors.New("Cannot pull by digest with v1 registry")}
 	}
 	}
 
 
-	tlsConfig, err := p.registryService.TlsConfig(p.repoInfo.Index.Name)
+	tlsConfig, err := p.registryService.TLSConfig(p.repoInfo.Index.Name)
 	if err != nil {
 	if err != nil {
 		return false, err
 		return false, err
 	}
 	}

+ 1 - 1
graph/push_v1.go

@@ -29,7 +29,7 @@ type v1Pusher struct {
 }
 }
 
 
 func (p *v1Pusher) Push() (fallback bool, err error) {
 func (p *v1Pusher) Push() (fallback bool, err error) {
-	tlsConfig, err := p.registryService.TlsConfig(p.repoInfo.Index.Name)
+	tlsConfig, err := p.registryService.TLSConfig(p.repoInfo.Index.Name)
 	if err != nil {
 	if err != nil {
 		return false, err
 		return false, err
 	}
 	}

+ 1 - 0
hack/make/validate-lint

@@ -36,6 +36,7 @@ packages=(
 	pkg/tlsconfig
 	pkg/tlsconfig
 	pkg/urlutil
 	pkg/urlutil
 	pkg/version
 	pkg/version
+	registry
 	utils
 	utils
 )
 )
 
 

+ 2 - 2
registry/auth.go

@@ -36,7 +36,7 @@ func loginV1(authConfig *cliconfig.AuthConfig, registryEndpoint *Endpoint) (stri
 		return "", fmt.Errorf("Server Error: Server Address not set.")
 		return "", fmt.Errorf("Server Error: Server Address not set.")
 	}
 	}
 
 
-	loginAgainstOfficialIndex := serverAddress == INDEXSERVER
+	loginAgainstOfficialIndex := serverAddress == IndexServer
 
 
 	// to avoid sending the server address to the server it should be removed before being marshalled
 	// to avoid sending the server address to the server it should be removed before being marshalled
 	authCopy := *authConfig
 	authCopy := *authConfig
@@ -220,7 +220,7 @@ func tryV2TokenAuthLogin(authConfig *cliconfig.AuthConfig, params map[string]str
 	return nil
 	return nil
 }
 }
 
 
-// this method matches a auth configuration to a server address or a url
+// ResolveAuthConfig matches an auth configuration to a server address or a URL
 func ResolveAuthConfig(config *cliconfig.ConfigFile, index *IndexInfo) cliconfig.AuthConfig {
 func ResolveAuthConfig(config *cliconfig.ConfigFile, index *IndexInfo) cliconfig.AuthConfig {
 	configKey := index.GetAuthConfigKey()
 	configKey := index.GetAuthConfigKey()
 	// First try the happy case
 	// First try the happy case

+ 5 - 5
registry/auth_test.go

@@ -37,7 +37,7 @@ func setupTempConfigFile() (*cliconfig.ConfigFile, error) {
 	root = filepath.Join(root, cliconfig.ConfigFileName)
 	root = filepath.Join(root, cliconfig.ConfigFileName)
 	configFile := cliconfig.NewConfigFile(root)
 	configFile := cliconfig.NewConfigFile(root)
 
 
-	for _, registry := range []string{"testIndex", INDEXSERVER} {
+	for _, registry := range []string{"testIndex", IndexServer} {
 		configFile.AuthConfigs[registry] = cliconfig.AuthConfig{
 		configFile.AuthConfigs[registry] = cliconfig.AuthConfig{
 			Username: "docker-user",
 			Username: "docker-user",
 			Password: "docker-pass",
 			Password: "docker-pass",
@@ -82,7 +82,7 @@ func TestResolveAuthConfigIndexServer(t *testing.T) {
 	}
 	}
 	defer os.RemoveAll(configFile.Filename())
 	defer os.RemoveAll(configFile.Filename())
 
 
-	indexConfig := configFile.AuthConfigs[INDEXSERVER]
+	indexConfig := configFile.AuthConfigs[IndexServer]
 
 
 	officialIndex := &IndexInfo{
 	officialIndex := &IndexInfo{
 		Official: true,
 		Official: true,
@@ -92,10 +92,10 @@ func TestResolveAuthConfigIndexServer(t *testing.T) {
 	}
 	}
 
 
 	resolved := ResolveAuthConfig(configFile, officialIndex)
 	resolved := ResolveAuthConfig(configFile, officialIndex)
-	assertEqual(t, resolved, indexConfig, "Expected ResolveAuthConfig to return INDEXSERVER")
+	assertEqual(t, resolved, indexConfig, "Expected ResolveAuthConfig to return IndexServer")
 
 
 	resolved = ResolveAuthConfig(configFile, privateIndex)
 	resolved = ResolveAuthConfig(configFile, privateIndex)
-	assertNotEqual(t, resolved, indexConfig, "Expected ResolveAuthConfig to not return INDEXSERVER")
+	assertNotEqual(t, resolved, indexConfig, "Expected ResolveAuthConfig to not return IndexServer")
 }
 }
 
 
 func TestResolveAuthConfigFullURL(t *testing.T) {
 func TestResolveAuthConfigFullURL(t *testing.T) {
@@ -120,7 +120,7 @@ func TestResolveAuthConfigFullURL(t *testing.T) {
 		Password: "baz-pass",
 		Password: "baz-pass",
 		Email:    "baz@example.com",
 		Email:    "baz@example.com",
 	}
 	}
-	configFile.AuthConfigs[INDEXSERVER] = officialAuth
+	configFile.AuthConfigs[IndexServer] = officialAuth
 
 
 	expectedAuths := map[string]cliconfig.AuthConfig{
 	expectedAuths := map[string]cliconfig.AuthConfig{
 		"registry.example.com": registryAuth,
 		"registry.example.com": registryAuth,

+ 29 - 20
registry/config.go

@@ -21,24 +21,33 @@ type Options struct {
 }
 }
 
 
 const (
 const (
-	DEFAULT_NAMESPACE               = "docker.io"
-	DEFAULT_V2_REGISTRY             = "https://registry-1.docker.io"
-	DEFAULT_REGISTRY_VERSION_HEADER = "Docker-Distribution-Api-Version"
-	DEFAULT_V1_REGISTRY             = "https://index.docker.io"
-
-	CERTS_DIR = "/etc/docker/certs.d"
-
-	// Only used for user auth + account creation
-	REGISTRYSERVER = DEFAULT_V2_REGISTRY
-	INDEXSERVER    = DEFAULT_V1_REGISTRY + "/v1/"
-	INDEXNAME      = "docker.io"
-
-	// INDEXSERVER = "https://registry-stage.hub.docker.com/v1/"
+	// DefaultNamespace is the default namespace
+	DefaultNamespace = "docker.io"
+	// DefaultV2Registry is the URI of the default v2 registry
+	DefaultV2Registry = "https://registry-1.docker.io"
+	// DefaultRegistryVersionHeader is the name of the default HTTP header
+	// that carries Registry version info
+	DefaultRegistryVersionHeader = "Docker-Distribution-Api-Version"
+	// DefaultV1Registry is the URI of the default v1 registry
+	DefaultV1Registry = "https://index.docker.io"
+
+	// CertsDir is the directory where certificates are stored
+	CertsDir = "/etc/docker/certs.d"
+
+	// IndexServer is the v1 registry server used for user auth + account creation
+	IndexServer = DefaultV1Registry + "/v1/"
+	// IndexName is the name of the index
+	IndexName = "docker.io"
+
+	// IndexServer = "https://registry-stage.hub.docker.com/v1/"
 )
 )
 
 
 var (
 var (
+	// ErrInvalidRepositoryName is an error returned if the repository name did
+	// not have the correct form
 	ErrInvalidRepositoryName = errors.New("Invalid repository name (ex: \"registry.domain.tld/myrepos\")")
 	ErrInvalidRepositoryName = errors.New("Invalid repository name (ex: \"registry.domain.tld/myrepos\")")
-	emptyServiceConfig       = NewServiceConfig(nil)
+
+	emptyServiceConfig = NewServiceConfig(nil)
 )
 )
 
 
 // InstallFlags adds command-line options to the top-level flag parser for
 // InstallFlags adds command-line options to the top-level flag parser for
@@ -116,8 +125,8 @@ func NewServiceConfig(options *Options) *ServiceConfig {
 	}
 	}
 
 
 	// Configure public registry.
 	// Configure public registry.
-	config.IndexConfigs[INDEXNAME] = &IndexInfo{
-		Name:     INDEXNAME,
+	config.IndexConfigs[IndexName] = &IndexInfo{
+		Name:     IndexName,
 		Mirrors:  config.Mirrors,
 		Mirrors:  config.Mirrors,
 		Secure:   true,
 		Secure:   true,
 		Official: true,
 		Official: true,
@@ -196,8 +205,8 @@ func ValidateMirror(val string) (string, error) {
 // ValidateIndexName validates an index name.
 // ValidateIndexName validates an index name.
 func ValidateIndexName(val string) (string, error) {
 func ValidateIndexName(val string) (string, error) {
 	// 'index.docker.io' => 'docker.io'
 	// 'index.docker.io' => 'docker.io'
-	if val == "index."+INDEXNAME {
-		val = INDEXNAME
+	if val == "index."+IndexName {
+		val = IndexName
 	}
 	}
 	if strings.HasPrefix(val, "-") || strings.HasSuffix(val, "-") {
 	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)
@@ -267,7 +276,7 @@ func (config *ServiceConfig) NewIndexInfo(indexName string) (*IndexInfo, error)
 // index as the AuthConfig key, and uses the (host)name[:port] for private indexes.
 // index as the AuthConfig key, and uses the (host)name[:port] for private indexes.
 func (index *IndexInfo) GetAuthConfigKey() string {
 func (index *IndexInfo) GetAuthConfigKey() string {
 	if index.Official {
 	if index.Official {
-		return INDEXSERVER
+		return IndexServer
 	}
 	}
 	return index.Name
 	return index.Name
 }
 }
@@ -280,7 +289,7 @@ func splitReposName(reposName string) (string, string) {
 		!strings.Contains(nameParts[0], ":") && nameParts[0] != "localhost") {
 		!strings.Contains(nameParts[0], ":") && nameParts[0] != "localhost") {
 		// This is a Docker Index repos (ex: samalba/hipache or ubuntu)
 		// This is a Docker Index repos (ex: samalba/hipache or ubuntu)
 		// 'docker.io'
 		// 'docker.io'
-		indexName = INDEXNAME
+		indexName = IndexName
 		remoteName = reposName
 		remoteName = reposName
 	} else {
 	} else {
 		indexName = nameParts[0]
 		indexName = nameParts[0]

+ 23 - 19
registry/endpoint.go

@@ -111,6 +111,7 @@ func newEndpoint(address string, tlsConfig *tls.Config, metaHeaders http.Header)
 	return endpoint, nil
 	return endpoint, nil
 }
 }
 
 
+// GetEndpoint returns a new endpoint with the specified headers
 func (repoInfo *RepositoryInfo) GetEndpoint(metaHeaders http.Header) (*Endpoint, error) {
 func (repoInfo *RepositoryInfo) GetEndpoint(metaHeaders http.Header) (*Endpoint, error) {
 	return NewEndpoint(repoInfo.Index, metaHeaders)
 	return NewEndpoint(repoInfo.Index, metaHeaders)
 }
 }
@@ -142,7 +143,10 @@ func (e *Endpoint) Path(path string) string {
 	return fmt.Sprintf("%s/v%d/%s", e.URL, e.Version, path)
 	return fmt.Sprintf("%s/v%d/%s", e.URL, e.Version, path)
 }
 }
 
 
-func (e *Endpoint) Ping() (RegistryInfo, error) {
+// Ping pings the remote endpoint with v2 and v1 pings to determine the API
+// version. It returns a PingResult containing the discovered version. The
+// PingResult also indicates whether the registry is standalone or not.
+func (e *Endpoint) Ping() (PingResult, error) {
 	// The ping logic to use is determined by the registry endpoint version.
 	// The ping logic to use is determined by the registry endpoint version.
 	switch e.Version {
 	switch e.Version {
 	case APIVersion1:
 	case APIVersion1:
@@ -167,49 +171,49 @@ func (e *Endpoint) Ping() (RegistryInfo, error) {
 	}
 	}
 
 
 	e.Version = APIVersionUnknown
 	e.Version = APIVersionUnknown
-	return RegistryInfo{}, fmt.Errorf("unable to ping registry endpoint %s\nv2 ping attempt failed with error: %s\n v1 ping attempt failed with error: %s", e, errV2, errV1)
+	return PingResult{}, fmt.Errorf("unable to ping registry endpoint %s\nv2 ping attempt failed with error: %s\n v1 ping attempt failed with error: %s", e, errV2, errV1)
 }
 }
 
 
-func (e *Endpoint) pingV1() (RegistryInfo, error) {
+func (e *Endpoint) pingV1() (PingResult, error) {
 	logrus.Debugf("attempting v1 ping for registry endpoint %s", e)
 	logrus.Debugf("attempting v1 ping for registry endpoint %s", e)
 
 
-	if e.String() == INDEXSERVER {
+	if e.String() == IndexServer {
 		// Skip the check, we know this one is valid
 		// Skip the check, we know this one is valid
 		// (and we never want to fallback to http in case of error)
 		// (and we never want to fallback to http in case of error)
-		return RegistryInfo{Standalone: false}, nil
+		return PingResult{Standalone: false}, nil
 	}
 	}
 
 
 	req, err := http.NewRequest("GET", e.Path("_ping"), nil)
 	req, err := http.NewRequest("GET", e.Path("_ping"), nil)
 	if err != nil {
 	if err != nil {
-		return RegistryInfo{Standalone: false}, err
+		return PingResult{Standalone: false}, err
 	}
 	}
 
 
 	resp, err := e.client.Do(req)
 	resp, err := e.client.Do(req)
 	if err != nil {
 	if err != nil {
-		return RegistryInfo{Standalone: false}, err
+		return PingResult{Standalone: false}, err
 	}
 	}
 
 
 	defer resp.Body.Close()
 	defer resp.Body.Close()
 
 
 	jsonString, err := ioutil.ReadAll(resp.Body)
 	jsonString, err := ioutil.ReadAll(resp.Body)
 	if err != nil {
 	if err != nil {
-		return RegistryInfo{Standalone: false}, fmt.Errorf("error while reading the http response: %s", err)
+		return PingResult{Standalone: false}, fmt.Errorf("error while reading the http response: %s", err)
 	}
 	}
 
 
 	// If the header is absent, we assume true for compatibility with earlier
 	// If the header is absent, we assume true for compatibility with earlier
 	// versions of the registry. default to true
 	// versions of the registry. default to true
-	info := RegistryInfo{
+	info := PingResult{
 		Standalone: true,
 		Standalone: true,
 	}
 	}
 	if err := json.Unmarshal(jsonString, &info); err != nil {
 	if err := json.Unmarshal(jsonString, &info); err != nil {
-		logrus.Debugf("Error unmarshalling the _ping RegistryInfo: %s", err)
+		logrus.Debugf("Error unmarshalling the _ping PingResult: %s", err)
 		// don't stop here. Just assume sane defaults
 		// don't stop here. Just assume sane defaults
 	}
 	}
 	if hdr := resp.Header.Get("X-Docker-Registry-Version"); hdr != "" {
 	if hdr := resp.Header.Get("X-Docker-Registry-Version"); hdr != "" {
 		logrus.Debugf("Registry version header: '%s'", hdr)
 		logrus.Debugf("Registry version header: '%s'", hdr)
 		info.Version = hdr
 		info.Version = hdr
 	}
 	}
-	logrus.Debugf("RegistryInfo.Version: %q", info.Version)
+	logrus.Debugf("PingResult.Version: %q", info.Version)
 
 
 	standalone := resp.Header.Get("X-Docker-Registry-Standalone")
 	standalone := resp.Header.Get("X-Docker-Registry-Standalone")
 	logrus.Debugf("Registry standalone header: '%s'", standalone)
 	logrus.Debugf("Registry standalone header: '%s'", standalone)
@@ -220,21 +224,21 @@ func (e *Endpoint) pingV1() (RegistryInfo, error) {
 		// there is a header set, and it is not "true" or "1", so assume fails
 		// there is a header set, and it is not "true" or "1", so assume fails
 		info.Standalone = false
 		info.Standalone = false
 	}
 	}
-	logrus.Debugf("RegistryInfo.Standalone: %t", info.Standalone)
+	logrus.Debugf("PingResult.Standalone: %t", info.Standalone)
 	return info, nil
 	return info, nil
 }
 }
 
 
-func (e *Endpoint) pingV2() (RegistryInfo, error) {
+func (e *Endpoint) pingV2() (PingResult, error) {
 	logrus.Debugf("attempting v2 ping for registry endpoint %s", e)
 	logrus.Debugf("attempting v2 ping for registry endpoint %s", e)
 
 
 	req, err := http.NewRequest("GET", e.Path(""), nil)
 	req, err := http.NewRequest("GET", e.Path(""), nil)
 	if err != nil {
 	if err != nil {
-		return RegistryInfo{}, err
+		return PingResult{}, err
 	}
 	}
 
 
 	resp, err := e.client.Do(req)
 	resp, err := e.client.Do(req)
 	if err != nil {
 	if err != nil {
-		return RegistryInfo{}, err
+		return PingResult{}, err
 	}
 	}
 	defer resp.Body.Close()
 	defer resp.Body.Close()
 
 
@@ -253,21 +257,21 @@ HeaderLoop:
 	}
 	}
 
 
 	if !supportsV2 {
 	if !supportsV2 {
-		return RegistryInfo{}, fmt.Errorf("%s does not appear to be a v2 registry endpoint", e)
+		return PingResult{}, fmt.Errorf("%s does not appear to be a v2 registry endpoint", e)
 	}
 	}
 
 
 	if resp.StatusCode == http.StatusOK {
 	if resp.StatusCode == http.StatusOK {
 		// It would seem that no authentication/authorization is required.
 		// It would seem that no authentication/authorization is required.
 		// So we don't need to parse/add any authorization schemes.
 		// So we don't need to parse/add any authorization schemes.
-		return RegistryInfo{Standalone: true}, nil
+		return PingResult{Standalone: true}, nil
 	}
 	}
 
 
 	if resp.StatusCode == http.StatusUnauthorized {
 	if resp.StatusCode == http.StatusUnauthorized {
 		// Parse the WWW-Authenticate Header and store the challenges
 		// Parse the WWW-Authenticate Header and store the challenges
 		// on this endpoint object.
 		// on this endpoint object.
 		e.AuthChallenges = parseAuthHeader(resp.Header)
 		e.AuthChallenges = parseAuthHeader(resp.Header)
-		return RegistryInfo{}, nil
+		return PingResult{}, nil
 	}
 	}
 
 
-	return RegistryInfo{}, fmt.Errorf("v2 registry endpoint returned status %d: %q", resp.StatusCode, http.StatusText(resp.StatusCode))
+	return PingResult{}, fmt.Errorf("v2 registry endpoint returned status %d: %q", resp.StatusCode, http.StatusText(resp.StatusCode))
 }
 }

+ 1 - 1
registry/endpoint_test.go

@@ -12,7 +12,7 @@ func TestEndpointParse(t *testing.T) {
 		str      string
 		str      string
 		expected string
 		expected string
 	}{
 	}{
-		{INDEXSERVER, INDEXSERVER},
+		{IndexServer, IndexServer},
 		{"http://0.0.0.0:5000/v1/", "http://0.0.0.0:5000/v1/"},
 		{"http://0.0.0.0:5000/v1/", "http://0.0.0.0:5000/v1/"},
 		{"http://0.0.0.0:5000/v2/", "http://0.0.0.0:5000/v2/"},
 		{"http://0.0.0.0:5000/v2/", "http://0.0.0.0:5000/v2/"},
 		{"http://0.0.0.0:5000", "http://0.0.0.0:5000/v0/"},
 		{"http://0.0.0.0:5000", "http://0.0.0.0:5000/v0/"},

+ 14 - 11
registry/registry.go

@@ -21,19 +21,12 @@ import (
 )
 )
 
 
 var (
 var (
+	// ErrAlreadyExists is an error returned if an image being pushed
+	// already exists on the remote side
 	ErrAlreadyExists = errors.New("Image already exists")
 	ErrAlreadyExists = errors.New("Image already exists")
-	ErrDoesNotExist  = errors.New("Image does not exist")
 	errLoginRequired = errors.New("Authentication is required.")
 	errLoginRequired = errors.New("Authentication is required.")
 )
 )
 
 
-type TimeoutType uint32
-
-const (
-	NoTimeout TimeoutType = iota
-	ReceiveTimeout
-	ConnectTimeout
-)
-
 // dockerUserAgent is the User-Agent the Docker client uses to identify itself.
 // dockerUserAgent is the User-Agent the Docker client uses to identify itself.
 // It is populated on init(), comprising version information of different components.
 // It is populated on init(), comprising version information of different components.
 var dockerUserAgent string
 var dockerUserAgent string
@@ -74,10 +67,12 @@ func DockerHeaders(metaHeaders http.Header) []transport.RequestModifier {
 	return modifiers
 	return modifiers
 }
 }
 
 
+// HTTPClient returns a HTTP client structure which uses the given transport
+// and contains the necessary headers for redirected requests
 func HTTPClient(transport http.RoundTripper) *http.Client {
 func HTTPClient(transport http.RoundTripper) *http.Client {
 	return &http.Client{
 	return &http.Client{
 		Transport:     transport,
 		Transport:     transport,
-		CheckRedirect: AddRequiredHeadersToRedirectedRequests,
+		CheckRedirect: addRequiredHeadersToRedirectedRequests,
 	}
 	}
 }
 }
 
 
@@ -98,7 +93,9 @@ func trustedLocation(req *http.Request) bool {
 	return false
 	return false
 }
 }
 
 
-func AddRequiredHeadersToRedirectedRequests(req *http.Request, via []*http.Request) error {
+// addRequiredHeadersToRedirectedRequests adds the necessary redirection headers
+// for redirected requests
+func addRequiredHeadersToRedirectedRequests(req *http.Request, via []*http.Request) error {
 	if via != nil && via[0] != nil {
 	if via != nil && via[0] != nil {
 		if trustedLocation(req) && trustedLocation(via[0]) {
 		if trustedLocation(req) && trustedLocation(via[0]) {
 			req.Header = via[0].Header
 			req.Header = via[0].Header
@@ -124,6 +121,8 @@ func shouldV2Fallback(err errcode.Error) bool {
 	return false
 	return false
 }
 }
 
 
+// ErrNoSupport is an error type used for errors indicating that an operation
+// is not supported. It encapsulates a more specific error.
 type ErrNoSupport struct{ Err error }
 type ErrNoSupport struct{ Err error }
 
 
 func (e ErrNoSupport) Error() string {
 func (e ErrNoSupport) Error() string {
@@ -133,6 +132,8 @@ func (e ErrNoSupport) Error() string {
 	return e.Err.Error()
 	return e.Err.Error()
 }
 }
 
 
+// ContinueOnError returns true if we should fallback to the next endpoint
+// as a result of this error.
 func ContinueOnError(err error) bool {
 func ContinueOnError(err error) bool {
 	switch v := err.(type) {
 	switch v := err.(type) {
 	case errcode.Errors:
 	case errcode.Errors:
@@ -145,6 +146,8 @@ func ContinueOnError(err error) bool {
 	return false
 	return false
 }
 }
 
 
+// NewTransport returns a new HTTP transport. If tlsConfig is nil, it uses the
+// default TLS configuration.
 func NewTransport(tlsConfig *tls.Config) *http.Transport {
 func NewTransport(tlsConfig *tls.Config) *http.Transport {
 	if tlsConfig == nil {
 	if tlsConfig == nil {
 		var cfg = tlsconfig.ServerDefault
 		var cfg = tlsconfig.ServerDefault

+ 5 - 5
registry/registry_mock_test.go

@@ -145,7 +145,7 @@ func makeURL(req string) string {
 	return testHTTPServer.URL + req
 	return testHTTPServer.URL + req
 }
 }
 
 
-func makeHttpsURL(req string) string {
+func makeHTTPSURL(req string) string {
 	return testHTTPSServer.URL + req
 	return testHTTPSServer.URL + req
 }
 }
 
 
@@ -156,16 +156,16 @@ func makeIndex(req string) *IndexInfo {
 	return index
 	return index
 }
 }
 
 
-func makeHttpsIndex(req string) *IndexInfo {
+func makeHTTPSIndex(req string) *IndexInfo {
 	index := &IndexInfo{
 	index := &IndexInfo{
-		Name: makeHttpsURL(req),
+		Name: makeHTTPSURL(req),
 	}
 	}
 	return index
 	return index
 }
 }
 
 
 func makePublicIndex() *IndexInfo {
 func makePublicIndex() *IndexInfo {
 	index := &IndexInfo{
 	index := &IndexInfo{
-		Name:     INDEXSERVER,
+		Name:     IndexServer,
 		Secure:   true,
 		Secure:   true,
 		Official: true,
 		Official: true,
 	}
 	}
@@ -468,7 +468,7 @@ func TestPing(t *testing.T) {
  * WARNING: Don't push on the repos uncommented, it'll block the tests
  * WARNING: Don't push on the repos uncommented, it'll block the tests
  *
  *
 func TestWait(t *testing.T) {
 func TestWait(t *testing.T) {
-	logrus.Println("Test HTTP server ready and waiting:", testHttpServer.URL)
+	logrus.Println("Test HTTP server ready and waiting:", testHTTPServer.URL)
 	c := make(chan int)
 	c := make(chan int)
 	<-c
 	<-c
 }
 }

+ 30 - 30
registry/registry_test.go

@@ -63,7 +63,7 @@ func TestPingRegistryEndpoint(t *testing.T) {
 	}
 	}
 
 
 	testPing(makeIndex("/v1/"), true, "Expected standalone to be true (default)")
 	testPing(makeIndex("/v1/"), true, "Expected standalone to be true (default)")
-	testPing(makeHttpsIndex("/v1/"), true, "Expected standalone to be true (default)")
+	testPing(makeHTTPSIndex("/v1/"), true, "Expected standalone to be true (default)")
 	testPing(makePublicIndex(), false, "Expected standalone to be false for public index")
 	testPing(makePublicIndex(), false, "Expected standalone to be false for public index")
 }
 }
 
 
@@ -119,7 +119,7 @@ func TestEndpoint(t *testing.T) {
 	}
 	}
 	assertInsecureIndex(index)
 	assertInsecureIndex(index)
 
 
-	index.Name = makeHttpsURL("/v1/")
+	index.Name = makeHTTPSURL("/v1/")
 	endpoint = expandEndpoint(index)
 	endpoint = expandEndpoint(index)
 	assertEqual(t, endpoint.String(), index.Name, "Expected endpoint to be "+index.Name)
 	assertEqual(t, endpoint.String(), index.Name, "Expected endpoint to be "+index.Name)
 	if endpoint.Version != APIVersion1 {
 	if endpoint.Version != APIVersion1 {
@@ -127,7 +127,7 @@ func TestEndpoint(t *testing.T) {
 	}
 	}
 	assertSecureIndex(index)
 	assertSecureIndex(index)
 
 
-	index.Name = makeHttpsURL("")
+	index.Name = makeHTTPSURL("")
 	endpoint = expandEndpoint(index)
 	endpoint = expandEndpoint(index)
 	assertEqual(t, endpoint.String(), index.Name+"/v1/", index.Name+": Expected endpoint to be "+index.Name+"/v1/")
 	assertEqual(t, endpoint.String(), index.Name+"/v1/", index.Name+": Expected endpoint to be "+index.Name+"/v1/")
 	if endpoint.Version != APIVersion1 {
 	if endpoint.Version != APIVersion1 {
@@ -135,7 +135,7 @@ func TestEndpoint(t *testing.T) {
 	}
 	}
 	assertSecureIndex(index)
 	assertSecureIndex(index)
 
 
-	httpsURL := makeHttpsURL("")
+	httpsURL := makeHTTPSURL("")
 	index.Name = strings.SplitN(httpsURL, "://", 2)[1]
 	index.Name = strings.SplitN(httpsURL, "://", 2)[1]
 	endpoint = expandEndpoint(index)
 	endpoint = expandEndpoint(index)
 	assertEqual(t, endpoint.String(), httpsURL+"/v1/", index.Name+": Expected endpoint to be "+httpsURL+"/v1/")
 	assertEqual(t, endpoint.String(), httpsURL+"/v1/", index.Name+": Expected endpoint to be "+httpsURL+"/v1/")
@@ -332,7 +332,7 @@ func TestParseRepositoryInfo(t *testing.T) {
 	expectedRepoInfos := map[string]RepositoryInfo{
 	expectedRepoInfos := map[string]RepositoryInfo{
 		"fooo/bar": {
 		"fooo/bar": {
 			Index: &IndexInfo{
 			Index: &IndexInfo{
-				Name:     INDEXNAME,
+				Name:     IndexName,
 				Official: true,
 				Official: true,
 			},
 			},
 			RemoteName:    "fooo/bar",
 			RemoteName:    "fooo/bar",
@@ -342,7 +342,7 @@ func TestParseRepositoryInfo(t *testing.T) {
 		},
 		},
 		"library/ubuntu": {
 		"library/ubuntu": {
 			Index: &IndexInfo{
 			Index: &IndexInfo{
-				Name:     INDEXNAME,
+				Name:     IndexName,
 				Official: true,
 				Official: true,
 			},
 			},
 			RemoteName:    "library/ubuntu",
 			RemoteName:    "library/ubuntu",
@@ -352,7 +352,7 @@ func TestParseRepositoryInfo(t *testing.T) {
 		},
 		},
 		"nonlibrary/ubuntu": {
 		"nonlibrary/ubuntu": {
 			Index: &IndexInfo{
 			Index: &IndexInfo{
-				Name:     INDEXNAME,
+				Name:     IndexName,
 				Official: true,
 				Official: true,
 			},
 			},
 			RemoteName:    "nonlibrary/ubuntu",
 			RemoteName:    "nonlibrary/ubuntu",
@@ -362,7 +362,7 @@ func TestParseRepositoryInfo(t *testing.T) {
 		},
 		},
 		"ubuntu": {
 		"ubuntu": {
 			Index: &IndexInfo{
 			Index: &IndexInfo{
-				Name:     INDEXNAME,
+				Name:     IndexName,
 				Official: true,
 				Official: true,
 			},
 			},
 			RemoteName:    "library/ubuntu",
 			RemoteName:    "library/ubuntu",
@@ -372,7 +372,7 @@ func TestParseRepositoryInfo(t *testing.T) {
 		},
 		},
 		"other/library": {
 		"other/library": {
 			Index: &IndexInfo{
 			Index: &IndexInfo{
-				Name:     INDEXNAME,
+				Name:     IndexName,
 				Official: true,
 				Official: true,
 			},
 			},
 			RemoteName:    "other/library",
 			RemoteName:    "other/library",
@@ -480,9 +480,9 @@ func TestParseRepositoryInfo(t *testing.T) {
 			CanonicalName: "localhost/privatebase",
 			CanonicalName: "localhost/privatebase",
 			Official:      false,
 			Official:      false,
 		},
 		},
-		INDEXNAME + "/public/moonbase": {
+		IndexName + "/public/moonbase": {
 			Index: &IndexInfo{
 			Index: &IndexInfo{
-				Name:     INDEXNAME,
+				Name:     IndexName,
 				Official: true,
 				Official: true,
 			},
 			},
 			RemoteName:    "public/moonbase",
 			RemoteName:    "public/moonbase",
@@ -490,9 +490,9 @@ func TestParseRepositoryInfo(t *testing.T) {
 			CanonicalName: "docker.io/public/moonbase",
 			CanonicalName: "docker.io/public/moonbase",
 			Official:      false,
 			Official:      false,
 		},
 		},
-		"index." + INDEXNAME + "/public/moonbase": {
+		"index." + IndexName + "/public/moonbase": {
 			Index: &IndexInfo{
 			Index: &IndexInfo{
-				Name:     INDEXNAME,
+				Name:     IndexName,
 				Official: true,
 				Official: true,
 			},
 			},
 			RemoteName:    "public/moonbase",
 			RemoteName:    "public/moonbase",
@@ -502,7 +502,7 @@ func TestParseRepositoryInfo(t *testing.T) {
 		},
 		},
 		"ubuntu-12.04-base": {
 		"ubuntu-12.04-base": {
 			Index: &IndexInfo{
 			Index: &IndexInfo{
-				Name:     INDEXNAME,
+				Name:     IndexName,
 				Official: true,
 				Official: true,
 			},
 			},
 			RemoteName:    "library/ubuntu-12.04-base",
 			RemoteName:    "library/ubuntu-12.04-base",
@@ -510,9 +510,9 @@ func TestParseRepositoryInfo(t *testing.T) {
 			CanonicalName: "docker.io/library/ubuntu-12.04-base",
 			CanonicalName: "docker.io/library/ubuntu-12.04-base",
 			Official:      true,
 			Official:      true,
 		},
 		},
-		INDEXNAME + "/ubuntu-12.04-base": {
+		IndexName + "/ubuntu-12.04-base": {
 			Index: &IndexInfo{
 			Index: &IndexInfo{
-				Name:     INDEXNAME,
+				Name:     IndexName,
 				Official: true,
 				Official: true,
 			},
 			},
 			RemoteName:    "library/ubuntu-12.04-base",
 			RemoteName:    "library/ubuntu-12.04-base",
@@ -520,9 +520,9 @@ func TestParseRepositoryInfo(t *testing.T) {
 			CanonicalName: "docker.io/library/ubuntu-12.04-base",
 			CanonicalName: "docker.io/library/ubuntu-12.04-base",
 			Official:      true,
 			Official:      true,
 		},
 		},
-		"index." + INDEXNAME + "/ubuntu-12.04-base": {
+		"index." + IndexName + "/ubuntu-12.04-base": {
 			Index: &IndexInfo{
 			Index: &IndexInfo{
-				Name:     INDEXNAME,
+				Name:     IndexName,
 				Official: true,
 				Official: true,
 			},
 			},
 			RemoteName:    "library/ubuntu-12.04-base",
 			RemoteName:    "library/ubuntu-12.04-base",
@@ -563,16 +563,16 @@ func TestNewIndexInfo(t *testing.T) {
 	}
 	}
 
 
 	config := NewServiceConfig(nil)
 	config := NewServiceConfig(nil)
-	noMirrors := make([]string, 0)
+	noMirrors := []string{}
 	expectedIndexInfos := map[string]*IndexInfo{
 	expectedIndexInfos := map[string]*IndexInfo{
-		INDEXNAME: {
-			Name:     INDEXNAME,
+		IndexName: {
+			Name:     IndexName,
 			Official: true,
 			Official: true,
 			Secure:   true,
 			Secure:   true,
 			Mirrors:  noMirrors,
 			Mirrors:  noMirrors,
 		},
 		},
-		"index." + INDEXNAME: {
-			Name:     INDEXNAME,
+		"index." + IndexName: {
+			Name:     IndexName,
 			Official: true,
 			Official: true,
 			Secure:   true,
 			Secure:   true,
 			Mirrors:  noMirrors,
 			Mirrors:  noMirrors,
@@ -596,14 +596,14 @@ func TestNewIndexInfo(t *testing.T) {
 	config = makeServiceConfig(publicMirrors, []string{"example.com"})
 	config = makeServiceConfig(publicMirrors, []string{"example.com"})
 
 
 	expectedIndexInfos = map[string]*IndexInfo{
 	expectedIndexInfos = map[string]*IndexInfo{
-		INDEXNAME: {
-			Name:     INDEXNAME,
+		IndexName: {
+			Name:     IndexName,
 			Official: true,
 			Official: true,
 			Secure:   true,
 			Secure:   true,
 			Mirrors:  publicMirrors,
 			Mirrors:  publicMirrors,
 		},
 		},
-		"index." + INDEXNAME: {
-			Name:     INDEXNAME,
+		"index." + IndexName: {
+			Name:     IndexName,
 			Official: true,
 			Official: true,
 			Secure:   true,
 			Secure:   true,
 			Mirrors:  publicMirrors,
 			Mirrors:  publicMirrors,
@@ -814,7 +814,7 @@ func TestAddRequiredHeadersToRedirectedRequests(t *testing.T) {
 		reqFrom.Header.Add("Authorization", "super_secret")
 		reqFrom.Header.Add("Authorization", "super_secret")
 		reqTo, _ := http.NewRequest("GET", urls[1], nil)
 		reqTo, _ := http.NewRequest("GET", urls[1], nil)
 
 
-		AddRequiredHeadersToRedirectedRequests(reqTo, []*http.Request{reqFrom})
+		addRequiredHeadersToRedirectedRequests(reqTo, []*http.Request{reqFrom})
 
 
 		if len(reqTo.Header) != 1 {
 		if len(reqTo.Header) != 1 {
 			t.Fatalf("Expected 1 headers, got %d", len(reqTo.Header))
 			t.Fatalf("Expected 1 headers, got %d", len(reqTo.Header))
@@ -838,7 +838,7 @@ func TestAddRequiredHeadersToRedirectedRequests(t *testing.T) {
 		reqFrom.Header.Add("Authorization", "super_secret")
 		reqFrom.Header.Add("Authorization", "super_secret")
 		reqTo, _ := http.NewRequest("GET", urls[1], nil)
 		reqTo, _ := http.NewRequest("GET", urls[1], nil)
 
 
-		AddRequiredHeadersToRedirectedRequests(reqTo, []*http.Request{reqFrom})
+		addRequiredHeadersToRedirectedRequests(reqTo, []*http.Request{reqFrom})
 
 
 		if len(reqTo.Header) != 2 {
 		if len(reqTo.Header) != 2 {
 			t.Fatalf("Expected 2 headers, got %d", len(reqTo.Header))
 			t.Fatalf("Expected 2 headers, got %d", len(reqTo.Header))
@@ -860,7 +860,7 @@ func TestIsSecureIndex(t *testing.T) {
 		insecureRegistries []string
 		insecureRegistries []string
 		expected           bool
 		expected           bool
 	}{
 	}{
-		{INDEXNAME, nil, true},
+		{IndexName, nil, true},
 		{"example.com", []string{}, true},
 		{"example.com", []string{}, true},
 		{"example.com", []string{"example.com"}, false},
 		{"example.com", []string{"example.com"}, false},
 		{"localhost", []string{"localhost:5000"}, false},
 		{"localhost", []string{"localhost:5000"}, false},

+ 22 - 15
registry/service.go

@@ -17,12 +17,14 @@ import (
 	"github.com/docker/docker/pkg/tlsconfig"
 	"github.com/docker/docker/pkg/tlsconfig"
 )
 )
 
 
+// Service is a registry service. It tracks configuration data such as a list
+// of mirrors.
 type Service struct {
 type Service struct {
 	Config *ServiceConfig
 	Config *ServiceConfig
 }
 }
 
 
 // NewService returns a new instance of Service ready to be
 // NewService returns a new instance of Service ready to be
-// installed no an engine.
+// installed into an engine.
 func NewService(options *Options) *Service {
 func NewService(options *Options) *Service {
 	return &Service{
 	return &Service{
 		Config: NewServiceConfig(options),
 		Config: NewServiceConfig(options),
@@ -36,7 +38,7 @@ func (s *Service) Auth(authConfig *cliconfig.AuthConfig) (string, error) {
 	addr := authConfig.ServerAddress
 	addr := authConfig.ServerAddress
 	if addr == "" {
 	if addr == "" {
 		// Use the official registry address if not specified.
 		// Use the official registry address if not specified.
-		addr = INDEXSERVER
+		addr = IndexServer
 	}
 	}
 	index, err := s.ResolveIndex(addr)
 	index, err := s.ResolveIndex(addr)
 	if err != nil {
 	if err != nil {
@@ -81,6 +83,7 @@ func (s *Service) ResolveIndex(name string) (*IndexInfo, error) {
 	return s.Config.NewIndexInfo(name)
 	return s.Config.NewIndexInfo(name)
 }
 }
 
 
+// APIEndpoint represents a remote API endpoint
 type APIEndpoint struct {
 type APIEndpoint struct {
 	Mirror        bool
 	Mirror        bool
 	URL           string
 	URL           string
@@ -92,12 +95,13 @@ type APIEndpoint struct {
 	Versions      []auth.APIVersion
 	Versions      []auth.APIVersion
 }
 }
 
 
+// ToV1Endpoint returns a V1 API endpoint based on the APIEndpoint
 func (e APIEndpoint) ToV1Endpoint(metaHeaders http.Header) (*Endpoint, error) {
 func (e APIEndpoint) ToV1Endpoint(metaHeaders http.Header) (*Endpoint, error) {
 	return newEndpoint(e.URL, e.TLSConfig, metaHeaders)
 	return newEndpoint(e.URL, e.TLSConfig, metaHeaders)
 }
 }
 
 
-func (s *Service) TlsConfig(hostname string) (*tls.Config, error) {
-	// we construct a client tls config from server defaults
+// TLSConfig constructs a client TLS configuration based on server defaults
+func (s *Service) TLSConfig(hostname string) (*tls.Config, error) {
 	// PreferredServerCipherSuites should have no effect
 	// PreferredServerCipherSuites should have no effect
 	tlsConfig := tlsconfig.ServerDefault
 	tlsConfig := tlsconfig.ServerDefault
 
 
@@ -115,7 +119,7 @@ func (s *Service) TlsConfig(hostname string) (*tls.Config, error) {
 			return false
 			return false
 		}
 		}
 
 
-		hostDir := filepath.Join(CERTS_DIR, hostname)
+		hostDir := filepath.Join(CertsDir, hostname)
 		logrus.Debugf("hostDir: %s", hostDir)
 		logrus.Debugf("hostDir: %s", hostDir)
 		fs, err := ioutil.ReadDir(hostDir)
 		fs, err := ioutil.ReadDir(hostDir)
 		if err != nil && !os.IsNotExist(err) {
 		if err != nil && !os.IsNotExist(err) {
@@ -163,20 +167,23 @@ func (s *Service) TlsConfig(hostname string) (*tls.Config, error) {
 }
 }
 
 
 func (s *Service) tlsConfigForMirror(mirror string) (*tls.Config, error) {
 func (s *Service) tlsConfigForMirror(mirror string) (*tls.Config, error) {
-	mirrorUrl, err := url.Parse(mirror)
+	mirrorURL, err := url.Parse(mirror)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
-	return s.TlsConfig(mirrorUrl.Host)
+	return s.TLSConfig(mirrorURL.Host)
 }
 }
 
 
+// LookupEndpoints creates an list of endpoints to try, in order of preference.
+// It gives preference to v2 endpoints over v1, mirrors over the actual
+// registry, and HTTPS over plain HTTP.
 func (s *Service) LookupEndpoints(repoName string) (endpoints []APIEndpoint, err error) {
 func (s *Service) LookupEndpoints(repoName string) (endpoints []APIEndpoint, err error) {
 	var cfg = tlsconfig.ServerDefault
 	var cfg = tlsconfig.ServerDefault
 	tlsConfig := &cfg
 	tlsConfig := &cfg
-	if strings.HasPrefix(repoName, DEFAULT_NAMESPACE+"/") {
+	if strings.HasPrefix(repoName, DefaultNamespace+"/") {
 		// v2 mirrors
 		// v2 mirrors
 		for _, mirror := range s.Config.Mirrors {
 		for _, mirror := range s.Config.Mirrors {
-			mirrorTlsConfig, err := s.tlsConfigForMirror(mirror)
+			mirrorTLSConfig, err := s.tlsConfigForMirror(mirror)
 			if err != nil {
 			if err != nil {
 				return nil, err
 				return nil, err
 			}
 			}
@@ -186,12 +193,12 @@ func (s *Service) LookupEndpoints(repoName string) (endpoints []APIEndpoint, err
 				Version:      APIVersion2,
 				Version:      APIVersion2,
 				Mirror:       true,
 				Mirror:       true,
 				TrimHostname: true,
 				TrimHostname: true,
-				TLSConfig:    mirrorTlsConfig,
+				TLSConfig:    mirrorTLSConfig,
 			})
 			})
 		}
 		}
 		// v2 registry
 		// v2 registry
 		endpoints = append(endpoints, APIEndpoint{
 		endpoints = append(endpoints, APIEndpoint{
-			URL:          DEFAULT_V2_REGISTRY,
+			URL:          DefaultV2Registry,
 			Version:      APIVersion2,
 			Version:      APIVersion2,
 			Official:     true,
 			Official:     true,
 			TrimHostname: true,
 			TrimHostname: true,
@@ -199,7 +206,7 @@ func (s *Service) LookupEndpoints(repoName string) (endpoints []APIEndpoint, err
 		})
 		})
 		// v1 registry
 		// v1 registry
 		endpoints = append(endpoints, APIEndpoint{
 		endpoints = append(endpoints, APIEndpoint{
-			URL:          DEFAULT_V1_REGISTRY,
+			URL:          DefaultV1Registry,
 			Version:      APIVersion1,
 			Version:      APIVersion1,
 			Official:     true,
 			Official:     true,
 			TrimHostname: true,
 			TrimHostname: true,
@@ -214,7 +221,7 @@ func (s *Service) LookupEndpoints(repoName string) (endpoints []APIEndpoint, err
 	}
 	}
 	hostname := repoName[:slashIndex]
 	hostname := repoName[:slashIndex]
 
 
-	tlsConfig, err = s.TlsConfig(hostname)
+	tlsConfig, err = s.TLSConfig(hostname)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
@@ -232,7 +239,7 @@ func (s *Service) LookupEndpoints(repoName string) (endpoints []APIEndpoint, err
 			Version:       APIVersion2,
 			Version:       APIVersion2,
 			TrimHostname:  true,
 			TrimHostname:  true,
 			TLSConfig:     tlsConfig,
 			TLSConfig:     tlsConfig,
-			VersionHeader: DEFAULT_REGISTRY_VERSION_HEADER,
+			VersionHeader: DefaultRegistryVersionHeader,
 			Versions:      v2Versions,
 			Versions:      v2Versions,
 		},
 		},
 		{
 		{
@@ -250,7 +257,7 @@ func (s *Service) LookupEndpoints(repoName string) (endpoints []APIEndpoint, err
 			TrimHostname: true,
 			TrimHostname: true,
 			// used to check if supposed to be secure via InsecureSkipVerify
 			// used to check if supposed to be secure via InsecureSkipVerify
 			TLSConfig:     tlsConfig,
 			TLSConfig:     tlsConfig,
-			VersionHeader: DEFAULT_REGISTRY_VERSION_HEADER,
+			VersionHeader: DefaultRegistryVersionHeader,
 			Versions:      v2Versions,
 			Versions:      v2Versions,
 		}, APIEndpoint{
 		}, APIEndpoint{
 			URL:          "http://" + hostname,
 			URL:          "http://" + hostname,

+ 35 - 16
registry/session.go

@@ -28,9 +28,12 @@ import (
 )
 )
 
 
 var (
 var (
+	// ErrRepoNotFound is returned if the repository didn't exist on the
+	// remote side
 	ErrRepoNotFound = errors.New("Repository not found")
 	ErrRepoNotFound = errors.New("Repository not found")
 )
 )
 
 
+// A Session is used to communicate with a V1 registry
 type Session struct {
 type Session struct {
 	indexEndpoint *Endpoint
 	indexEndpoint *Endpoint
 	client        *http.Client
 	client        *http.Client
@@ -90,9 +93,11 @@ func cloneRequest(r *http.Request) *http.Request {
 	return r2
 	return r2
 }
 }
 
 
+// RoundTrip changes a HTTP request's headers to add the necessary
+// authentication-related headers
 func (tr *authTransport) RoundTrip(orig *http.Request) (*http.Response, error) {
 func (tr *authTransport) RoundTrip(orig *http.Request) (*http.Response, error) {
 	// Authorization should not be set on 302 redirect for untrusted locations.
 	// Authorization should not be set on 302 redirect for untrusted locations.
-	// This logic mirrors the behavior in AddRequiredHeadersToRedirectedRequests.
+	// This logic mirrors the behavior in addRequiredHeadersToRedirectedRequests.
 	// As the authorization logic is currently implemented in RoundTrip,
 	// As the authorization logic is currently implemented in RoundTrip,
 	// a 302 redirect is detected by looking at the Referer header as go http package adds said header.
 	// a 302 redirect is detected by looking at the Referer header as go http package adds said header.
 	// This is safe as Docker doesn't set Referer in other scenarios.
 	// This is safe as Docker doesn't set Referer in other scenarios.
@@ -154,6 +159,7 @@ func (tr *authTransport) CancelRequest(req *http.Request) {
 	}
 	}
 }
 }
 
 
+// NewSession creates a new session
 // TODO(tiborvass): remove authConfig param once registry client v2 is vendored
 // TODO(tiborvass): remove authConfig param once registry client v2 is vendored
 func NewSession(client *http.Client, authConfig *cliconfig.AuthConfig, endpoint *Endpoint) (r *Session, err error) {
 func NewSession(client *http.Client, authConfig *cliconfig.AuthConfig, endpoint *Endpoint) (r *Session, err error) {
 	r = &Session{
 	r = &Session{
@@ -167,7 +173,7 @@ func NewSession(client *http.Client, authConfig *cliconfig.AuthConfig, endpoint
 
 
 	// If we're working with a standalone private registry over HTTPS, send Basic Auth headers
 	// If we're working with a standalone private registry over HTTPS, send Basic Auth headers
 	// alongside all our requests.
 	// alongside all our requests.
-	if endpoint.VersionString(1) != INDEXSERVER && endpoint.URL.Scheme == "https" {
+	if endpoint.VersionString(1) != IndexServer && endpoint.URL.Scheme == "https" {
 		info, err := endpoint.Ping()
 		info, err := endpoint.Ping()
 		if err != nil {
 		if err != nil {
 			return nil, err
 			return nil, err
@@ -196,8 +202,8 @@ func (r *Session) ID() string {
 	return r.id
 	return r.id
 }
 }
 
 
-// Retrieve the history of a given image from the Registry.
-// Return a list of the parent's json (requested image included)
+// GetRemoteHistory retrieves the history of a given image from the registry.
+// It returns a list of the parent's JSON files (including the requested image).
 func (r *Session) GetRemoteHistory(imgID, registry string) ([]string, error) {
 func (r *Session) GetRemoteHistory(imgID, registry string) ([]string, error) {
 	res, err := r.client.Get(registry + "images/" + imgID + "/ancestry")
 	res, err := r.client.Get(registry + "images/" + imgID + "/ancestry")
 	if err != nil {
 	if err != nil {
@@ -220,7 +226,7 @@ func (r *Session) GetRemoteHistory(imgID, registry string) ([]string, error) {
 	return history, nil
 	return history, nil
 }
 }
 
 
-// Check if an image exists in the Registry
+// LookupRemoteImage checks if an image exists in the registry
 func (r *Session) LookupRemoteImage(imgID, registry string) error {
 func (r *Session) LookupRemoteImage(imgID, registry string) error {
 	res, err := r.client.Get(registry + "images/" + imgID + "/json")
 	res, err := r.client.Get(registry + "images/" + imgID + "/json")
 	if err != nil {
 	if err != nil {
@@ -233,7 +239,7 @@ func (r *Session) LookupRemoteImage(imgID, registry string) error {
 	return nil
 	return nil
 }
 }
 
 
-// Retrieve an image from the Registry.
+// GetRemoteImageJSON retrieves an image's JSON metadata from the registry.
 func (r *Session) GetRemoteImageJSON(imgID, registry string) ([]byte, int, error) {
 func (r *Session) GetRemoteImageJSON(imgID, registry string) ([]byte, int, error) {
 	res, err := r.client.Get(registry + "images/" + imgID + "/json")
 	res, err := r.client.Get(registry + "images/" + imgID + "/json")
 	if err != nil {
 	if err != nil {
@@ -259,6 +265,7 @@ func (r *Session) GetRemoteImageJSON(imgID, registry string) ([]byte, int, error
 	return jsonString, imageSize, nil
 	return jsonString, imageSize, nil
 }
 }
 
 
+// GetRemoteImageLayer retrieves an image layer from the registry
 func (r *Session) GetRemoteImageLayer(imgID, registry string, imgSize int64) (io.ReadCloser, error) {
 func (r *Session) GetRemoteImageLayer(imgID, registry string, imgSize int64) (io.ReadCloser, error) {
 	var (
 	var (
 		retries    = 5
 		retries    = 5
@@ -308,9 +315,13 @@ func (r *Session) GetRemoteImageLayer(imgID, registry string, imgSize int64) (io
 	return res.Body, nil
 	return res.Body, nil
 }
 }
 
 
+// GetRemoteTag retrieves the tag named in the askedTag argument from the given
+// repository. It queries each of the registries supplied in the registries
+// argument, and returns data from the first one that answers the query
+// successfully.
 func (r *Session) GetRemoteTag(registries []string, repository string, askedTag string) (string, error) {
 func (r *Session) GetRemoteTag(registries []string, repository string, askedTag string) (string, error) {
 	if strings.Count(repository, "/") == 0 {
 	if strings.Count(repository, "/") == 0 {
-		// This will be removed once the Registry supports auto-resolution on
+		// This will be removed once the registry supports auto-resolution on
 		// the "library" namespace
 		// the "library" namespace
 		repository = "library/" + repository
 		repository = "library/" + repository
 	}
 	}
@@ -331,18 +342,22 @@ func (r *Session) GetRemoteTag(registries []string, repository string, askedTag
 			continue
 			continue
 		}
 		}
 
 
-		var tagId string
-		if err := json.NewDecoder(res.Body).Decode(&tagId); err != nil {
+		var tagID string
+		if err := json.NewDecoder(res.Body).Decode(&tagID); err != nil {
 			return "", err
 			return "", err
 		}
 		}
-		return tagId, nil
+		return tagID, nil
 	}
 	}
 	return "", fmt.Errorf("Could not reach any registry endpoint")
 	return "", fmt.Errorf("Could not reach any registry endpoint")
 }
 }
 
 
+// GetRemoteTags retrieves all tags from the given repository. It queries each
+// of the registries supplied in the registries argument, and returns data from
+// the first one that answers the query successfully. It returns a map with
+// tag names as the keys and image IDs as the values.
 func (r *Session) GetRemoteTags(registries []string, repository string) (map[string]string, error) {
 func (r *Session) GetRemoteTags(registries []string, repository string) (map[string]string, error) {
 	if strings.Count(repository, "/") == 0 {
 	if strings.Count(repository, "/") == 0 {
-		// This will be removed once the Registry supports auto-resolution on
+		// This will be removed once the registry supports auto-resolution on
 		// the "library" namespace
 		// the "library" namespace
 		repository = "library/" + repository
 		repository = "library/" + repository
 	}
 	}
@@ -379,7 +394,7 @@ func buildEndpointsList(headers []string, indexEp string) ([]string, error) {
 		return nil, err
 		return nil, err
 	}
 	}
 	var urlScheme = parsedURL.Scheme
 	var urlScheme = parsedURL.Scheme
-	// The Registry's URL scheme has to match the Index'
+	// The registry's URL scheme has to match the Index'
 	for _, ep := range headers {
 	for _, ep := range headers {
 		epList := strings.Split(ep, ",")
 		epList := strings.Split(ep, ",")
 		for _, epListElement := range epList {
 		for _, epListElement := range epList {
@@ -391,6 +406,7 @@ func buildEndpointsList(headers []string, indexEp string) ([]string, error) {
 	return endpoints, nil
 	return endpoints, nil
 }
 }
 
 
+// GetRepositoryData returns lists of images and endpoints for the repository
 func (r *Session) GetRepositoryData(remote string) (*RepositoryData, error) {
 func (r *Session) GetRepositoryData(remote string) (*RepositoryData, error) {
 	repositoryTarget := fmt.Sprintf("%srepositories/%s/images", r.indexEndpoint.VersionString(1), remote)
 	repositoryTarget := fmt.Sprintf("%srepositories/%s/images", r.indexEndpoint.VersionString(1), remote)
 
 
@@ -457,8 +473,8 @@ func (r *Session) GetRepositoryData(remote string) (*RepositoryData, error) {
 	}, nil
 	}, nil
 }
 }
 
 
+// PushImageChecksumRegistry uploads checksums for an image
 func (r *Session) PushImageChecksumRegistry(imgData *ImgData, registry string) error {
 func (r *Session) PushImageChecksumRegistry(imgData *ImgData, registry string) error {
-
 	u := registry + "images/" + imgData.ID + "/checksum"
 	u := registry + "images/" + imgData.ID + "/checksum"
 
 
 	logrus.Debugf("[registry] Calling PUT %s", u)
 	logrus.Debugf("[registry] Calling PUT %s", u)
@@ -494,7 +510,7 @@ func (r *Session) PushImageChecksumRegistry(imgData *ImgData, registry string) e
 	return nil
 	return nil
 }
 }
 
 
-// Push a local image to the registry
+// PushImageJSONRegistry pushes JSON metadata for a local image to the registry
 func (r *Session) PushImageJSONRegistry(imgData *ImgData, jsonRaw []byte, registry string) error {
 func (r *Session) PushImageJSONRegistry(imgData *ImgData, jsonRaw []byte, registry string) error {
 
 
 	u := registry + "images/" + imgData.ID + "/json"
 	u := registry + "images/" + imgData.ID + "/json"
@@ -531,8 +547,8 @@ func (r *Session) PushImageJSONRegistry(imgData *ImgData, jsonRaw []byte, regist
 	return nil
 	return nil
 }
 }
 
 
+// PushImageLayerRegistry sends the checksum of an image layer to the registry
 func (r *Session) PushImageLayerRegistry(imgID string, layer io.Reader, registry string, jsonRaw []byte) (checksum string, checksumPayload string, err error) {
 func (r *Session) PushImageLayerRegistry(imgID string, layer io.Reader, registry string, jsonRaw []byte) (checksum string, checksumPayload string, err error) {
-
 	u := registry + "images/" + imgID + "/layer"
 	u := registry + "images/" + imgID + "/layer"
 
 
 	logrus.Debugf("[registry] Calling PUT %s", u)
 	logrus.Debugf("[registry] Calling PUT %s", u)
@@ -576,7 +592,7 @@ func (r *Session) PushImageLayerRegistry(imgID string, layer io.Reader, registry
 	return tarsumLayer.Sum(jsonRaw), checksumPayload, nil
 	return tarsumLayer.Sum(jsonRaw), checksumPayload, nil
 }
 }
 
 
-// push a tag on the registry.
+// PushRegistryTag pushes a tag on the registry.
 // Remote has the format '<user>/<repo>
 // Remote has the format '<user>/<repo>
 func (r *Session) PushRegistryTag(remote, revision, tag, registry string) error {
 func (r *Session) PushRegistryTag(remote, revision, tag, registry string) error {
 	// "jsonify" the string
 	// "jsonify" the string
@@ -600,6 +616,7 @@ func (r *Session) PushRegistryTag(remote, revision, tag, registry string) error
 	return nil
 	return nil
 }
 }
 
 
+// PushImageJSONIndex uploads an image list to the repository
 func (r *Session) PushImageJSONIndex(remote string, imgList []*ImgData, validate bool, regs []string) (*RepositoryData, error) {
 func (r *Session) PushImageJSONIndex(remote string, imgList []*ImgData, validate bool, regs []string) (*RepositoryData, error) {
 	cleanImgList := []*ImgData{}
 	cleanImgList := []*ImgData{}
 	if validate {
 	if validate {
@@ -705,6 +722,7 @@ func shouldRedirect(response *http.Response) bool {
 	return response.StatusCode >= 300 && response.StatusCode < 400
 	return response.StatusCode >= 300 && response.StatusCode < 400
 }
 }
 
 
+// SearchRepositories performs a search against the remote repository
 func (r *Session) SearchRepositories(term string) (*SearchResults, error) {
 func (r *Session) SearchRepositories(term string) (*SearchResults, error) {
 	logrus.Debugf("Index server: %s", r.indexEndpoint)
 	logrus.Debugf("Index server: %s", r.indexEndpoint)
 	u := r.indexEndpoint.VersionString(1) + "search?q=" + url.QueryEscape(term)
 	u := r.indexEndpoint.VersionString(1) + "search?q=" + url.QueryEscape(term)
@@ -727,6 +745,7 @@ func (r *Session) SearchRepositories(term string) (*SearchResults, error) {
 	return result, json.NewDecoder(res.Body).Decode(result)
 	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
 // TODO(tiborvass): remove this once registry client v2 is vendored
 func (r *Session) GetAuthConfig(withPasswd bool) *cliconfig.AuthConfig {
 func (r *Session) GetAuthConfig(withPasswd bool) *cliconfig.AuthConfig {
 	password := ""
 	password := ""

+ 68 - 21
registry/types.go

@@ -1,38 +1,66 @@
 package registry
 package registry
 
 
+// SearchResult describes a search result returned from a registry
 type SearchResult struct {
 type SearchResult struct {
-	StarCount   int    `json:"star_count"`
-	IsOfficial  bool   `json:"is_official"`
-	Name        string `json:"name"`
-	IsTrusted   bool   `json:"is_trusted"`
-	IsAutomated bool   `json:"is_automated"`
+	// StarCount indicates the number of stars this repository has
+	StarCount int `json:"star_count"`
+	// IsOfficial indicates whether the result is an official repository or not
+	IsOfficial bool `json:"is_official"`
+	// Name is the name of the repository
+	Name string `json:"name"`
+	// IsOfficial indicates whether the result is trusted
+	IsTrusted bool `json:"is_trusted"`
+	// IsAutomated indicates whether the result is automated
+	IsAutomated bool `json:"is_automated"`
+	// Description is a textual description of the repository
 	Description string `json:"description"`
 	Description string `json:"description"`
 }
 }
 
 
+// SearchResults lists a collection search results returned from a registry
 type SearchResults struct {
 type SearchResults struct {
-	Query      string         `json:"query"`
-	NumResults int            `json:"num_results"`
-	Results    []SearchResult `json:"results"`
+	// Query contains the query string that generated the search results
+	Query string `json:"query"`
+	// NumResults indicates the number of results the query returned
+	NumResults int `json:"num_results"`
+	// Results is a slice containing the acutal results for the search
+	Results []SearchResult `json:"results"`
 }
 }
 
 
+// RepositoryData tracks the image list, list of endpoints, and list of tokens
+// for a repository
 type RepositoryData struct {
 type RepositoryData struct {
-	ImgList   map[string]*ImgData
+	// ImgList is a list of images in the repository
+	ImgList map[string]*ImgData
+	// Endpoints is a list of endpoints returned in X-Docker-Endpoints
 	Endpoints []string
 	Endpoints []string
-	Tokens    []string
+	// Tokens is currently unused (remove it?)
+	Tokens []string
 }
 }
 
 
+// ImgData is used to transfer image checksums to and from the registry
 type ImgData struct {
 type ImgData struct {
+	// ID is an opaque string that identifies the image
 	ID              string `json:"id"`
 	ID              string `json:"id"`
 	Checksum        string `json:"checksum,omitempty"`
 	Checksum        string `json:"checksum,omitempty"`
 	ChecksumPayload string `json:"-"`
 	ChecksumPayload string `json:"-"`
 	Tag             string `json:",omitempty"`
 	Tag             string `json:",omitempty"`
 }
 }
 
 
-type RegistryInfo struct {
-	Version    string `json:"version"`
-	Standalone bool   `json:"standalone"`
+// PingResult contains the information returned when pinging a registry. It
+// indicates the registry's version and whether the registry claims to be a
+// standalone registry.
+type PingResult struct {
+	// Version is the registry version supplied by the registry in a HTTP
+	// header
+	Version string `json:"version"`
+	// Standalone is set to true if the registry indicates it is a
+	// standalone registry in the X-Docker-Registry-Standalone
+	// header
+	Standalone bool `json:"standalone"`
 }
 }
 
 
+// APIVersion is an integral representation of an API version (presently
+// either 1 or 2)
 type APIVersion int
 type APIVersion int
 
 
 func (av APIVersion) String() string {
 func (av APIVersion) String() string {
@@ -51,6 +79,8 @@ const (
 	APIVersion2
 	APIVersion2
 )
 )
 
 
+// IndexInfo contains information about a registry
+//
 // RepositoryInfo Examples:
 // RepositoryInfo Examples:
 // {
 // {
 //   "Index" : {
 //   "Index" : {
@@ -64,7 +94,7 @@ const (
 //   "CanonicalName" : "docker.io/debian"
 //   "CanonicalName" : "docker.io/debian"
 //   "Official" : true,
 //   "Official" : true,
 // }
 // }
-
+//
 // {
 // {
 //   "Index" : {
 //   "Index" : {
 //     "Name" : "127.0.0.1:5000",
 //     "Name" : "127.0.0.1:5000",
@@ -78,16 +108,33 @@ const (
 //   "Official" : false,
 //   "Official" : false,
 // }
 // }
 type IndexInfo struct {
 type IndexInfo struct {
-	Name     string
-	Mirrors  []string
-	Secure   bool
+	// Name is the name of the registry, such as "docker.io"
+	Name string
+	// Mirrors is a list of mirrors, expressed as URIs
+	Mirrors []string
+	// Secure is set to false if the registry is part of the list of
+	// insecure registries. Insecure registries accept HTTP and/or accept
+	// HTTPS with certificates from unknown CAs.
+	Secure bool
+	// Official indicates whether this is an official registry
 	Official bool
 	Official bool
 }
 }
 
 
+// RepositoryInfo describes a repository
 type RepositoryInfo struct {
 type RepositoryInfo struct {
-	Index         *IndexInfo
-	RemoteName    string
-	LocalName     string
+	// Index points to registry information
+	Index *IndexInfo
+	// RemoteName is the remote name of the repository, such as
+	// "library/ubuntu-12.04-base"
+	RemoteName string
+	// LocalName is the local name of the repository, such as
+	// "ubuntu-12.04-base"
+	LocalName string
+	// CanonicalName is the canonical name of the repository, such as
+	// "docker.io/library/ubuntu-12.04-base"
 	CanonicalName string
 	CanonicalName string
-	Official      bool
+	// Official indicates whether the repository is considered official.
+	// If the registry is official, and the normalized name does not
+	// contain a '/' (e.g. "foo"), then it is considered an official repo.
+	Official bool
 }
 }