From 4dc81927d3fa8176c4a468f3aac4e23b84917fbc Mon Sep 17 00:00:00 2001
From: Wenkai Yin <yinw@vmware.com>
Date: Sun, 17 Apr 2016 22:39:10 +0800
Subject: [PATCH] remove useless code

---
 api/repository.go               |  34 ++++++----
 service/utils/cache.go          |  11 +--
 utils/registry/registry.go      |  66 ++++++++++++++++--
 utils/registry/registryutils.go | 115 --------------------------------
 4 files changed, 86 insertions(+), 140 deletions(-)
 delete mode 100644 utils/registry/registryutils.go

diff --git a/api/repository.go b/api/repository.go
index 40d8f6bb5..307ff60fe 100644
--- a/api/repository.go
+++ b/api/repository.go
@@ -225,15 +225,19 @@ func (ra *RepositoryAPI) GetTags() {
 	var tags []string
 
 	repoName := ra.GetString("repo_name")
-	result, err := registry.APIGet(registry.BuildRegistryURL(repoName, "tags", "list"), ra.username)
+
+	tags, err := ra.registry.ListTag(repoName)
 	if err != nil {
-		log.Errorf("Failed to get repo tags, repo name: %s, error: %v", repoName, err)
-		ra.RenderError(http.StatusInternalServerError, "Failed to get repo tags")
-	} else {
-		t := tag{}
-		json.Unmarshal(result, &t)
-		tags = t.Tags
+		e, ok := errors.ParseError(err)
+		if ok {
+			log.Info(e)
+			ra.CustomAbort(e.StatusCode, e.Message)
+		} else {
+			log.Error(err)
+			ra.CustomAbort(http.StatusInternalServerError, "internal error")
+		}
 	}
+
 	ra.Data["json"] = tags
 	ra.ServeJSON()
 }
