commit
						ae2146c6a8
					
				|  | @ -13,7 +13,6 @@ import ( | |||
| // creating and traversing backend links.
 | ||||
| type blobStore struct { | ||||
| 	driver  driver.StorageDriver | ||||
| 	pm      *pathMapper | ||||
| 	statter distribution.BlobStatter | ||||
| } | ||||
| 
 | ||||
|  | @ -94,7 +93,7 @@ func (bs *blobStore) Put(ctx context.Context, mediaType string, p []byte) (distr | |||
| // path returns the canonical path for the blob identified by digest. The blob
 | ||||
| // may or may not exist.
 | ||||
| func (bs *blobStore) path(dgst digest.Digest) (string, error) { | ||||
| 	bp, err := bs.pm.path(blobDataPathSpec{ | ||||
| 	bp, err := pathFor(blobDataPathSpec{ | ||||
| 		digest: dgst, | ||||
| 	}) | ||||
| 
 | ||||
|  | @ -140,7 +139,6 @@ func (bs *blobStore) resolve(ctx context.Context, path string) (string, error) { | |||
| 
 | ||||
| type blobStatter struct { | ||||
| 	driver driver.StorageDriver | ||||
| 	pm     *pathMapper | ||||
| } | ||||
| 
 | ||||
| var _ distribution.BlobDescriptorService = &blobStatter{} | ||||
|  | @ -149,9 +147,10 @@ var _ distribution.BlobDescriptorService = &blobStatter{} | |||
| // in the main blob store. If this method returns successfully, there is
 | ||||
| // strong guarantee that the blob exists and is available.
 | ||||
| func (bs *blobStatter) Stat(ctx context.Context, dgst digest.Digest) (distribution.Descriptor, error) { | ||||
| 	path, err := bs.pm.path(blobDataPathSpec{ | ||||
| 	path, err := pathFor(blobDataPathSpec{ | ||||
| 		digest: dgst, | ||||
| 	}) | ||||
| 
 | ||||
| 	if err != nil { | ||||
| 		return distribution.Descriptor{}, err | ||||
| 	} | ||||
|  |  | |||
|  | @ -266,7 +266,7 @@ func (bw *blobWriter) validateBlob(ctx context.Context, desc distribution.Descri | |||
| // identified by dgst. The layer should be validated before commencing the
 | ||||
| // move.
 | ||||
| func (bw *blobWriter) moveBlob(ctx context.Context, desc distribution.Descriptor) error { | ||||
| 	blobPath, err := bw.blobStore.pm.path(blobDataPathSpec{ | ||||
| 	blobPath, err := pathFor(blobDataPathSpec{ | ||||
| 		digest: desc.Digest, | ||||
| 	}) | ||||
| 
 | ||||
|  | @ -324,7 +324,7 @@ func (bw *blobWriter) moveBlob(ctx context.Context, desc distribution.Descriptor | |||
| // instance. An error will be returned if the clean up cannot proceed. If the
 | ||||
| // resources are already not present, no error will be returned.
 | ||||
| func (bw *blobWriter) removeResources(ctx context.Context) error { | ||||
| 	dataPath, err := bw.blobStore.pm.path(uploadDataPathSpec{ | ||||
| 	dataPath, err := pathFor(uploadDataPathSpec{ | ||||
| 		name: bw.blobStore.repository.Name(), | ||||
| 		id:   bw.id, | ||||
| 	}) | ||||
|  |  | |||
|  | @ -111,12 +111,13 @@ type hashStateEntry struct { | |||
| 
 | ||||
| // getStoredHashStates returns a slice of hashStateEntries for this upload.
 | ||||
| func (bw *blobWriter) getStoredHashStates(ctx context.Context) ([]hashStateEntry, error) { | ||||
| 	uploadHashStatePathPrefix, err := bw.blobStore.pm.path(uploadHashStatePathSpec{ | ||||
| 	uploadHashStatePathPrefix, err := pathFor(uploadHashStatePathSpec{ | ||||
| 		name: bw.blobStore.repository.Name(), | ||||
| 		id:   bw.id, | ||||
| 		alg:  bw.digester.Digest().Algorithm(), | ||||
| 		list: true, | ||||
| 	}) | ||||
| 
 | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | @ -156,12 +157,13 @@ func (bw *blobWriter) storeHashState(ctx context.Context) error { | |||
| 		return errResumableDigestNotAvailable | ||||
| 	} | ||||
| 
 | ||||
| 	uploadHashStatePath, err := bw.blobStore.pm.path(uploadHashStatePathSpec{ | ||||
| 	uploadHashStatePath, err := pathFor(uploadHashStatePathSpec{ | ||||
| 		name:   bw.blobStore.repository.Name(), | ||||
| 		id:     bw.id, | ||||
| 		alg:    bw.digester.Digest().Algorithm(), | ||||
| 		offset: int64(h.Len()), | ||||
| 	}) | ||||
| 
 | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  |  | |||
|  | @ -22,7 +22,7 @@ func (reg *registry) Repositories(ctx context.Context, repos []string, last stri | |||
| 		return 0, errors.New("no space in slice") | ||||
| 	} | ||||
| 
 | ||||
| 	root, err := defaultPathMapper.path(repositoriesRootPathSpec{}) | ||||
| 	root, err := pathFor(repositoriesRootPathSpec{}) | ||||
| 	if err != nil { | ||||
| 		return 0, err | ||||
| 	} | ||||
|  |  | |||
|  | @ -23,7 +23,7 @@ func setupFS(t *testing.T) *setupEnv { | |||
| 	c := []byte("") | ||||
| 	ctx := context.Background() | ||||
| 	registry := NewRegistryWithDriver(ctx, d, memory.NewInMemoryBlobDescriptorCacheProvider(), false, true, false) | ||||
| 	rootpath, _ := defaultPathMapper.path(repositoriesRootPathSpec{}) | ||||
| 	rootpath, _ := pathFor(repositoriesRootPathSpec{}) | ||||
| 
 | ||||
| 	repos := []string{ | ||||
| 		"/foo/a/_layers/1", | ||||
|  |  | |||
|  | @ -13,7 +13,7 @@ import ( | |||
| 
 | ||||
| // linkPathFunc describes a function that can resolve a link based on the
 | ||||
| // repository name and digest.
 | ||||
| type linkPathFunc func(pm *pathMapper, name string, dgst digest.Digest) (string, error) | ||||
| type linkPathFunc func(name string, dgst digest.Digest) (string, error) | ||||
| 
 | ||||
| // linkedBlobStore provides a full BlobService that namespaces the blobs to a
 | ||||
| // given repository. Effectively, it manages the links in a given repository
 | ||||
|  | @ -104,7 +104,7 @@ func (lbs *linkedBlobStore) Create(ctx context.Context) (distribution.BlobWriter | |||
| 	uuid := uuid.Generate().String() | ||||
| 	startedAt := time.Now().UTC() | ||||
| 
 | ||||
| 	path, err := lbs.blobStore.pm.path(uploadDataPathSpec{ | ||||
| 	path, err := pathFor(uploadDataPathSpec{ | ||||
| 		name: lbs.repository.Name(), | ||||
| 		id:   uuid, | ||||
| 	}) | ||||
|  | @ -113,7 +113,7 @@ func (lbs *linkedBlobStore) Create(ctx context.Context) (distribution.BlobWriter | |||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	startedAtPath, err := lbs.blobStore.pm.path(uploadStartedAtPathSpec{ | ||||
| 	startedAtPath, err := pathFor(uploadStartedAtPathSpec{ | ||||
| 		name: lbs.repository.Name(), | ||||
| 		id:   uuid, | ||||
| 	}) | ||||
|  | @ -133,7 +133,7 @@ func (lbs *linkedBlobStore) Create(ctx context.Context) (distribution.BlobWriter | |||
| func (lbs *linkedBlobStore) Resume(ctx context.Context, id string) (distribution.BlobWriter, error) { | ||||
| 	context.GetLogger(ctx).Debug("(*linkedBlobStore).Resume") | ||||
| 
 | ||||
| 	startedAtPath, err := lbs.blobStore.pm.path(uploadStartedAtPathSpec{ | ||||
| 	startedAtPath, err := pathFor(uploadStartedAtPathSpec{ | ||||
| 		name: lbs.repository.Name(), | ||||
| 		id:   id, | ||||
| 	}) | ||||
|  | @ -157,7 +157,7 @@ func (lbs *linkedBlobStore) Resume(ctx context.Context, id string) (distribution | |||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	path, err := lbs.pm.path(uploadDataPathSpec{ | ||||
| 	path, err := pathFor(uploadDataPathSpec{ | ||||
| 		name: lbs.repository.Name(), | ||||
| 		id:   id, | ||||
| 	}) | ||||
|  | @ -228,7 +228,7 @@ func (lbs *linkedBlobStore) linkBlob(ctx context.Context, canonical distribution | |||
| 		} | ||||
| 		seenDigests[dgst] = struct{}{} | ||||
| 
 | ||||
| 		blobLinkPath, err := linkPathFn(lbs.pm, lbs.repository.Name(), dgst) | ||||
| 		blobLinkPath, err := linkPathFn(lbs.repository.Name(), dgst) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
|  | @ -298,7 +298,7 @@ func (lbs *linkedBlobStatter) Stat(ctx context.Context, dgst digest.Digest) (dis | |||
| func (lbs *linkedBlobStatter) Clear(ctx context.Context, dgst digest.Digest) (err error) { | ||||
| 	// clear any possible existence of a link described in linkPathFns
 | ||||
| 	for _, linkPathFn := range lbs.linkPathFns { | ||||
| 		blobLinkPath, err := linkPathFn(lbs.pm, lbs.repository.Name(), dgst) | ||||
| 		blobLinkPath, err := linkPathFn(lbs.repository.Name(), dgst) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
|  | @ -321,7 +321,7 @@ func (lbs *linkedBlobStatter) Clear(ctx context.Context, dgst digest.Digest) (er | |||
| // linkPathFuncs to let us try a few different paths before returning not
 | ||||
| // found.
 | ||||
| func (lbs *linkedBlobStatter) resolveWithLinkFunc(ctx context.Context, dgst digest.Digest, linkPathFn linkPathFunc) (digest.Digest, error) { | ||||
| 	blobLinkPath, err := linkPathFn(lbs.pm, lbs.repository.Name(), dgst) | ||||
| 	blobLinkPath, err := linkPathFn(lbs.repository.Name(), dgst) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
|  | @ -335,11 +335,11 @@ func (lbs *linkedBlobStatter) SetDescriptor(ctx context.Context, dgst digest.Dig | |||
| } | ||||
| 
 | ||||
| // blobLinkPath provides the path to the blob link, also known as layers.
 | ||||
| func blobLinkPath(pm *pathMapper, name string, dgst digest.Digest) (string, error) { | ||||
| 	return pm.path(layerLinkPathSpec{name: name, digest: dgst}) | ||||
| func blobLinkPath(name string, dgst digest.Digest) (string, error) { | ||||
| 	return pathFor(layerLinkPathSpec{name: name, digest: dgst}) | ||||
| } | ||||
| 
 | ||||
| // manifestRevisionLinkPath provides the path to the manifest revision link.
 | ||||
| func manifestRevisionLinkPath(pm *pathMapper, name string, dgst digest.Digest) (string, error) { | ||||
| 	return pm.path(manifestRevisionLinkPathSpec{name: name, revision: dgst}) | ||||
| func manifestRevisionLinkPath(name string, dgst digest.Digest) (string, error) { | ||||
| 	return pathFor(manifestRevisionLinkPathSpec{name: name, revision: dgst}) | ||||
| } | ||||
|  |  | |||
|  | @ -385,7 +385,7 @@ func TestLinkPathFuncs(t *testing.T) { | |||
| 			expected:   "/docker/registry/v2/repositories/foo/bar/_manifests/revisions/sha256/deadbeaf/link", | ||||
| 		}, | ||||
| 	} { | ||||
| 		p, err := testcase.linkPathFn(defaultPathMapper, testcase.repo, testcase.digest) | ||||
| 		p, err := testcase.linkPathFn(testcase.repo, testcase.digest) | ||||
| 		if err != nil { | ||||
| 			t.Fatalf("unexpected error calling linkPathFn(pm, %q, %q): %v", testcase.repo, testcase.digest, err) | ||||
| 		} | ||||
|  |  | |||
|  | @ -8,10 +8,18 @@ import ( | |||
| 	"github.com/docker/distribution/digest" | ||||
| ) | ||||
| 
 | ||||
| const storagePathVersion = "v2" | ||||
| const ( | ||||
| 	storagePathVersion = "v2"                // fixed storage layout version
 | ||||
| 	storagePathRoot    = "/docker/registry/" // all driver paths have a prefix
 | ||||
| 
 | ||||
| // pathMapper maps paths based on "object names" and their ids. The "object
 | ||||
| // names" mapped by pathMapper are internal to the storage system.
 | ||||
| 	// TODO(stevvooe): Get rid of the "storagePathRoot". Initially, we though
 | ||||
| 	// storage path root would configurable for all drivers through this
 | ||||
| 	// package. In reality, we've found it simpler to do this on a per driver
 | ||||
| 	// basis.
 | ||||
| ) | ||||
| 
 | ||||
| // pathFor maps paths based on "object names" and their ids. The "object
 | ||||
| // names" mapped by are internal to the storage system.
 | ||||
| //
 | ||||
| // The path layout in the storage backend is roughly as follows:
 | ||||
| //
 | ||||
|  | @ -37,7 +45,7 @@ const storagePathVersion = "v2" | |||
| //			-> blob/<algorithm>
 | ||||
| //				<split directory content addressable storage>
 | ||||
| //
 | ||||
| // The storage backend layout is broken up into a content- addressable blob
 | ||||
| // The storage backend layout is broken up into a content-addressable blob
 | ||||
| // store and repositories. The content-addressable blob store holds most data
 | ||||
| // throughout the backend, keyed by algorithm and digests of the underlying
 | ||||
| // content. Access to the blob store is controled through links from the
 | ||||
|  | @ -98,18 +106,7 @@ const storagePathVersion = "v2" | |||
| //
 | ||||
| // For more information on the semantic meaning of each path and their
 | ||||
| // contents, please see the path spec documentation.
 | ||||
| type pathMapper struct { | ||||
| 	root    string | ||||
| 	version string // should be a constant?
 | ||||
| } | ||||
| 
 | ||||
| var defaultPathMapper = &pathMapper{ | ||||
| 	root:    "/docker/registry/", | ||||
| 	version: storagePathVersion, | ||||
| } | ||||
| 
 | ||||
| // path returns the path identified by spec.
 | ||||
| func (pm *pathMapper) path(spec pathSpec) (string, error) { | ||||
| func pathFor(spec pathSpec) (string, error) { | ||||
| 
 | ||||
| 	// Switch on the path object type and return the appropriate path. At
 | ||||
| 	// first glance, one may wonder why we don't use an interface to
 | ||||
|  | @ -123,7 +120,7 @@ func (pm *pathMapper) path(spec pathSpec) (string, error) { | |||
| 	// to an intermediate path object, than can be consumed and mapped by the
 | ||||
| 	// other version.
 | ||||
| 
 | ||||
| 	rootPrefix := []string{pm.root, pm.version} | ||||
| 	rootPrefix := []string{storagePathRoot, storagePathVersion} | ||||
| 	repoPrefix := append(rootPrefix, "repositories") | ||||
| 
 | ||||
| 	switch v := spec.(type) { | ||||
|  | @ -136,7 +133,7 @@ func (pm *pathMapper) path(spec pathSpec) (string, error) { | |||
| 
 | ||||
| 		return path.Join(append(append(repoPrefix, v.name, "_manifests", "revisions"), components...)...), nil | ||||
| 	case manifestRevisionLinkPathSpec: | ||||
| 		root, err := pm.path(manifestRevisionPathSpec{ | ||||
| 		root, err := pathFor(manifestRevisionPathSpec{ | ||||
| 			name:     v.name, | ||||
| 			revision: v.revision, | ||||
| 		}) | ||||
|  | @ -147,7 +144,7 @@ func (pm *pathMapper) path(spec pathSpec) (string, error) { | |||
| 
 | ||||
| 		return path.Join(root, "link"), nil | ||||
| 	case manifestSignaturesPathSpec: | ||||
| 		root, err := pm.path(manifestRevisionPathSpec{ | ||||
| 		root, err := pathFor(manifestRevisionPathSpec{ | ||||
| 			name:     v.name, | ||||
| 			revision: v.revision, | ||||
| 		}) | ||||
|  | @ -158,10 +155,11 @@ func (pm *pathMapper) path(spec pathSpec) (string, error) { | |||
| 
 | ||||
| 		return path.Join(root, "signatures"), nil | ||||
| 	case manifestSignatureLinkPathSpec: | ||||
| 		root, err := pm.path(manifestSignaturesPathSpec{ | ||||
| 		root, err := pathFor(manifestSignaturesPathSpec{ | ||||
| 			name:     v.name, | ||||
| 			revision: v.revision, | ||||
| 		}) | ||||
| 
 | ||||
| 		if err != nil { | ||||
| 			return "", err | ||||
| 		} | ||||
|  | @ -175,50 +173,55 @@ func (pm *pathMapper) path(spec pathSpec) (string, error) { | |||
| 	case manifestTagsPathSpec: | ||||
| 		return path.Join(append(repoPrefix, v.name, "_manifests", "tags")...), nil | ||||
| 	case manifestTagPathSpec: | ||||
| 		root, err := pm.path(manifestTagsPathSpec{ | ||||
| 		root, err := pathFor(manifestTagsPathSpec{ | ||||
| 			name: v.name, | ||||
| 		}) | ||||
| 
 | ||||
| 		if err != nil { | ||||
| 			return "", err | ||||
| 		} | ||||
| 
 | ||||
| 		return path.Join(root, v.tag), nil | ||||
| 	case manifestTagCurrentPathSpec: | ||||
| 		root, err := pm.path(manifestTagPathSpec{ | ||||
| 		root, err := pathFor(manifestTagPathSpec{ | ||||
| 			name: v.name, | ||||
| 			tag:  v.tag, | ||||
| 		}) | ||||
| 
 | ||||
| 		if err != nil { | ||||
| 			return "", err | ||||
| 		} | ||||
| 
 | ||||
| 		return path.Join(root, "current", "link"), nil | ||||
| 	case manifestTagIndexPathSpec: | ||||
| 		root, err := pm.path(manifestTagPathSpec{ | ||||
| 		root, err := pathFor(manifestTagPathSpec{ | ||||
| 			name: v.name, | ||||
| 			tag:  v.tag, | ||||
| 		}) | ||||
| 
 | ||||
| 		if err != nil { | ||||
| 			return "", err | ||||
| 		} | ||||
| 
 | ||||
| 		return path.Join(root, "index"), nil | ||||
| 	case manifestTagIndexEntryLinkPathSpec: | ||||
| 		root, err := pm.path(manifestTagIndexEntryPathSpec{ | ||||
| 		root, err := pathFor(manifestTagIndexEntryPathSpec{ | ||||
| 			name:     v.name, | ||||
| 			tag:      v.tag, | ||||
| 			revision: v.revision, | ||||
| 		}) | ||||
| 
 | ||||
| 		if err != nil { | ||||
| 			return "", err | ||||
| 		} | ||||
| 
 | ||||
| 		return path.Join(root, "link"), nil | ||||
| 	case manifestTagIndexEntryPathSpec: | ||||
| 		root, err := pm.path(manifestTagIndexPathSpec{ | ||||
| 		root, err := pathFor(manifestTagIndexPathSpec{ | ||||
| 			name: v.name, | ||||
| 			tag:  v.tag, | ||||
| 		}) | ||||
| 
 | ||||
| 		if err != nil { | ||||
| 			return "", err | ||||
| 		} | ||||
|  |  | |||
|  | @ -7,10 +7,6 @@ import ( | |||
| ) | ||||
| 
 | ||||
| func TestPathMapper(t *testing.T) { | ||||
| 	pm := &pathMapper{ | ||||
| 		root: "/pathmapper-test", | ||||
| 	} | ||||
| 
 | ||||
| 	for _, testcase := range []struct { | ||||
| 		spec     pathSpec | ||||
| 		expected string | ||||
|  | @ -21,14 +17,14 @@ func TestPathMapper(t *testing.T) { | |||
| 				name:     "foo/bar", | ||||
| 				revision: "sha256:abcdef0123456789", | ||||
| 			}, | ||||
| 			expected: "/pathmapper-test/repositories/foo/bar/_manifests/revisions/sha256/abcdef0123456789", | ||||
| 			expected: "/docker/registry/v2/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", | ||||
| 			expected: "/docker/registry/v2/repositories/foo/bar/_manifests/revisions/sha256/abcdef0123456789/link", | ||||
| 		}, | ||||
| 		{ | ||||
| 			spec: manifestSignatureLinkPathSpec{ | ||||
|  | @ -36,41 +32,41 @@ func TestPathMapper(t *testing.T) { | |||
| 				revision:  "sha256:abcdef0123456789", | ||||
| 				signature: "sha256:abcdef0123456789", | ||||
| 			}, | ||||
| 			expected: "/pathmapper-test/repositories/foo/bar/_manifests/revisions/sha256/abcdef0123456789/signatures/sha256/abcdef0123456789/link", | ||||
| 			expected: "/docker/registry/v2/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", | ||||
| 			expected: "/docker/registry/v2/repositories/foo/bar/_manifests/revisions/sha256/abcdef0123456789/signatures", | ||||
| 		}, | ||||
| 		{ | ||||
| 			spec: manifestTagsPathSpec{ | ||||
| 				name: "foo/bar", | ||||
| 			}, | ||||
| 			expected: "/pathmapper-test/repositories/foo/bar/_manifests/tags", | ||||
| 			expected: "/docker/registry/v2/repositories/foo/bar/_manifests/tags", | ||||
| 		}, | ||||
| 		{ | ||||
| 			spec: manifestTagPathSpec{ | ||||
| 				name: "foo/bar", | ||||
| 				tag:  "thetag", | ||||
| 			}, | ||||
| 			expected: "/pathmapper-test/repositories/foo/bar/_manifests/tags/thetag", | ||||
| 			expected: "/docker/registry/v2/repositories/foo/bar/_manifests/tags/thetag", | ||||
| 		}, | ||||
| 		{ | ||||
| 			spec: manifestTagCurrentPathSpec{ | ||||
| 				name: "foo/bar", | ||||
| 				tag:  "thetag", | ||||
| 			}, | ||||
| 			expected: "/pathmapper-test/repositories/foo/bar/_manifests/tags/thetag/current/link", | ||||
| 			expected: "/docker/registry/v2/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", | ||||
| 			expected: "/docker/registry/v2/repositories/foo/bar/_manifests/tags/thetag/index", | ||||
| 		}, | ||||
| 		{ | ||||
| 			spec: manifestTagIndexEntryPathSpec{ | ||||
|  | @ -78,7 +74,7 @@ func TestPathMapper(t *testing.T) { | |||
| 				tag:      "thetag", | ||||
| 				revision: "sha256:abcdef0123456789", | ||||
| 			}, | ||||
| 			expected: "/pathmapper-test/repositories/foo/bar/_manifests/tags/thetag/index/sha256/abcdef0123456789", | ||||
| 			expected: "/docker/registry/v2/repositories/foo/bar/_manifests/tags/thetag/index/sha256/abcdef0123456789", | ||||
| 		}, | ||||
| 		{ | ||||
| 			spec: manifestTagIndexEntryLinkPathSpec{ | ||||
|  | @ -86,26 +82,26 @@ func TestPathMapper(t *testing.T) { | |||
| 				tag:      "thetag", | ||||
| 				revision: "sha256:abcdef0123456789", | ||||
| 			}, | ||||
| 			expected: "/pathmapper-test/repositories/foo/bar/_manifests/tags/thetag/index/sha256/abcdef0123456789/link", | ||||
| 			expected: "/docker/registry/v2/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", | ||||
| 			expected: "/docker/registry/v2/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", | ||||
| 			expected: "/docker/registry/v2/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", | ||||
| 			expected: "/docker/registry/v2/blobs/tarsum/v1/sha256/ab/abcdefabcdefabcdef908909909/data", | ||||
| 		}, | ||||
| 
 | ||||
| 		{ | ||||
|  | @ -113,17 +109,17 @@ func TestPathMapper(t *testing.T) { | |||
| 				name: "foo/bar", | ||||
| 				id:   "asdf-asdf-asdf-adsf", | ||||
| 			}, | ||||
| 			expected: "/pathmapper-test/repositories/foo/bar/_uploads/asdf-asdf-asdf-adsf/data", | ||||
| 			expected: "/docker/registry/v2/repositories/foo/bar/_uploads/asdf-asdf-asdf-adsf/data", | ||||
| 		}, | ||||
| 		{ | ||||
| 			spec: uploadStartedAtPathSpec{ | ||||
| 				name: "foo/bar", | ||||
| 				id:   "asdf-asdf-asdf-adsf", | ||||
| 			}, | ||||
| 			expected: "/pathmapper-test/repositories/foo/bar/_uploads/asdf-asdf-asdf-adsf/startedat", | ||||
| 			expected: "/docker/registry/v2/repositories/foo/bar/_uploads/asdf-asdf-asdf-adsf/startedat", | ||||
| 		}, | ||||
| 	} { | ||||
| 		p, err := pm.path(testcase.spec) | ||||
| 		p, err := pathFor(testcase.spec) | ||||
| 		if err != nil { | ||||
| 			t.Fatalf("unexpected generating path (%T): %v", testcase.spec, err) | ||||
| 		} | ||||
|  | @ -136,9 +132,10 @@ func TestPathMapper(t *testing.T) { | |||
| 	// 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{ | ||||
| 	badpath, err := pathFor(manifestSignaturesPathSpec{ | ||||
| 		name: "foo/bar", | ||||
| 	}) | ||||
| 
 | ||||
| 	if err == nil { | ||||
| 		t.Fatalf("expected an error when mapping an invalid revision: %s", badpath) | ||||
| 	} | ||||
|  |  | |||
|  | @ -62,10 +62,11 @@ func getOutstandingUploads(ctx context.Context, driver storageDriver.StorageDriv | |||
| 	uploads := make(map[string]uploadData, 0) | ||||
| 
 | ||||
| 	inUploadDir := false | ||||
| 	root, err := defaultPathMapper.path(repositoriesRootPathSpec{}) | ||||
| 	root, err := pathFor(repositoriesRootPathSpec{}) | ||||
| 	if err != nil { | ||||
| 		return uploads, append(errors, err) | ||||
| 	} | ||||
| 
 | ||||
| 	err = Walk(ctx, driver, root, func(fileInfo storageDriver.FileInfo) error { | ||||
| 		filePath := fileInfo.Path() | ||||
| 		_, file := path.Split(filePath) | ||||
|  |  | |||
|  | @ -12,8 +12,6 @@ import ( | |||
| 	"github.com/docker/distribution/uuid" | ||||
| ) | ||||
| 
 | ||||
| var pm = defaultPathMapper | ||||
| 
 | ||||
| func testUploadFS(t *testing.T, numUploads int, repoName string, startedAt time.Time) (driver.StorageDriver, context.Context) { | ||||
| 	d := inmemory.New() | ||||
| 	ctx := context.Background() | ||||
|  | @ -24,7 +22,7 @@ func testUploadFS(t *testing.T, numUploads int, repoName string, startedAt time. | |||
| } | ||||
| 
 | ||||
| func addUploads(ctx context.Context, t *testing.T, d driver.StorageDriver, uploadID, repo string, startedAt time.Time) { | ||||
| 	dataPath, err := pm.path(uploadDataPathSpec{name: repo, id: uploadID}) | ||||
| 	dataPath, err := pathFor(uploadDataPathSpec{name: repo, id: uploadID}) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("Unable to resolve path") | ||||
| 	} | ||||
|  | @ -32,7 +30,7 @@ func addUploads(ctx context.Context, t *testing.T, d driver.StorageDriver, uploa | |||
| 		t.Fatalf("Unable to write data file") | ||||
| 	} | ||||
| 
 | ||||
| 	startedAtPath, err := pm.path(uploadStartedAtPathSpec{name: repo, id: uploadID}) | ||||
| 	startedAtPath, err := pathFor(uploadStartedAtPathSpec{name: repo, id: uploadID}) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("Unable to resolve path") | ||||
| 	} | ||||
|  | @ -115,7 +113,7 @@ func TestPurgeOnlyUploads(t *testing.T) { | |||
| 
 | ||||
| 	// Create a directory tree outside _uploads and ensure
 | ||||
| 	// these files aren't deleted.
 | ||||
| 	dataPath, err := pm.path(uploadDataPathSpec{name: "test-repo", id: uuid.Generate().String()}) | ||||
| 	dataPath, err := pathFor(uploadDataPathSpec{name: "test-repo", id: uuid.Generate().String()}) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf(err.Error()) | ||||
| 	} | ||||
|  |  | |||
|  | @ -30,7 +30,6 @@ func NewRegistryWithDriver(ctx context.Context, driver storagedriver.StorageDriv | |||
| 	// create global statter, with cache.
 | ||||
| 	var statter distribution.BlobDescriptorService = &blobStatter{ | ||||
| 		driver: driver, | ||||
| 		pm:     defaultPathMapper, | ||||
| 	} | ||||
| 
 | ||||
| 	if blobDescriptorCacheProvider != nil { | ||||
|  | @ -39,7 +38,6 @@ func NewRegistryWithDriver(ctx context.Context, driver storagedriver.StorageDriv | |||
| 
 | ||||
| 	bs := &blobStore{ | ||||
| 		driver:  driver, | ||||
| 		pm:      defaultPathMapper, | ||||
| 		statter: statter, | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
|  | @ -26,7 +26,7 @@ func newSignatureStore(ctx context.Context, repo *repository, blobStore *blobSto | |||
| var _ distribution.SignatureService = &signatureStore{} | ||||
| 
 | ||||
| func (s *signatureStore) Get(dgst digest.Digest) ([][]byte, error) { | ||||
| 	signaturesPath, err := s.blobStore.pm.path(manifestSignaturesPathSpec{ | ||||
| 	signaturesPath, err := pathFor(manifestSignaturesPathSpec{ | ||||
| 		name:     s.repository.Name(), | ||||
| 		revision: dgst, | ||||
| 	}) | ||||
|  | @ -119,12 +119,13 @@ func (s *signatureStore) Put(dgst digest.Digest, signatures ...[]byte) error { | |||
| // manifest with the given digest. Effectively, each signature link path
 | ||||
| // layout is a unique linked blob store.
 | ||||
| func (s *signatureStore) linkedBlobStore(ctx context.Context, revision digest.Digest) *linkedBlobStore { | ||||
| 	linkpath := func(pm *pathMapper, name string, dgst digest.Digest) (string, error) { | ||||
| 		return pm.path(manifestSignatureLinkPathSpec{ | ||||
| 	linkpath := func(name string, dgst digest.Digest) (string, error) { | ||||
| 		return pathFor(manifestSignatureLinkPathSpec{ | ||||
| 			name:      name, | ||||
| 			revision:  revision, | ||||
| 			signature: dgst, | ||||
| 		}) | ||||
| 
 | ||||
| 	} | ||||
| 
 | ||||
| 	return &linkedBlobStore{ | ||||
|  |  | |||
|  | @ -18,9 +18,10 @@ type tagStore struct { | |||
| 
 | ||||
| // tags lists the manifest tags for the specified repository.
 | ||||
| func (ts *tagStore) tags() ([]string, error) { | ||||
| 	p, err := ts.blobStore.pm.path(manifestTagPathSpec{ | ||||
| 	p, err := pathFor(manifestTagPathSpec{ | ||||
| 		name: ts.repository.Name(), | ||||
| 	}) | ||||
| 
 | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | @ -47,10 +48,11 @@ func (ts *tagStore) tags() ([]string, error) { | |||
| 
 | ||||
| // exists returns true if the specified manifest tag exists in the repository.
 | ||||
| func (ts *tagStore) exists(tag string) (bool, error) { | ||||
| 	tagPath, err := ts.blobStore.pm.path(manifestTagCurrentPathSpec{ | ||||
| 	tagPath, err := pathFor(manifestTagCurrentPathSpec{ | ||||
| 		name: ts.repository.Name(), | ||||
| 		tag:  tag, | ||||
| 	}) | ||||
| 
 | ||||
| 	if err != nil { | ||||
| 		return false, err | ||||
| 	} | ||||
|  | @ -66,7 +68,7 @@ func (ts *tagStore) exists(tag string) (bool, error) { | |||
| // tag tags the digest with the given tag, updating the the store to point at
 | ||||
| // the current tag. The digest must point to a manifest.
 | ||||
| func (ts *tagStore) tag(tag string, revision digest.Digest) error { | ||||
| 	currentPath, err := ts.blobStore.pm.path(manifestTagCurrentPathSpec{ | ||||
| 	currentPath, err := pathFor(manifestTagCurrentPathSpec{ | ||||
| 		name: ts.repository.Name(), | ||||
| 		tag:  tag, | ||||
| 	}) | ||||
|  | @ -87,10 +89,11 @@ func (ts *tagStore) tag(tag string, revision digest.Digest) error { | |||
| 
 | ||||
| // resolve the current revision for name and tag.
 | ||||
| func (ts *tagStore) resolve(tag string) (digest.Digest, error) { | ||||
| 	currentPath, err := ts.blobStore.pm.path(manifestTagCurrentPathSpec{ | ||||
| 	currentPath, err := pathFor(manifestTagCurrentPathSpec{ | ||||
| 		name: ts.repository.Name(), | ||||
| 		tag:  tag, | ||||
| 	}) | ||||
| 
 | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
|  | @ -111,10 +114,11 @@ func (ts *tagStore) resolve(tag string) (digest.Digest, error) { | |||
| // delete removes the tag from repository, including the history of all
 | ||||
| // revisions that have the specified tag.
 | ||||
| func (ts *tagStore) delete(tag string) error { | ||||
| 	tagPath, err := ts.blobStore.pm.path(manifestTagPathSpec{ | ||||
| 	tagPath, err := pathFor(manifestTagPathSpec{ | ||||
| 		name: ts.repository.Name(), | ||||
| 		tag:  tag, | ||||
| 	}) | ||||
| 
 | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | @ -131,12 +135,13 @@ func (ts *tagStore) linkedBlobStore(ctx context.Context, tag string) *linkedBlob | |||
| 		blobStore:  ts.blobStore, | ||||
| 		repository: ts.repository, | ||||
| 		ctx:        ctx, | ||||
| 		linkPathFns: []linkPathFunc{func(pm *pathMapper, name string, dgst digest.Digest) (string, error) { | ||||
| 			return pm.path(manifestTagIndexEntryLinkPathSpec{ | ||||
| 		linkPathFns: []linkPathFunc{func(name string, dgst digest.Digest) (string, error) { | ||||
| 			return pathFor(manifestTagIndexEntryLinkPathSpec{ | ||||
| 				name:     name, | ||||
| 				tag:      tag, | ||||
| 				revision: dgst, | ||||
| 			}) | ||||
| 
 | ||||
| 		}}, | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -18,13 +18,11 @@ func NewVacuum(ctx context.Context, driver driver.StorageDriver) Vacuum { | |||
| 	return Vacuum{ | ||||
| 		ctx:    ctx, | ||||
| 		driver: driver, | ||||
| 		pm:     defaultPathMapper, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Vacuum removes content from the filesystem
 | ||||
| type Vacuum struct { | ||||
| 	pm     *pathMapper | ||||
| 	driver driver.StorageDriver | ||||
| 	ctx    context.Context | ||||
| } | ||||
|  | @ -36,7 +34,7 @@ func (v Vacuum) RemoveBlob(dgst string) error { | |||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	blobPath, err := v.pm.path(blobDataPathSpec{digest: d}) | ||||
| 	blobPath, err := pathFor(blobDataPathSpec{digest: d}) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | @ -52,7 +50,7 @@ func (v Vacuum) RemoveBlob(dgst string) error { | |||
| // RemoveRepository removes a repository directory from the
 | ||||
| // filesystem
 | ||||
| func (v Vacuum) RemoveRepository(repoName string) error { | ||||
| 	rootForRepository, err := v.pm.path(repositoriesRootPathSpec{}) | ||||
| 	rootForRepository, err := pathFor(repositoriesRootPathSpec{}) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue