diff options
Diffstat (limited to 'reference')
-rw-r--r-- | reference/reference.go | 194 | ||||
-rw-r--r-- | reference/reference_test.go | 275 | ||||
-rw-r--r-- | reference/store.go | 117 | ||||
-rw-r--r-- | reference/store_test.go | 31 |
4 files changed, 87 insertions, 530 deletions
diff --git a/reference/reference.go b/reference/reference.go deleted file mode 100644 index e6e070cb8c..0000000000 --- a/reference/reference.go +++ /dev/null @@ -1,194 +0,0 @@ -package reference - -import ( - "fmt" - - distreference "github.com/docker/distribution/reference" - "github.com/docker/docker/pkg/stringid" - "github.com/opencontainers/go-digest" - "github.com/pkg/errors" -) - -const ( - // DefaultTag defines the default tag used when performing images related actions and no tag or digest is specified - DefaultTag = "latest" - // DefaultHostname is the default built-in hostname - DefaultHostname = "docker.io" - // LegacyDefaultHostname is automatically converted to DefaultHostname - LegacyDefaultHostname = "index.docker.io" - // DefaultRepoPrefix is the prefix used for default repositories in default host - DefaultRepoPrefix = "library/" -) - -// Named is an object with a full name -type Named interface { - // Name returns normalized repository name, like "ubuntu". - Name() string - // String returns full reference, like "ubuntu@sha256:abcdef..." - String() string - // FullName returns full repository name with hostname, like "docker.io/library/ubuntu" - FullName() string - // Hostname returns hostname for the reference, like "docker.io" - Hostname() string - // RemoteName returns the repository component of the full name, like "library/ubuntu" - RemoteName() string -} - -// NamedTagged is an object including a name and tag. -type NamedTagged interface { - Named - Tag() string -} - -// Canonical reference is an object with a fully unique -// name including a name with hostname and digest -type Canonical interface { - Named - Digest() digest.Digest -} - -// ParseNamed parses s and returns a syntactically valid reference implementing -// the Named interface. The reference must have a name, otherwise an error is -// returned. -// If an error was encountered it is returned, along with a nil Reference. -func ParseNamed(s string) (Named, error) { - named, err := distreference.ParseNormalizedNamed(s) - if err != nil { - return nil, errors.Wrapf(err, "failed to parse reference %q", s) - } - if err := validateName(distreference.FamiliarName(named)); err != nil { - return nil, err - } - - // Ensure returned reference cannot have tag and digest - if canonical, isCanonical := named.(distreference.Canonical); isCanonical { - r, err := distreference.WithDigest(distreference.TrimNamed(named), canonical.Digest()) - if err != nil { - return nil, err - } - return &canonicalRef{namedRef{r}}, nil - } - if tagged, isTagged := named.(distreference.NamedTagged); isTagged { - r, err := distreference.WithTag(distreference.TrimNamed(named), tagged.Tag()) - if err != nil { - return nil, err - } - return &taggedRef{namedRef{r}}, nil - } - - return &namedRef{named}, nil -} - -// TrimNamed removes any tag or digest from the named reference -func TrimNamed(ref Named) Named { - return &namedRef{distreference.TrimNamed(ref)} -} - -// WithName returns a named object representing the given string. If the input -// is invalid ErrReferenceInvalidFormat will be returned. -func WithName(name string) (Named, error) { - r, err := distreference.ParseNormalizedNamed(name) - if err != nil { - return nil, err - } - if err := validateName(distreference.FamiliarName(r)); err != nil { - return nil, err - } - if !distreference.IsNameOnly(r) { - return nil, distreference.ErrReferenceInvalidFormat - } - return &namedRef{r}, nil -} - -// WithTag combines the name from "name" and the tag from "tag" to form a -// reference incorporating both the name and the tag. -func WithTag(name Named, tag string) (NamedTagged, error) { - r, err := distreference.WithTag(name, tag) - if err != nil { - return nil, err - } - return &taggedRef{namedRef{r}}, nil -} - -// WithDigest combines the name from "name" and the digest from "digest" to form -// a reference incorporating both the name and the digest. -func WithDigest(name Named, digest digest.Digest) (Canonical, error) { - r, err := distreference.WithDigest(name, digest) - if err != nil { - return nil, err - } - return &canonicalRef{namedRef{r}}, nil -} - -type namedRef struct { - distreference.Named -} -type taggedRef struct { - namedRef -} -type canonicalRef struct { - namedRef -} - -func (r *namedRef) Name() string { - return distreference.FamiliarName(r.Named) -} - -func (r *namedRef) String() string { - return distreference.FamiliarString(r.Named) -} - -func (r *namedRef) FullName() string { - return r.Named.Name() -} -func (r *namedRef) Hostname() string { - return distreference.Domain(r.Named) -} -func (r *namedRef) RemoteName() string { - return distreference.Path(r.Named) -} -func (r *taggedRef) Tag() string { - return r.namedRef.Named.(distreference.NamedTagged).Tag() -} -func (r *canonicalRef) Digest() digest.Digest { - return r.namedRef.Named.(distreference.Canonical).Digest() -} - -// WithDefaultTag adds a default tag to a reference if it only has a repo name. -func WithDefaultTag(ref Named) Named { - if IsNameOnly(ref) { - ref, _ = WithTag(ref, DefaultTag) - } - return ref -} - -// IsNameOnly returns true if reference only contains a repo name. -func IsNameOnly(ref Named) bool { - if _, ok := ref.(NamedTagged); ok { - return false - } - if _, ok := ref.(Canonical); ok { - return false - } - return true -} - -// ParseIDOrReference parses string for an image ID or a reference. ID can be -// without a default prefix. -func ParseIDOrReference(idOrRef string) (digest.Digest, Named, error) { - if err := stringid.ValidateID(idOrRef); err == nil { - idOrRef = "sha256:" + idOrRef - } - if dgst, err := digest.Parse(idOrRef); err == nil { - return dgst, nil, nil - } - ref, err := ParseNamed(idOrRef) - return "", ref, err -} - -func validateName(name string) error { - if err := stringid.ValidateID(name); err == nil { - return fmt.Errorf("Invalid repository name (%s), cannot specify 64-byte hexadecimal strings", name) - } - return nil -} diff --git a/reference/reference_test.go b/reference/reference_test.go deleted file mode 100644 index 481a2dd97b..0000000000 --- a/reference/reference_test.go +++ /dev/null @@ -1,275 +0,0 @@ -package reference - -import ( - "testing" - - "github.com/opencontainers/go-digest" -) - -func TestValidateReferenceName(t *testing.T) { - validRepoNames := []string{ - "docker/docker", - "library/debian", - "debian", - "docker.io/docker/docker", - "docker.io/library/debian", - "docker.io/debian", - "index.docker.io/docker/docker", - "index.docker.io/library/debian", - "index.docker.io/debian", - "127.0.0.1:5000/docker/docker", - "127.0.0.1:5000/library/debian", - "127.0.0.1:5000/debian", - "thisisthesongthatneverendsitgoesonandonandonthisisthesongthatnev", - } - invalidRepoNames := []string{ - "https://github.com/docker/docker", - "docker/Docker", - "-docker", - "-docker/docker", - "-docker.io/docker/docker", - "docker///docker", - "docker.io/docker/Docker", - "docker.io/docker///docker", - "1a3f5e7d9c1b3a5f7e9d1c3b5a7f9e1d3c5b7a9f1e3d5d7c9b1a3f5e7d9c1b3a", - "docker.io/1a3f5e7d9c1b3a5f7e9d1c3b5a7f9e1d3c5b7a9f1e3d5d7c9b1a3f5e7d9c1b3a", - } - - for _, name := range invalidRepoNames { - _, err := ParseNamed(name) - if err == nil { - t.Fatalf("Expected invalid repo name for %q", name) - } - } - - for _, name := range validRepoNames { - _, err := ParseNamed(name) - if err != nil { - t.Fatalf("Error parsing repo name %s, got: %q", name, err) - } - } -} - -func TestValidateRemoteName(t *testing.T) { - validRepositoryNames := []string{ - // Sanity check. - "docker/docker", - - // Allow 64-character non-hexadecimal names (hexadecimal names are forbidden). - "thisisthesongthatneverendsitgoesonandonandonthisisthesongthatnev", - - // Allow embedded hyphens. - "docker-rules/docker", - - // Allow multiple hyphens as well. - "docker---rules/docker", - - //Username doc and image name docker being tested. - "doc/docker", - - // single character names are now allowed. - "d/docker", - "jess/t", - - // Consecutive underscores. - "dock__er/docker", - } - for _, repositoryName := range validRepositoryNames { - _, err := ParseNamed(repositoryName) - if err != nil { - t.Errorf("Repository name should be valid: %v. Error: %v", repositoryName, err) - } - } - - invalidRepositoryNames := []string{ - // Disallow capital letters. - "docker/Docker", - - // Only allow one slash. - "docker///docker", - - // Disallow 64-character hexadecimal. - "1a3f5e7d9c1b3a5f7e9d1c3b5a7f9e1d3c5b7a9f1e3d5d7c9b1a3f5e7d9c1b3a", - - // Disallow leading and trailing hyphens in namespace. - "-docker/docker", - "docker-/docker", - "-docker-/docker", - - // Don't allow underscores everywhere (as opposed to hyphens). - "____/____", - - "_docker/_docker", - - // Disallow consecutive periods. - "dock..er/docker", - "dock_.er/docker", - "dock-.er/docker", - - // No repository. - "docker/", - - //namespace too long - "this_is_not_a_valid_namespace_because_its_lenth_is_greater_than_255_this_is_not_a_valid_namespace_because_its_lenth_is_greater_than_255_this_is_not_a_valid_namespace_because_its_lenth_is_greater_than_255_this_is_not_a_valid_namespace_because_its_lenth_is_greater_than_255/docker", - } - for _, repositoryName := range invalidRepositoryNames { - if _, err := ParseNamed(repositoryName); err == nil { - t.Errorf("Repository name should be invalid: %v", repositoryName) - } - } -} - -func TestParseRepositoryInfo(t *testing.T) { - type tcase struct { - RemoteName, NormalizedName, FullName, AmbiguousName, Hostname string - } - - tcases := []tcase{ - { - RemoteName: "fooo/bar", - NormalizedName: "fooo/bar", - FullName: "docker.io/fooo/bar", - AmbiguousName: "index.docker.io/fooo/bar", - Hostname: "docker.io", - }, - { - RemoteName: "library/ubuntu", - NormalizedName: "ubuntu", - FullName: "docker.io/library/ubuntu", - AmbiguousName: "library/ubuntu", - Hostname: "docker.io", - }, - { - RemoteName: "nonlibrary/ubuntu", - NormalizedName: "nonlibrary/ubuntu", - FullName: "docker.io/nonlibrary/ubuntu", - AmbiguousName: "", - Hostname: "docker.io", - }, - { - RemoteName: "other/library", - NormalizedName: "other/library", - FullName: "docker.io/other/library", - AmbiguousName: "", - Hostname: "docker.io", - }, - { - RemoteName: "private/moonbase", - NormalizedName: "127.0.0.1:8000/private/moonbase", - FullName: "127.0.0.1:8000/private/moonbase", - AmbiguousName: "", - Hostname: "127.0.0.1:8000", - }, - { - RemoteName: "privatebase", - NormalizedName: "127.0.0.1:8000/privatebase", - FullName: "127.0.0.1:8000/privatebase", - AmbiguousName: "", - Hostname: "127.0.0.1:8000", - }, - { - RemoteName: "private/moonbase", - NormalizedName: "example.com/private/moonbase", - FullName: "example.com/private/moonbase", - AmbiguousName: "", - Hostname: "example.com", - }, - { - RemoteName: "privatebase", - NormalizedName: "example.com/privatebase", - FullName: "example.com/privatebase", - AmbiguousName: "", - Hostname: "example.com", - }, - { - RemoteName: "private/moonbase", - NormalizedName: "example.com:8000/private/moonbase", - FullName: "example.com:8000/private/moonbase", - AmbiguousName: "", - Hostname: "example.com:8000", - }, - { - RemoteName: "privatebasee", - NormalizedName: "example.com:8000/privatebasee", - FullName: "example.com:8000/privatebasee", - AmbiguousName: "", - Hostname: "example.com:8000", - }, - { - RemoteName: "library/ubuntu-12.04-base", - NormalizedName: "ubuntu-12.04-base", - FullName: "docker.io/library/ubuntu-12.04-base", - AmbiguousName: "index.docker.io/library/ubuntu-12.04-base", - Hostname: "docker.io", - }, - } - - for _, tcase := range tcases { - refStrings := []string{tcase.NormalizedName, tcase.FullName} - if tcase.AmbiguousName != "" { - refStrings = append(refStrings, tcase.AmbiguousName) - } - - var refs []Named - for _, r := range refStrings { - named, err := ParseNamed(r) - if err != nil { - t.Fatal(err) - } - refs = append(refs, named) - named, err = WithName(r) - if err != nil { - t.Fatal(err) - } - refs = append(refs, named) - } - - for _, r := range refs { - if expected, actual := tcase.NormalizedName, r.Name(); expected != actual { - t.Fatalf("Invalid normalized reference for %q. Expected %q, got %q", r, expected, actual) - } - if expected, actual := tcase.FullName, r.FullName(); expected != actual { - t.Fatalf("Invalid fullName for %q. Expected %q, got %q", r, expected, actual) - } - if expected, actual := tcase.Hostname, r.Hostname(); expected != actual { - t.Fatalf("Invalid hostname for %q. Expected %q, got %q", r, expected, actual) - } - if expected, actual := tcase.RemoteName, r.RemoteName(); expected != actual { - t.Fatalf("Invalid remoteName for %q. Expected %q, got %q", r, expected, actual) - } - - } - } -} - -func TestParseReferenceWithTagAndDigest(t *testing.T) { - ref, err := ParseNamed("busybox:latest@sha256:86e0e091d0da6bde2456dbb48306f3956bbeb2eae1b5b9a43045843f69fe4aaa") - if err != nil { - t.Fatal(err) - } - if _, isTagged := ref.(NamedTagged); isTagged { - t.Fatalf("Reference from %q should not support tag", ref) - } - if _, isCanonical := ref.(Canonical); !isCanonical { - t.Fatalf("Reference from %q should not support digest", ref) - } - if expected, actual := "busybox@sha256:86e0e091d0da6bde2456dbb48306f3956bbeb2eae1b5b9a43045843f69fe4aaa", ref.String(); actual != expected { - t.Fatalf("Invalid parsed reference for %q: expected %q, got %q", ref, expected, actual) - } -} - -func TestInvalidReferenceComponents(t *testing.T) { - if _, err := WithName("-foo"); err == nil { - t.Fatal("Expected WithName to detect invalid name") - } - ref, err := WithName("busybox") - if err != nil { - t.Fatal(err) - } - if _, err := WithTag(ref, "-foo"); err == nil { - t.Fatal("Expected WithName to detect invalid tag") - } - if _, err := WithDigest(ref, digest.Digest("foo")); err == nil { - t.Fatal("Expected WithName to detect invalid digest") - } -} diff --git a/reference/store.go b/reference/store.go index 35ae33660a..844ebf5319 100644 --- a/reference/store.go +++ b/reference/store.go @@ -9,6 +9,7 @@ import ( "sort" "sync" + "github.com/docker/distribution/reference" "github.com/docker/docker/pkg/ioutils" "github.com/opencontainers/go-digest" ) @@ -21,18 +22,18 @@ var ( // An Association is a tuple associating a reference with an image ID. type Association struct { - Ref Named + Ref reference.Named ID digest.Digest } // Store provides the set of methods which can operate on a tag store. type Store interface { - References(id digest.Digest) []Named - ReferencesByName(ref Named) []Association - AddTag(ref Named, id digest.Digest, force bool) error - AddDigest(ref Canonical, id digest.Digest, force bool) error - Delete(ref Named) (bool, error) - Get(ref Named) (digest.Digest, error) + References(id digest.Digest) []reference.Named + ReferencesByName(ref reference.Named) []Association + AddTag(ref reference.Named, id digest.Digest, force bool) error + AddDigest(ref reference.Canonical, id digest.Digest, force bool) error + Delete(ref reference.Named) (bool, error) + Get(ref reference.Named) (digest.Digest, error) } type store struct { @@ -44,24 +45,28 @@ type store struct { Repositories map[string]repository // referencesByIDCache is a cache of references indexed by ID, to speed // up References. - referencesByIDCache map[digest.Digest]map[string]Named + referencesByIDCache map[digest.Digest]map[string]reference.Named } // Repository maps tags to digests. The key is a stringified Reference, // including the repository name. type repository map[string]digest.Digest -type lexicalRefs []Named +type lexicalRefs []reference.Named -func (a lexicalRefs) Len() int { return len(a) } -func (a lexicalRefs) Swap(i, j int) { a[i], a[j] = a[j], a[i] } -func (a lexicalRefs) Less(i, j int) bool { return a[i].String() < a[j].String() } +func (a lexicalRefs) Len() int { return len(a) } +func (a lexicalRefs) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +func (a lexicalRefs) Less(i, j int) bool { + return a[i].String() < a[j].String() +} type lexicalAssociations []Association -func (a lexicalAssociations) Len() int { return len(a) } -func (a lexicalAssociations) Swap(i, j int) { a[i], a[j] = a[j], a[i] } -func (a lexicalAssociations) Less(i, j int) bool { return a[i].Ref.String() < a[j].Ref.String() } +func (a lexicalAssociations) Len() int { return len(a) } +func (a lexicalAssociations) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +func (a lexicalAssociations) Less(i, j int) bool { + return a[i].Ref.String() < a[j].Ref.String() +} // NewReferenceStore creates a new reference store, tied to a file path where // the set of references are serialized in JSON format. @@ -74,7 +79,7 @@ func NewReferenceStore(jsonPath string) (Store, error) { store := &store{ jsonPath: abspath, Repositories: make(map[string]repository), - referencesByIDCache: make(map[digest.Digest]map[string]Named), + referencesByIDCache: make(map[digest.Digest]map[string]reference.Named), } // Load the json file if it exists, otherwise create it. if err := store.reload(); os.IsNotExist(err) { @@ -89,43 +94,45 @@ func NewReferenceStore(jsonPath string) (Store, error) { // AddTag adds a tag reference to the store. If force is set to true, existing // references can be overwritten. This only works for tags, not digests. -func (store *store) AddTag(ref Named, id digest.Digest, force bool) error { - if _, isCanonical := ref.(Canonical); isCanonical { +func (store *store) AddTag(ref reference.Named, id digest.Digest, force bool) error { + if _, isCanonical := ref.(reference.Canonical); isCanonical { return errors.New("refusing to create a tag with a digest reference") } - return store.addReference(WithDefaultTag(ref), id, force) + return store.addReference(reference.TagNameOnly(ref), id, force) } // AddDigest adds a digest reference to the store. -func (store *store) AddDigest(ref Canonical, id digest.Digest, force bool) error { +func (store *store) AddDigest(ref reference.Canonical, id digest.Digest, force bool) error { return store.addReference(ref, id, force) } -func (store *store) addReference(ref Named, id digest.Digest, force bool) error { - if ref.Name() == string(digest.Canonical) { +func (store *store) addReference(ref reference.Named, id digest.Digest, force bool) error { + refName := reference.FamiliarName(ref) + refStr := reference.FamiliarString(ref) + + if refName == string(digest.Canonical) { return errors.New("refusing to create an ambiguous tag using digest algorithm as name") } store.mu.Lock() defer store.mu.Unlock() - repository, exists := store.Repositories[ref.Name()] + repository, exists := store.Repositories[refName] if !exists || repository == nil { repository = make(map[string]digest.Digest) - store.Repositories[ref.Name()] = repository + store.Repositories[refName] = repository } - refStr := ref.String() oldID, exists := repository[refStr] if exists { // force only works for tags - if digested, isDigest := ref.(Canonical); isDigest { + if digested, isDigest := ref.(reference.Canonical); isDigest { return fmt.Errorf("Cannot overwrite digest %s", digested.Digest().String()) } if !force { - return fmt.Errorf("Conflict: Tag %s is already set to image %s, if you want to replace it, please use -f option", ref.String(), oldID.String()) + return fmt.Errorf("Conflict: Tag %s is already set to image %s, if you want to replace it, please use -f option", refStr, oldID.String()) } if store.referencesByIDCache[oldID] != nil { @@ -138,7 +145,7 @@ func (store *store) addReference(ref Named, id digest.Digest, force bool) error repository[refStr] = id if store.referencesByIDCache[id] == nil { - store.referencesByIDCache[id] = make(map[string]Named) + store.referencesByIDCache[id] = make(map[string]reference.Named) } store.referencesByIDCache[id][refStr] = ref @@ -147,24 +154,24 @@ func (store *store) addReference(ref Named, id digest.Digest, force bool) error // Delete deletes a reference from the store. It returns true if a deletion // happened, or false otherwise. -func (store *store) Delete(ref Named) (bool, error) { - ref = WithDefaultTag(ref) +func (store *store) Delete(ref reference.Named) (bool, error) { + ref = reference.TagNameOnly(ref) + + refName := reference.FamiliarName(ref) + refStr := reference.FamiliarString(ref) store.mu.Lock() defer store.mu.Unlock() - repoName := ref.Name() - - repository, exists := store.Repositories[repoName] + repository, exists := store.Repositories[refName] if !exists { return false, ErrDoesNotExist } - refStr := ref.String() if id, exists := repository[refStr]; exists { delete(repository, refStr) if len(repository) == 0 { - delete(store.Repositories, repoName) + delete(store.Repositories, refName) } if store.referencesByIDCache[id] != nil { delete(store.referencesByIDCache[id], refStr) @@ -179,18 +186,34 @@ func (store *store) Delete(ref Named) (bool, error) { } // Get retrieves an item from the store by reference -func (store *store) Get(ref Named) (digest.Digest, error) { - ref = WithDefaultTag(ref) +func (store *store) Get(ref reference.Named) (digest.Digest, error) { + if canonical, ok := ref.(reference.Canonical); ok { + // If reference contains both tag and digest, only + // lookup by digest as it takes precendent over + // tag, until tag/digest combos are stored. + if _, ok := ref.(reference.Tagged); ok { + var err error + ref, err = reference.WithDigest(reference.TrimNamed(canonical), canonical.Digest()) + if err != nil { + return "", err + } + } + } else { + ref = reference.TagNameOnly(ref) + } + + refName := reference.FamiliarName(ref) + refStr := reference.FamiliarString(ref) store.mu.RLock() defer store.mu.RUnlock() - repository, exists := store.Repositories[ref.Name()] + repository, exists := store.Repositories[refName] if !exists || repository == nil { return "", ErrDoesNotExist } - id, exists := repository[ref.String()] + id, exists := repository[refStr] if !exists { return "", ErrDoesNotExist } @@ -200,7 +223,7 @@ func (store *store) Get(ref Named) (digest.Digest, error) { // References returns a slice of references to the given ID. The slice // will be nil if there are no references to this ID. -func (store *store) References(id digest.Digest) []Named { +func (store *store) References(id digest.Digest) []reference.Named { store.mu.RLock() defer store.mu.RUnlock() @@ -208,7 +231,7 @@ func (store *store) References(id digest.Digest) []Named { // 1) We must not return a mutable // 2) It would be ugly to expose the extraneous map keys to callers. - var references []Named + var references []reference.Named for _, ref := range store.referencesByIDCache[id] { references = append(references, ref) } @@ -221,18 +244,20 @@ func (store *store) References(id digest.Digest) []Named { // ReferencesByName returns the references for a given repository name. // If there are no references known for this repository name, // ReferencesByName returns nil. -func (store *store) ReferencesByName(ref Named) []Association { +func (store *store) ReferencesByName(ref reference.Named) []Association { + refName := reference.FamiliarName(ref) + store.mu.RLock() defer store.mu.RUnlock() - repository, exists := store.Repositories[ref.Name()] + repository, exists := store.Repositories[refName] if !exists { return nil } var associations []Association for refStr, refID := range repository { - ref, err := ParseNamed(refStr) + ref, err := reference.ParseNormalizedNamed(refStr) if err != nil { // Should never happen return nil @@ -270,13 +295,13 @@ func (store *store) reload() error { for _, repository := range store.Repositories { for refStr, refID := range repository { - ref, err := ParseNamed(refStr) + ref, err := reference.ParseNormalizedNamed(refStr) if err != nil { // Should never happen continue } if store.referencesByIDCache[refID] == nil { - store.referencesByIDCache[refID] = make(map[string]Named) + store.referencesByIDCache[refID] = make(map[string]reference.Named) } store.referencesByIDCache[refID][refStr] = ref } diff --git a/reference/store_test.go b/reference/store_test.go index 0d96e6b694..8f0ff6304e 100644 --- a/reference/store_test.go +++ b/reference/store_test.go @@ -8,6 +8,7 @@ import ( "strings" "testing" + "github.com/docker/distribution/reference" "github.com/opencontainers/go-digest" ) @@ -45,7 +46,7 @@ func TestLoad(t *testing.T) { } for refStr, expectedID := range saveLoadTestCases { - ref, err := ParseNamed(refStr) + ref, err := reference.ParseNormalizedNamed(refStr) if err != nil { t.Fatalf("failed to parse reference: %v", err) } @@ -74,11 +75,11 @@ func TestSave(t *testing.T) { } for refStr, id := range saveLoadTestCases { - ref, err := ParseNamed(refStr) + ref, err := reference.ParseNormalizedNamed(refStr) if err != nil { t.Fatalf("failed to parse reference: %v", err) } - if canonical, ok := ref.(Canonical); ok { + if canonical, ok := ref.(reference.Canonical); ok { err = store.AddDigest(canonical, id, false) if err != nil { t.Fatalf("could not add digest reference %s: %v", refStr, err) @@ -120,7 +121,7 @@ func TestAddDeleteGet(t *testing.T) { testImageID3 := digest.Digest("sha256:9655aef5fd742a1b4e1b7b163aa9f1c76c186304bf39102283d80927c916ca9e") // Try adding a reference with no tag or digest - nameOnly, err := WithName("username/repo") + nameOnly, err := reference.ParseNormalizedNamed("username/repo") if err != nil { t.Fatalf("could not parse reference: %v", err) } @@ -129,7 +130,7 @@ func TestAddDeleteGet(t *testing.T) { } // Add a few references - ref1, err := ParseNamed("username/repo1:latest") + ref1, err := reference.ParseNormalizedNamed("username/repo1:latest") if err != nil { t.Fatalf("could not parse reference: %v", err) } @@ -137,7 +138,7 @@ func TestAddDeleteGet(t *testing.T) { t.Fatalf("error adding to store: %v", err) } - ref2, err := ParseNamed("username/repo1:old") + ref2, err := reference.ParseNormalizedNamed("username/repo1:old") if err != nil { t.Fatalf("could not parse reference: %v", err) } @@ -145,7 +146,7 @@ func TestAddDeleteGet(t *testing.T) { t.Fatalf("error adding to store: %v", err) } - ref3, err := ParseNamed("username/repo1:alias") + ref3, err := reference.ParseNormalizedNamed("username/repo1:alias") if err != nil { t.Fatalf("could not parse reference: %v", err) } @@ -153,7 +154,7 @@ func TestAddDeleteGet(t *testing.T) { t.Fatalf("error adding to store: %v", err) } - ref4, err := ParseNamed("username/repo2:latest") + ref4, err := reference.ParseNormalizedNamed("username/repo2:latest") if err != nil { t.Fatalf("could not parse reference: %v", err) } @@ -161,11 +162,11 @@ func TestAddDeleteGet(t *testing.T) { t.Fatalf("error adding to store: %v", err) } - ref5, err := ParseNamed("username/repo3@sha256:58153dfb11794fad694460162bf0cb0a4fa710cfa3f60979c177d920813e267c") + ref5, err := reference.ParseNormalizedNamed("username/repo3@sha256:58153dfb11794fad694460162bf0cb0a4fa710cfa3f60979c177d920813e267c") if err != nil { t.Fatalf("could not parse reference: %v", err) } - if err = store.AddDigest(ref5.(Canonical), testImageID2, false); err != nil { + if err = store.AddDigest(ref5.(reference.Canonical), testImageID2, false); err != nil { t.Fatalf("error adding to store: %v", err) } @@ -228,7 +229,7 @@ func TestAddDeleteGet(t *testing.T) { } // Get should return ErrDoesNotExist for a nonexistent repo - nonExistRepo, err := ParseNamed("username/nonexistrepo:latest") + nonExistRepo, err := reference.ParseNormalizedNamed("username/nonexistrepo:latest") if err != nil { t.Fatalf("could not parse reference: %v", err) } @@ -237,7 +238,7 @@ func TestAddDeleteGet(t *testing.T) { } // Get should return ErrDoesNotExist for a nonexistent tag - nonExistTag, err := ParseNamed("username/repo1:nonexist") + nonExistTag, err := reference.ParseNormalizedNamed("username/repo1:nonexist") if err != nil { t.Fatalf("could not parse reference: %v", err) } @@ -263,7 +264,7 @@ func TestAddDeleteGet(t *testing.T) { } // Check ReferencesByName - repoName, err := WithName("username/repo1") + repoName, err := reference.ParseNormalizedNamed("username/repo1") if err != nil { t.Fatalf("could not parse reference: %v", err) } @@ -334,7 +335,7 @@ func TestInvalidTags(t *testing.T) { id := digest.Digest("sha256:470022b8af682154f57a2163d030eb369549549cba00edc69e1b99b46bb924d6") // sha256 as repo name - ref, err := ParseNamed("sha256:abc") + ref, err := reference.ParseNormalizedNamed("sha256:abc") if err != nil { t.Fatal(err) } @@ -344,7 +345,7 @@ func TestInvalidTags(t *testing.T) { } // setting digest as a tag - ref, err = ParseNamed("registry@sha256:367eb40fd0330a7e464777121e39d2f5b3e8e23a1e159342e53ab05c9e4d94e6") + ref, err = reference.ParseNormalizedNamed("registry@sha256:367eb40fd0330a7e464777121e39d2f5b3e8e23a1e159342e53ab05c9e4d94e6") if err != nil { t.Fatal(err) } |