Browse Source

Only pulling single repository tag on pull for a specific tag. extending TestGetRemoteTags unit test
Splitting out GetRemoteTag from GetRemoteTags. Adding registry.ErrRepoNotFound error

Signed-off-by: Don Kjer <don.kjer@gmail.com>

Don Kjer 10 years ago
parent
commit
b349a74c71
4 changed files with 67 additions and 5 deletions
  1. 11 1
      graph/pull.go
  2. 1 0
      registry/registry_mock_test.go
  3. 18 3
      registry/registry_test.go
  4. 37 1
      registry/session.go

+ 11 - 1
graph/pull.go

@@ -219,8 +219,18 @@ func (s *TagStore) pullRepository(r *registry.Session, out io.Writer, repoInfo *
 	}
 
 	logrus.Debugf("Retrieving the tag list")
-	tagsList, err := r.GetRemoteTags(repoData.Endpoints, repoInfo.RemoteName)
+	tagsList := make(map[string]string)
+	if askedTag == "" {
+		tagsList, err = r.GetRemoteTags(repoData.Endpoints, repoInfo.RemoteName)
+	} else {
+		var tagId string
+		tagId, err = r.GetRemoteTag(repoData.Endpoints, repoInfo.RemoteName, askedTag)
+		tagsList[askedTag] = tagId
+	}
 	if err != nil {
+		if err == registry.ErrRepoNotFound && askedTag != "" {
+			return fmt.Errorf("Tag %s not found in repository %s", askedTag, repoInfo.CanonicalName)
+		}
 		logrus.Errorf("unable to get remote tags: %s", err)
 		return err
 	}

+ 1 - 0
registry/registry_mock_test.go

@@ -81,6 +81,7 @@ var (
 	testRepositories = map[string]map[string]string{
 		"foo42/bar": {
 			"latest": "42d718c941f5c532ac049bf0b0ab53f0062f09a03afd4aa4a02c098e46032b9d",
+			"test":   "42d718c941f5c532ac049bf0b0ab53f0062f09a03afd4aa4a02c098e46032b9d",
 		},
 	}
 	mockHosts = map[string][]net.IP{

+ 18 - 3
registry/registry_test.go

@@ -211,18 +211,33 @@ func TestGetRemoteImageLayer(t *testing.T) {
 	}
 }
 
+func TestGetRemoteTag(t *testing.T) {
+	r := spawnTestRegistrySession(t)
+	tag, err := r.GetRemoteTag([]string{makeURL("/v1/")}, REPO, "test")
+	if err != nil {
+		t.Fatal(err)
+	}
+	assertEqual(t, tag, imageID, "Expected tag test to map to "+imageID)
+
+	_, err = r.GetRemoteTag([]string{makeURL("/v1/")}, "foo42/baz", "foo")
+	if err != ErrRepoNotFound {
+		t.Fatal("Expected ErrRepoNotFound error when fetching tag for bogus repo")
+	}
+}
+
 func TestGetRemoteTags(t *testing.T) {
 	r := spawnTestRegistrySession(t)
 	tags, err := r.GetRemoteTags([]string{makeURL("/v1/")}, REPO)
 	if err != nil {
 		t.Fatal(err)
 	}
-	assertEqual(t, len(tags), 1, "Expected one tag")
+	assertEqual(t, len(tags), 2, "Expected two tags")
 	assertEqual(t, tags["latest"], imageID, "Expected tag latest to map to "+imageID)
+	assertEqual(t, tags["test"], imageID, "Expected tag test to map to "+imageID)
 
 	_, err = r.GetRemoteTags([]string{makeURL("/v1/")}, "foo42/baz")
-	if err == nil {
-		t.Fatal("Expected error when fetching tags for bogus repo")
+	if err != ErrRepoNotFound {
+		t.Fatal("Expected ErrRepoNotFound error when fetching tags for bogus repo")
 	}
 }
 

+ 37 - 1
registry/session.go

@@ -26,6 +26,10 @@ import (
 	"github.com/docker/docker/pkg/transport"
 )
 
+var (
+	ErrRepoNotFound = errors.New("Repository not found")
+)
+
 type Session struct {
 	indexEndpoint *Endpoint
 	client        *http.Client
@@ -279,6 +283,38 @@ func (r *Session) GetRemoteImageLayer(imgID, registry string, imgSize int64) (io
 	return res.Body, nil
 }
 
+func (r *Session) GetRemoteTag(registries []string, repository string, askedTag string) (string, error) {
+	if strings.Count(repository, "/") == 0 {
+		// This will be removed once the Registry supports auto-resolution on
+		// the "library" namespace
+		repository = "library/" + repository
+	}
+	for _, host := range registries {
+		endpoint := fmt.Sprintf("%srepositories/%s/tags/%s", host, repository, askedTag)
+		res, err := r.client.Get(endpoint)
+		if err != nil {
+			return "", err
+		}
+
+		logrus.Debugf("Got status code %d from %s", res.StatusCode, endpoint)
+		defer res.Body.Close()
+
+		if res.StatusCode == 404 {
+			return "", ErrRepoNotFound
+		}
+		if res.StatusCode != 200 {
+			continue
+		}
+
+		var tagId string
+		if err := json.NewDecoder(res.Body).Decode(&tagId); err != nil {
+			return "", err
+		}
+		return tagId, nil
+	}
+	return "", fmt.Errorf("Could not reach any registry endpoint")
+}
+
 func (r *Session) GetRemoteTags(registries []string, repository string) (map[string]string, error) {
 	if strings.Count(repository, "/") == 0 {
 		// This will be removed once the Registry supports auto-resolution on
@@ -296,7 +332,7 @@ func (r *Session) GetRemoteTags(registries []string, repository string) (map[str
 		defer res.Body.Close()
 
 		if res.StatusCode == 404 {
-			return nil, fmt.Errorf("Repository not found")
+			return nil, ErrRepoNotFound
 		}
 		if res.StatusCode != 200 {
 			continue