Преглед на файлове

registry: Info collection

roll version and standalone information into the _ping. And to support
Headers they are checked after the JSON is loaded (if there is anything
to load). To stay backwards compatible, if the _ping contents are not
able to unmarshal to RegistryInfo, do not stop, but continue with the
same behavior.

Docker-DCO-1.1-Signed-off-by: Vincent Batts <vbatts@redhat.com> (github: vbatts)
Vincent Batts преди 11 години
родител
ревизия
2b855afaee
променени са 1 файла, в които са добавени 40 реда и са изтрити 38 реда
  1. 40 38
      registry/registry.go

+ 40 - 38
registry/registry.go

@@ -25,8 +25,12 @@ var (
 	errLoginRequired         = errors.New("Authentication is required.")
 )
 
-// reuse this chunk of code
-func newClient() *http.Client {
+func pingRegistryEndpoint(endpoint string) (RegistryInfo, error) {
+	if endpoint == IndexServerAddress() {
+		// Skip the check, we now this one is valid
+		// (and we never want to fallback to http in case of error)
+		return RegistryInfo{Standalone: false}, nil
+	}
 	httpDial := func(proto string, addr string) (net.Conn, error) {
 		// Set the connect timeout to 5 seconds
 		conn, err := net.DialTimeout(proto, addr, time.Duration(5)*time.Second)
@@ -38,51 +42,44 @@ func newClient() *http.Client {
 		return conn, nil
 	}
 	httpTransport := &http.Transport{Dial: httpDial}
-	return &http.Client{Transport: httpTransport}
-}
-
-// Have an API to access the version of the registry
-func getRegistryVersion(endpoint string) (string, error) {
-
-	client := newClient()
-	resp, err := client.Get(endpoint + "_version")
+	client := &http.Client{Transport: httpTransport}
+	resp, err := client.Get(endpoint + "_ping")
 	if err != nil {
-		return "", err
+		return RegistryInfo{Standalone: false}, err
 	}
 	defer resp.Body.Close()
 
-	if hdr := resp.Header.Get("X-Docker-Registry-Version"); hdr != "" {
-		return hdr, nil
+	jsonString, err := ioutil.ReadAll(resp.Body)
+	if err != nil {
+		return RegistryInfo{Standalone: false}, fmt.Errorf("Error while reading the http response: %s", err)
 	}
-	versionBody, err := ioutil.ReadAll(resp.Body)
-	return string(versionBody), err
-}
 
-func pingRegistryEndpoint(endpoint string) (bool, error) {
-	if endpoint == IndexServerAddress() {
-		// Skip the check, we now this one is valid
-		// (and we never want to fallback to http in case of error)
-		return false, nil
+	// If the header is absent, we assume true for compatibility with earlier
+	// versions of the registry. default to true
+	info := RegistryInfo{
+		Standalone: true,
 	}
-	client := newClient()
-	resp, err := client.Get(endpoint + "_ping")
-	if err != nil {
-		return false, err
+	if err := json.Unmarshal(jsonString, &info); err != nil {
+		utils.Debugf("Error unmarshalling the _ping RegistryInfo: %s", err)
+		// don't stop here. Just assume sane defaults
 	}
-	defer resp.Body.Close()
+	if hdr := resp.Header.Get("X-Docker-Registry-Version"); hdr != "" {
+		utils.Debugf("Registry version header: '%s'", hdr)
+		info.Version = hdr
+	}
+	utils.Debugf("RegistryInfo.Version: %q", info.Version)
 
 	standalone := resp.Header.Get("X-Docker-Registry-Standalone")
 	utils.Debugf("Registry standalone header: '%s'", standalone)
-	// If the header is absent, we assume true for compatibility with earlier
-	// versions of the registry
-	if standalone == "" {
-		return true, nil
-		// Accepted values are "true" (case-insensitive) and "1".
-	} else if strings.EqualFold(standalone, "true") || standalone == "1" {
-		return true, nil
-	}
-	// Otherwise, not standalone
-	return false, nil
+	// Accepted values are "true" (case-insensitive) and "1".
+	if strings.EqualFold(standalone, "true") || standalone == "1" {
+		info.Standalone = true
+	} else if len(standalone) > 0 {
+		// there is a header set, and it is not "true" or "1", so assume fails
+		info.Standalone = false
+	}
+	utils.Debugf("RegistryInfo.Standalone: %q", info.Standalone)
+	return info, nil
 }
 
 func validateRepositoryName(repositoryName string) error {
@@ -688,6 +685,11 @@ type ImgData struct {
 	Tag             string `json:",omitempty"`
 }
 
+type RegistryInfo struct {
+	Version    string `json:"version"`
+	Standalone bool   `json:"standalone"`
+}
+
 type Registry struct {
 	client        *http.Client
 	authConfig    *AuthConfig
@@ -716,11 +718,11 @@ func NewRegistry(authConfig *AuthConfig, factory *utils.HTTPRequestFactory, inde
 	// If we're working with a standalone private registry over HTTPS, send Basic Auth headers
 	// alongside our requests.
 	if indexEndpoint != IndexServerAddress() && strings.HasPrefix(indexEndpoint, "https://") {
-		standalone, err := pingRegistryEndpoint(indexEndpoint)
+		info, err := pingRegistryEndpoint(indexEndpoint)
 		if err != nil {
 			return nil, err
 		}
-		if standalone {
+		if info.Standalone {
 			utils.Debugf("Endpoint %s is eligible for private registry registry. Enabling decorator.", indexEndpoint)
 			dec := utils.NewHTTPAuthDecorator(authConfig.Username, authConfig.Password)
 			factory.AddDecorator(dec)