3277d9fc74
Several requirements for storing registry data have been compiled and the backend layout has been refactored to comply. Specifically, we now store most data as blobs that are linked from repositories. All data access is traversed through repositories. Manifest updates are no longer destructive and support references by digest or tag. Signatures for manifests are now stored externally to the manifest payload to allow merging of signatures posted at different time. The design is detailed in the documentation for pathMapper. Signed-off-by: Stephen J Day <stephen.day@docker.com>
138 lines
3.6 KiB
Go
138 lines
3.6 KiB
Go
package storage
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/docker/distribution/digest"
|
|
)
|
|
|
|
func TestPathMapper(t *testing.T) {
|
|
pm := &pathMapper{
|
|
root: "/pathmapper-test",
|
|
}
|
|
|
|
for _, testcase := range []struct {
|
|
spec pathSpec
|
|
expected string
|
|
err error
|
|
}{
|
|
{
|
|
spec: manifestRevisionPathSpec{
|
|
name: "foo/bar",
|
|
revision: "sha256:abcdef0123456789",
|
|
},
|
|
expected: "/pathmapper-test/repositories/foo/bar/manifests/revisions/sha256/abcdef0123456789",
|
|
},
|
|
{
|
|
spec: manifestRevisionLinkPathSpec{
|
|
name: "foo/bar",
|
|
revision: "sha256:abcdef0123456789",
|
|
},
|
|
expected: "/pathmapper-test/repositories/foo/bar/manifests/revisions/sha256/abcdef0123456789/link",
|
|
},
|
|
{
|
|
spec: manifestSignatureLinkPathSpec{
|
|
name: "foo/bar",
|
|
revision: "sha256:abcdef0123456789",
|
|
signature: "sha256:abcdef0123456789",
|
|
},
|
|
expected: "/pathmapper-test/repositories/foo/bar/manifests/revisions/sha256/abcdef0123456789/signatures/sha256/abcdef0123456789/link",
|
|
},
|
|
{
|
|
spec: manifestSignaturesPathSpec{
|
|
name: "foo/bar",
|
|
revision: "sha256:abcdef0123456789",
|
|
},
|
|
expected: "/pathmapper-test/repositories/foo/bar/manifests/revisions/sha256/abcdef0123456789/signatures",
|
|
},
|
|
{
|
|
spec: manifestTagsPathSpec{
|
|
name: "foo/bar",
|
|
},
|
|
expected: "/pathmapper-test/repositories/foo/bar/manifests/tags",
|
|
},
|
|
{
|
|
spec: manifestTagPathSpec{
|
|
name: "foo/bar",
|
|
tag: "thetag",
|
|
},
|
|
expected: "/pathmapper-test/repositories/foo/bar/manifests/tags/thetag",
|
|
},
|
|
{
|
|
spec: manifestTagCurrentPathSpec{
|
|
name: "foo/bar",
|
|
tag: "thetag",
|
|
},
|
|
expected: "/pathmapper-test/repositories/foo/bar/manifests/tags/thetag/current/link",
|
|
},
|
|
{
|
|
spec: manifestTagIndexPathSpec{
|
|
name: "foo/bar",
|
|
tag: "thetag",
|
|
},
|
|
expected: "/pathmapper-test/repositories/foo/bar/manifests/tags/thetag/index",
|
|
},
|
|
{
|
|
spec: manifestTagIndexEntryPathSpec{
|
|
name: "foo/bar",
|
|
tag: "thetag",
|
|
revision: "sha256:abcdef0123456789",
|
|
},
|
|
expected: "/pathmapper-test/repositories/foo/bar/manifests/tags/thetag/index/sha256/abcdef0123456789/link",
|
|
},
|
|
{
|
|
spec: layerLinkPathSpec{
|
|
name: "foo/bar",
|
|
digest: "tarsum.v1+test:abcdef",
|
|
},
|
|
expected: "/pathmapper-test/repositories/foo/bar/layers/tarsum/v1/test/abcdef/link",
|
|
},
|
|
{
|
|
spec: blobDataPathSpec{
|
|
digest: digest.Digest("tarsum.dev+sha512:abcdefabcdefabcdef908909909"),
|
|
},
|
|
expected: "/pathmapper-test/blobs/tarsum/dev/sha512/ab/abcdefabcdefabcdef908909909/data",
|
|
},
|
|
{
|
|
spec: blobDataPathSpec{
|
|
digest: digest.Digest("tarsum.v1+sha256:abcdefabcdefabcdef908909909"),
|
|
},
|
|
expected: "/pathmapper-test/blobs/tarsum/v1/sha256/ab/abcdefabcdefabcdef908909909/data",
|
|
},
|
|
|
|
{
|
|
spec: uploadDataPathSpec{
|
|
name: "foo/bar",
|
|
uuid: "asdf-asdf-asdf-adsf",
|
|
},
|
|
expected: "/pathmapper-test/repositories/foo/bar/uploads/asdf-asdf-asdf-adsf/data",
|
|
},
|
|
{
|
|
spec: uploadStartedAtPathSpec{
|
|
name: "foo/bar",
|
|
uuid: "asdf-asdf-asdf-adsf",
|
|
},
|
|
expected: "/pathmapper-test/repositories/foo/bar/uploads/asdf-asdf-asdf-adsf/startedat",
|
|
},
|
|
} {
|
|
p, err := pm.path(testcase.spec)
|
|
if err != nil {
|
|
t.Fatalf("unexpected generating path (%T): %v", testcase.spec, err)
|
|
}
|
|
|
|
if p != testcase.expected {
|
|
t.Fatalf("unexpected path generated (%T): %q != %q", testcase.spec, p, testcase.expected)
|
|
}
|
|
}
|
|
|
|
// Add a few test cases to ensure we cover some errors
|
|
|
|
// Specify a path that requires a revision and get a digest validation error.
|
|
badpath, err := pm.path(manifestSignaturesPathSpec{
|
|
name: "foo/bar",
|
|
})
|
|
if err == nil {
|
|
t.Fatalf("expected an error when mapping an invalid revision: %s", badpath)
|
|
}
|
|
|
|
}
|