Implement Tags method on ManifestService

This commit is contained in:
Stephen J Day 2014-12-09 11:06:51 -08:00
parent 45c29be442
commit c71089c653
5 changed files with 67 additions and 0 deletions

View file

@ -13,6 +13,16 @@ import (
"github.com/docker/docker-registry/digest" "github.com/docker/docker-registry/digest"
) )
// ErrUnknownRepository is returned if the named repository is not known by
// the registry.
type ErrUnknownRepository struct {
Name string
}
func (err ErrUnknownRepository) Error() string {
return fmt.Sprintf("unknown respository name=%s", err.Name)
}
// ErrUnknownManifest is returned if the manifest is not known by the // ErrUnknownManifest is returned if the manifest is not known by the
// registry. // registry.
type ErrUnknownManifest struct { type ErrUnknownManifest struct {

View file

@ -99,6 +99,20 @@ func TestManifestStorage(t *testing.T) {
if !reflect.DeepEqual(fetchedManifest, sm) { if !reflect.DeepEqual(fetchedManifest, sm) {
t.Fatalf("fetched manifest not equal: %#v != %#v", fetchedManifest, sm) t.Fatalf("fetched manifest not equal: %#v != %#v", fetchedManifest, sm)
} }
// Grabs the tags and check that this tagged manifest is present
tags, err := ms.Tags(name)
if err != nil {
t.Fatalf("unexpected error fetching tags: %v", err)
}
if len(tags) != 1 {
t.Fatalf("unexpected tags returned: %v", tags)
}
if tags[0] != tag {
t.Fatalf("unexpected tag found in tags: %v != %v", tags, []string{tag})
}
} }
type layerKey struct { type layerKey struct {

View file

@ -3,6 +3,7 @@ package storage
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"path"
"github.com/docker/docker-registry/storagedriver" "github.com/docker/docker-registry/storagedriver"
"github.com/docker/libtrust" "github.com/docker/libtrust"
@ -16,6 +17,35 @@ type manifestStore struct {
var _ ManifestService = &manifestStore{} var _ ManifestService = &manifestStore{}
func (ms *manifestStore) Tags(name string) ([]string, error) {
p, err := ms.pathMapper.path(manifestTagsPath{
name: name,
})
if err != nil {
return nil, err
}
var tags []string
entries, err := ms.driver.List(p)
if err != nil {
logrus.Infof("%#v", err)
switch err := err.(type) {
case storagedriver.PathNotFoundError:
return nil, ErrUnknownRepository{Name: name}
default:
return nil, err
}
}
for _, entry := range entries {
_, filename := path.Split(entry)
tags = append(tags, filename)
}
return tags, nil
}
func (ms *manifestStore) Exists(name, tag string) (bool, error) { func (ms *manifestStore) Exists(name, tag string) (bool, error) {
p, err := ms.path(name, tag) p, err := ms.path(name, tag)
if err != nil { if err != nil {

View file

@ -64,6 +64,8 @@ func (pm *pathMapper) path(spec pathSpec) (string, error) {
repoPrefix := append(rootPrefix, "repositories") repoPrefix := append(rootPrefix, "repositories")
switch v := spec.(type) { switch v := spec.(type) {
case manifestTagsPath:
return path.Join(append(repoPrefix, v.name, "manifests")...), nil
case manifestPathSpec: case manifestPathSpec:
// TODO(sday): May need to store manifest by architecture. // TODO(sday): May need to store manifest by architecture.
return path.Join(append(repoPrefix, v.name, "manifests", v.tag)...), nil return path.Join(append(repoPrefix, v.name, "manifests", v.tag)...), nil
@ -109,6 +111,14 @@ type pathSpec interface {
pathSpec() pathSpec()
} }
// manifestTagsPath describes the path elements required to point to the
// directory with all manifest tags under the repository.
type manifestTagsPath struct {
name string
}
func (manifestTagsPath) pathSpec() {}
// manifestPathSpec describes the path elements used to build a manifest path. // manifestPathSpec describes the path elements used to build a manifest path.
// The contents should be a signed manifest json file. // The contents should be a signed manifest json file.
type manifestPathSpec struct { type manifestPathSpec struct {

View file

@ -52,6 +52,9 @@ func (ss *Services) Manifests() ManifestService {
// ManifestService provides operations on image manifests. // ManifestService provides operations on image manifests.
type ManifestService interface { type ManifestService interface {
// Tags lists the tags under the named repository.
Tags(name string) ([]string, error)
// Exists returns true if the layer exists. // Exists returns true if the layer exists.
Exists(name, tag string) (bool, error) Exists(name, tag string) (bool, error)