@@ -245,14 +249,20 @@ func (ra *RepositoryAPI) GetManifests() {
 
 	item := models.RepoItem{}
 
-	result, err := registry.APIGet(registry.BuildRegistryURL(repoName, "manifests", tag), ra.username)
+	_, _, payload, err := ra.registry.PullManifest(repoName, tag, registry.ManifestVersion1)
 	if err != nil {
-		log.Errorf("Failed to get manifests for repo, repo name: %s, tag: %s, error: %v", repoName, tag, err)
-		ra.RenderError(http.StatusInternalServerError, "Internal Server Error")
-		return
+		e, ok := errors.ParseError(err)
+		if ok {
+			log.Info(e)
+			ra.CustomAbort(e.StatusCode, e.Message)
+		} else {
+			log.Error(err)
+			ra.CustomAbort(http.StatusInternalServerError, "internal error")
+		}
 	}
+
 	mani := manifest{}
-	err = json.Unmarshal(result, &mani)
+	err = json.Unmarshal(payload, &mani)
 	if err != nil {
 		log.Errorf("Failed to decode json from response for manifests, repo name: %s, tag: %s, error: %v", repoName, tag, err)
 		ra.RenderError(http.StatusInternalServerError, "Internal Server Error")
diff --git a/service/utils/cache.go b/service/utils/cache.go
index 7f4508b0c..a97a4599c 100644
--- a/service/utils/cache.go
+++ b/service/utils/cache.go
@@ -16,11 +16,9 @@
 package utils
 
 import (
-	"encoding/json"
 	"os"
 	"time"
 
-	"github.com/vmware/harbor/models"
 	"github.com/vmware/harbor/utils/log"
 	"github.com/vmware/harbor/utils/registry"
 
@@ -52,19 +50,14 @@ func init() {
 // RefreshCatalogCache calls registry's API to get repository list and write it to cache.
 func RefreshCatalogCache() error {
 	log.Debug("refreshing catalog cache...")
-	result, err := registry.APIGet(registry.BuildRegistryURL("_catalog"), "")
-	if err != nil {
-		return err
-	}
-	repoResp := models.Repo{}
-	err = json.Unmarshal(result, &repoResp)
+	rs, err := registryClient.Catalog()
 	if err != nil {
 		return err
 	}
 
 	repos := []string{}
 
-	for _, repo := range repoResp.Repositories {
+	for _, repo := range rs {
 		tags, err := registryClient.ListTag(repo)
 		if err != nil {
 			log.Errorf("error occurred while list tag for %s: %v", repo, err)
diff --git a/utils/registry/registry.go b/utils/registry/registry.go
index 5fe3283bd..e390c4c0d 100644
--- a/utils/registry/registry.go
+++ b/utils/registry/registry.go
@@ -22,6 +22,8 @@ import (
 	"net/http"
 	"net/url"
 
+	"github.com/docker/distribution/manifest"
+	"github.com/docker/distribution/manifest/schema1"
 	"github.com/docker/distribution/manifest/schema2"
 	"github.com/vmware/harbor/utils/registry/errors"
 )
@@ -37,6 +39,19 @@ type uRLBuilder struct {
 	root *url.URL
 }
 
+var (
+	// ManifestVersion1 : schema 1
+	ManifestVersion1 = manifest.Versioned{
+		SchemaVersion: 1,
+		MediaType:     schema1.MediaTypeManifest,
+	}
+	// ManifestVersion2 : schema 2
+	ManifestVersion2 = manifest.Versioned{
+		SchemaVersion: 2,
+		MediaType:     schema2.MediaTypeManifest,
+	}
+)
+
 // New returns an instance of Registry
 func New(endpoint string, client *http.Client) (*Registry, error) {
 	u, err := url.Parse(endpoint)
@@ -53,6 +68,46 @@ func New(endpoint string, client *http.Client) (*Registry, error) {
 	}, nil
 }
 
+// Catalog ...
+func (r *Registry) Catalog() ([]string, error) {
+	repos := []string{}
+	req, err := http.NewRequest("GET", r.ub.buildCatalogURL(), nil)
+	if err != nil {
+		return repos, err
+	}
+
+	resp, err := r.client.Do(req)
+	if err != nil {
+		return repos, err
+	}
+
+	defer resp.Body.Close()
+
+	b, err := ioutil.ReadAll(resp.Body)
+	if err != nil {
+		return repos, err
+	}
+
+	if resp.StatusCode == http.StatusOK {
+		catalogResp := struct {
+			Repositories []string `json:"repositories"`
+		}{}
+
+		if err := json.Unmarshal(b, &catalogResp); err != nil {
+			return repos, err
+		}
+
+		repos = catalogResp.Repositories
+
+		return repos, nil
+	}
+
+	return repos, errors.Error{
+		StatusCode: resp.StatusCode,
+		Message:    string(b),
+	}
+}
+
 // ListTag ...
 func (r *Registry) ListTag(name string) ([]string, error) {
 	tags := []string{}
@@ -135,15 +190,14 @@ func (r *Registry) ManifestExist(name, reference string) (digest string, exist b
 }
 
 // PullManifest ...
-func (r *Registry) PullManifest(name, reference string) (digest, mediaType string, payload []byte, err error) {
+func (r *Registry) PullManifest(name, reference string, version manifest.Versioned) (digest, mediaType string, payload []byte, err error) {
 	req, err := http.NewRequest("GET", r.ub.buildManifestURL(name, reference), nil)
 	if err != nil {
 		return
 	}
 
-	// request Schema 2 manifest, if the registry does not support it,
-	// Schema 1 manifest will be returned
-	req.Header.Set(http.CanonicalHeaderKey("Accept"), schema2.MediaTypeManifest)
+	// if the registry does not support schema 2, schema 1 manifest will be returned
+	req.Header.Set(http.CanonicalHeaderKey("Accept"), version.MediaType)
 
 	resp, err := r.client.Do(req)
 	if err != nil {
@@ -245,6 +299,10 @@ func (r *Registry) DeleteBlob(name, digest string) error {
 	}
 }
 
+func (u *uRLBuilder) buildCatalogURL() string {
+	return fmt.Sprintf("%s/v2/_catalog", u.root.String())
+}
+
 func (u *uRLBuilder) buildTagListURL(name string) string {
 	return fmt.Sprintf("%s/v2/%s/tags/list", u.root.String(), name)
 }
diff --git a/utils/registry/registryutils.go b/utils/registry/registryutils.go
deleted file mode 100644
index 54a0b6ddf..000000000
--- a/utils/registry/registryutils.go
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
-   Copyright (c) 2016 VMware, Inc. All Rights Reserved.
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-*/
-
-package registry
-
-import (
-	"errors"
-	"fmt"
-	"io/ioutil"
-	"net/http"
-	"os"
-	"regexp"
-
-	token_util "github.com/vmware/harbor/service/token"
-	"github.com/vmware/harbor/utils/log"
-)
-
-// BuildRegistryURL ...
-func BuildRegistryURL(segments ...string) string {
-	registryURL := os.Getenv("REGISTRY_URL")
-	if registryURL == "" {
-		registryURL = "http://localhost:5000"
-	}
-	url := registryURL + "/v2"
-	for _, s := range segments {
-		if s == "v2" {
-			log.Debugf("unnecessary v2 in %v", segments)
-			continue
-		}
-		url += "/" + s
-	}
-	return url
-}
-
-// APIGet triggers GET request to the URL which is the endpoint of registry and returns the response body.
-// It will attach a valid jwt token to the request if registry requires.
-func APIGet(url, username string) ([]byte, error) {
-
-	log.Debugf("Registry API url: %s", url)
-	response, err := http.Get(url)
-	if err != nil {
-		return nil, err
-	}
-	result, err := ioutil.ReadAll(response.Body)
-	if err != nil {
-		return nil, err
-	}
-	defer response.Body.Close()
-	if response.StatusCode == http.StatusOK {
-		return result, nil
-	} else if response.StatusCode == http.StatusUnauthorized {
-		authenticate := response.Header.Get("WWW-Authenticate")
-		log.Debugf("authenticate header: %s", authenticate)
-		var service string
-		var scopes []string
-		//Disregard the case for hanlding multiple scopes for http call initiated from UI, as there's refactor planned.
-		re := regexp.MustCompile(`service=\"(.*?)\".*scope=\"(.*?)\"`)
-		res := re.FindStringSubmatch(authenticate)
-		if len(res) > 2 {
-			service = res[1]
-			scopes = append(scopes, res[2])
-		}
-		token, err := token_util.GenTokenForUI(username, service, scopes)
-		if err != nil {
-			return nil, err
-		}
-		request, err := http.NewRequest("GET", url, nil)
-		if err != nil {
-			return nil, err
-		}
-		request.Header.Add("Authorization", "Bearer "+token)
-		client := &http.Client{}
-		client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
-			//	log.Infof("via length: %d\n", len(via))
-			if len(via) >= 10 {
-				return fmt.Errorf("too many redirects")
-			}
-			for k, v := range via[0].Header {
-				if _, ok := req.Header[k]; !ok {
-					req.Header[k] = v
-				}
-			}
-			return nil
-		}
-		response, err = client.Do(request)
-		if err != nil {
-			return nil, err
-		}
-		if response.StatusCode != http.StatusOK {
-			errMsg := fmt.Sprintf("Unexpected return code from registry: %d", response.StatusCode)
-			log.Error(errMsg)
-			return nil, fmt.Errorf(errMsg)
-		}
-		result, err = ioutil.ReadAll(response.Body)
-		if err != nil {
-			return nil, err
-		}
-		defer response.Body.Close()
-		return result, nil
-	} else {
-		return nil, errors.New(string(result))
-	}
-}