Merge pull request #3061 from guillaumerose/reconciliate
Add pathspec for repo _layers directory and allow Repository.BlobStore to enumerate over blobs
This commit is contained in:
commit
f18781257e
4 changed files with 64 additions and 0 deletions
|
@ -5,6 +5,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
@ -14,6 +15,54 @@ import (
|
||||||
"github.com/opencontainers/go-digest"
|
"github.com/opencontainers/go-digest"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestLinkedBlobStoreEnumerator(t *testing.T) {
|
||||||
|
fooRepoName, _ := reference.WithName("nm/foo")
|
||||||
|
fooEnv := newManifestStoreTestEnv(t, fooRepoName, "thetag")
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
var expected []string
|
||||||
|
for i := 0; i < 2; i++ {
|
||||||
|
rs, dgst, err := testutil.CreateRandomTarFile()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error generating test layer file")
|
||||||
|
}
|
||||||
|
|
||||||
|
expected = append(expected, dgst.String())
|
||||||
|
|
||||||
|
wr, err := fooEnv.repository.Blobs(fooEnv.ctx).Create(fooEnv.ctx)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error creating test upload: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := io.Copy(wr, rs); err != nil {
|
||||||
|
t.Fatalf("unexpected error copying to upload: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := wr.Commit(fooEnv.ctx, distribution.Descriptor{Digest: dgst}); err != nil {
|
||||||
|
t.Fatalf("unexpected error finishing upload: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enumerator, ok := fooEnv.repository.Blobs(fooEnv.ctx).(distribution.BlobEnumerator)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("Blobs is not a BlobEnumerator")
|
||||||
|
}
|
||||||
|
|
||||||
|
var actual []string
|
||||||
|
if err := enumerator.Enumerate(ctx, func(dgst digest.Digest) error {
|
||||||
|
actual = append(actual, dgst.String())
|
||||||
|
return nil
|
||||||
|
}); err != nil {
|
||||||
|
t.Fatalf("cannot enumerate on repository: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Strings(actual)
|
||||||
|
sort.Strings(expected)
|
||||||
|
if !reflect.DeepEqual(expected, actual) {
|
||||||
|
t.Fatalf("unexpected array difference (expected: %v actual: %v)", expected, actual)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestLinkedBlobStoreCreateWithMountFrom(t *testing.T) {
|
func TestLinkedBlobStoreCreateWithMountFrom(t *testing.T) {
|
||||||
fooRepoName, _ := reference.WithName("nm/foo")
|
fooRepoName, _ := reference.WithName("nm/foo")
|
||||||
fooEnv := newManifestStoreTestEnv(t, fooRepoName, "thetag")
|
fooEnv := newManifestStoreTestEnv(t, fooRepoName, "thetag")
|
||||||
|
|
|
@ -87,6 +87,7 @@ const (
|
||||||
// Blobs:
|
// Blobs:
|
||||||
//
|
//
|
||||||
// layerLinkPathSpec: <root>/v2/repositories/<name>/_layers/<algorithm>/<hex digest>/link
|
// layerLinkPathSpec: <root>/v2/repositories/<name>/_layers/<algorithm>/<hex digest>/link
|
||||||
|
// layersPathSpec: <root>/v2/repositories/<name>/_layers
|
||||||
//
|
//
|
||||||
// Uploads:
|
// Uploads:
|
||||||
//
|
//
|
||||||
|
@ -206,6 +207,8 @@ func pathFor(spec pathSpec) (string, error) {
|
||||||
blobLinkPathComponents := append(repoPrefix, v.name, "_layers")
|
blobLinkPathComponents := append(repoPrefix, v.name, "_layers")
|
||||||
|
|
||||||
return path.Join(path.Join(append(blobLinkPathComponents, components...)...), "link"), nil
|
return path.Join(path.Join(append(blobLinkPathComponents, components...)...), "link"), nil
|
||||||
|
case layersPathSpec:
|
||||||
|
return path.Join(append(repoPrefix, v.name, "_layers")...), nil
|
||||||
case blobsPathSpec:
|
case blobsPathSpec:
|
||||||
blobsPathPrefix := append(rootPrefix, "blobs")
|
blobsPathPrefix := append(rootPrefix, "blobs")
|
||||||
return path.Join(blobsPathPrefix...), nil
|
return path.Join(blobsPathPrefix...), nil
|
||||||
|
@ -335,6 +338,13 @@ type manifestTagIndexEntryLinkPathSpec struct {
|
||||||
|
|
||||||
func (manifestTagIndexEntryLinkPathSpec) pathSpec() {}
|
func (manifestTagIndexEntryLinkPathSpec) pathSpec() {}
|
||||||
|
|
||||||
|
// layersPathSpec contains the path for the layers inside a repo
|
||||||
|
type layersPathSpec struct {
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (layersPathSpec) pathSpec() {}
|
||||||
|
|
||||||
// blobLinkPathSpec specifies a path for a blob link, which is a file with a
|
// blobLinkPathSpec specifies a path for a blob link, which is a file with a
|
||||||
// blob id. The blob link will contain a content addressable blob id reference
|
// blob id. The blob link will contain a content addressable blob id reference
|
||||||
// into the blob store. The format of the contents is as follows:
|
// into the blob store. The format of the contents is as follows:
|
||||||
|
|
|
@ -83,6 +83,10 @@ func TestPathMapper(t *testing.T) {
|
||||||
},
|
},
|
||||||
expected: "/docker/registry/v2/repositories/foo/bar/_uploads/asdf-asdf-asdf-adsf/startedat",
|
expected: "/docker/registry/v2/repositories/foo/bar/_uploads/asdf-asdf-asdf-adsf/startedat",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
spec: layersPathSpec{name: "foo/bar"},
|
||||||
|
expected: "/docker/registry/v2/repositories/foo/bar/_layers",
|
||||||
|
},
|
||||||
} {
|
} {
|
||||||
p, err := pathFor(testcase.spec)
|
p, err := pathFor(testcase.spec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -330,6 +330,7 @@ func (repo *repository) Blobs(ctx context.Context) distribution.BlobStore {
|
||||||
// TODO(stevvooe): linkPath limits this blob store to only layers.
|
// TODO(stevvooe): linkPath limits this blob store to only layers.
|
||||||
// This instance cannot be used for manifest checks.
|
// This instance cannot be used for manifest checks.
|
||||||
linkPathFns: []linkPathFunc{blobLinkPath},
|
linkPathFns: []linkPathFunc{blobLinkPath},
|
||||||
|
linkDirectoryPathSpec: layersPathSpec{name: repo.name.Name()},
|
||||||
deleteEnabled: repo.registry.deleteEnabled,
|
deleteEnabled: repo.registry.deleteEnabled,
|
||||||
resumableDigestEnabled: repo.resumableDigestEnabled,
|
resumableDigestEnabled: repo.resumableDigestEnabled,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue