mirror of
https://github.com/distribution/distribution.git
synced 2025-09-26 06:40:12 +00:00
replace uses of Descriptor alias
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
@@ -16,6 +16,7 @@ import (
|
||||
"github.com/distribution/distribution/v3/testutil"
|
||||
"github.com/distribution/reference"
|
||||
"github.com/opencontainers/go-digest"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
// TestWriteSeek tests that the current file size can be
|
||||
@@ -133,7 +134,7 @@ func TestSimpleBlobUpload(t *testing.T) {
|
||||
}
|
||||
|
||||
sha256Digest := digest.NewDigest("sha256", h)
|
||||
desc, err := blobUpload.Commit(ctx, distribution.Descriptor{Digest: dgst})
|
||||
desc, err := blobUpload.Commit(ctx, v1.Descriptor{Digest: dgst})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error finishing layer upload: %v", err)
|
||||
}
|
||||
@@ -285,7 +286,7 @@ func TestSimpleBlobRead(t *testing.T) {
|
||||
t.Fatalf("error getting seeker size for random layer: %v", err)
|
||||
}
|
||||
|
||||
descBefore := distribution.Descriptor{Digest: dgst, MediaType: "application/octet-stream", Size: randomLayerSize}
|
||||
descBefore := v1.Descriptor{Digest: dgst, MediaType: "application/octet-stream", Size: randomLayerSize}
|
||||
t.Logf("desc: %v", descBefore)
|
||||
|
||||
desc, err = addBlob(ctx, bs, descBefore, randomLayerReader)
|
||||
@@ -398,7 +399,7 @@ func TestBlobMount(t *testing.T) {
|
||||
t.Fatalf("unexpected error uploading layer data: %v", err)
|
||||
}
|
||||
|
||||
desc, err := blobUpload.Commit(ctx, distribution.Descriptor{Digest: dgst})
|
||||
desc, err := blobUpload.Commit(ctx, v1.Descriptor{Digest: dgst})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error finishing layer upload: %v", err)
|
||||
}
|
||||
@@ -555,7 +556,7 @@ func simpleUpload(t *testing.T, bs distribution.BlobIngester, blob []byte, expec
|
||||
t.Fatalf("digest not as expected: %v != %v", dgst, expectedDigest)
|
||||
}
|
||||
|
||||
desc, err := wr.Commit(ctx, distribution.Descriptor{Digest: dgst})
|
||||
desc, err := wr.Commit(ctx, v1.Descriptor{Digest: dgst})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error committing write: %v", err)
|
||||
}
|
||||
@@ -593,18 +594,18 @@ func seekerSize(seeker io.ReadSeeker) (int64, error) {
|
||||
|
||||
// addBlob simply consumes the reader and inserts into the blob service,
|
||||
// returning a descriptor on success.
|
||||
func addBlob(ctx context.Context, bs distribution.BlobIngester, desc distribution.Descriptor, rd io.Reader) (distribution.Descriptor, error) {
|
||||
func addBlob(ctx context.Context, bs distribution.BlobIngester, desc v1.Descriptor, rd io.Reader) (v1.Descriptor, error) {
|
||||
wr, err := bs.Create(ctx)
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
// nolint:errcheck
|
||||
defer wr.Cancel(ctx)
|
||||
|
||||
if nn, err := io.Copy(wr, rd); err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
} else if nn != desc.Size {
|
||||
return distribution.Descriptor{}, fmt.Errorf("incorrect number of bytes copied: %v != %v", nn, desc.Size)
|
||||
return v1.Descriptor{}, fmt.Errorf("incorrect number of bytes copied: %v != %v", nn, desc.Size)
|
||||
}
|
||||
|
||||
return wr.Commit(ctx, desc)
|
||||
|
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/distribution/distribution/v3/internal/dcontext"
|
||||
"github.com/distribution/distribution/v3/registry/storage/driver"
|
||||
"github.com/opencontainers/go-digest"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
// blobStore implements the read side of the blob store interface over a
|
||||
@@ -59,7 +60,7 @@ func (bs *blobStore) Open(ctx context.Context, dgst digest.Digest) (io.ReadSeekC
|
||||
// Put stores the content p in the blob store, calculating the digest. If the
|
||||
// content is already present, only the digest will be returned. This should
|
||||
// only be used for small objects, such as manifests. This implemented as a convenience for other Put implementations
|
||||
func (bs *blobStore) Put(ctx context.Context, mediaType string, p []byte) (distribution.Descriptor, error) {
|
||||
func (bs *blobStore) Put(ctx context.Context, mediaType string, p []byte) (v1.Descriptor, error) {
|
||||
dgst := digest.FromBytes(p)
|
||||
desc, err := bs.statter.Stat(ctx, dgst)
|
||||
if err == nil {
|
||||
@@ -68,16 +69,16 @@ func (bs *blobStore) Put(ctx context.Context, mediaType string, p []byte) (distr
|
||||
} else if err != distribution.ErrBlobUnknown {
|
||||
dcontext.GetLogger(ctx).Errorf("blobStore: error stating content (%v): %v", dgst, err)
|
||||
// real error, return it
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
|
||||
bp, err := bs.path(dgst)
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
|
||||
// TODO(stevvooe): Write out mediatype here, as well.
|
||||
return distribution.Descriptor{
|
||||
return v1.Descriptor{
|
||||
Size: int64(len(p)),
|
||||
|
||||
// NOTE(stevvooe): The central blob store firewalls media types from
|
||||
@@ -161,21 +162,21 @@ var _ distribution.BlobDescriptorService = &blobStatter{}
|
||||
// Stat implements BlobStatter.Stat by returning the descriptor for the blob
|
||||
// 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) {
|
||||
func (bs *blobStatter) Stat(ctx context.Context, dgst digest.Digest) (v1.Descriptor, error) {
|
||||
path, err := pathFor(blobDataPathSpec{
|
||||
digest: dgst,
|
||||
})
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
|
||||
fi, err := bs.driver.Stat(ctx, path)
|
||||
if err != nil {
|
||||
switch err := err.(type) {
|
||||
case driver.PathNotFoundError:
|
||||
return distribution.Descriptor{}, distribution.ErrBlobUnknown
|
||||
return v1.Descriptor{}, distribution.ErrBlobUnknown
|
||||
default:
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,14 +185,14 @@ func (bs *blobStatter) Stat(ctx context.Context, dgst digest.Digest) (distributi
|
||||
// calculated a blob path and then detected a directory. We log the
|
||||
// error and then error on the side of not knowing about the blob.
|
||||
dcontext.GetLogger(ctx).Warnf("blob path should not be a directory: %q", path)
|
||||
return distribution.Descriptor{}, distribution.ErrBlobUnknown
|
||||
return v1.Descriptor{}, distribution.ErrBlobUnknown
|
||||
}
|
||||
|
||||
// TODO(stevvooe): Add method to resolve the mediatype. We can store and
|
||||
// cache a "global" media type for the blob, even if a specific repo has a
|
||||
// mediatype that overrides the main one.
|
||||
|
||||
return distribution.Descriptor{
|
||||
return v1.Descriptor{
|
||||
Size: fi.Size(),
|
||||
|
||||
// NOTE(stevvooe): The central blob store firewalls media types from
|
||||
@@ -206,6 +207,6 @@ func (bs *blobStatter) Clear(ctx context.Context, dgst digest.Digest) error {
|
||||
return distribution.ErrUnsupported
|
||||
}
|
||||
|
||||
func (bs *blobStatter) SetDescriptor(ctx context.Context, dgst digest.Digest, desc distribution.Descriptor) error {
|
||||
func (bs *blobStatter) SetDescriptor(ctx context.Context, dgst digest.Digest, desc v1.Descriptor) error {
|
||||
return distribution.ErrUnsupported
|
||||
}
|
||||
|
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/distribution/distribution/v3/internal/dcontext"
|
||||
storagedriver "github.com/distribution/distribution/v3/registry/storage/driver"
|
||||
"github.com/opencontainers/go-digest"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
@@ -54,11 +55,11 @@ func (bw *blobWriter) StartedAt() time.Time {
|
||||
|
||||
// Commit marks the upload as completed, returning a valid descriptor. The
|
||||
// final size and digest are checked against the first descriptor provided.
|
||||
func (bw *blobWriter) Commit(ctx context.Context, desc distribution.Descriptor) (distribution.Descriptor, error) {
|
||||
func (bw *blobWriter) Commit(ctx context.Context, desc v1.Descriptor) (v1.Descriptor, error) {
|
||||
dcontext.GetLogger(ctx).Debug("(*blobWriter).Commit")
|
||||
|
||||
if err := bw.fileWriter.Commit(ctx); err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
|
||||
bw.Close()
|
||||
@@ -66,24 +67,24 @@ func (bw *blobWriter) Commit(ctx context.Context, desc distribution.Descriptor)
|
||||
|
||||
canonical, err := bw.validateBlob(ctx, desc)
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
|
||||
if err := bw.moveBlob(ctx, canonical); err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
|
||||
if err := bw.blobStore.linkBlob(ctx, canonical, desc.Digest); err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
|
||||
if err := bw.removeResources(ctx); err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
|
||||
err = bw.blobStore.blobAccessController.SetDescriptor(ctx, canonical.Digest, canonical)
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
|
||||
bw.committed = true
|
||||
@@ -160,7 +161,7 @@ func (bw *blobWriter) Close() error {
|
||||
|
||||
// validateBlob checks the data against the digest, returning an error if it
|
||||
// does not match. The canonical descriptor is returned.
|
||||
func (bw *blobWriter) validateBlob(ctx context.Context, desc distribution.Descriptor) (distribution.Descriptor, error) {
|
||||
func (bw *blobWriter) validateBlob(ctx context.Context, desc v1.Descriptor) (v1.Descriptor, error) {
|
||||
var (
|
||||
verified, fullHash bool
|
||||
canonical digest.Digest
|
||||
@@ -169,7 +170,7 @@ func (bw *blobWriter) validateBlob(ctx context.Context, desc distribution.Descri
|
||||
if desc.Digest == "" {
|
||||
// if no descriptors are provided, we have nothing to validate
|
||||
// against. We don't really want to support this for the registry.
|
||||
return distribution.Descriptor{}, distribution.ErrBlobInvalidDigest{
|
||||
return v1.Descriptor{}, distribution.ErrBlobInvalidDigest{
|
||||
Reason: fmt.Errorf("cannot validate against empty digest"),
|
||||
}
|
||||
}
|
||||
@@ -186,11 +187,11 @@ func (bw *blobWriter) validateBlob(ctx context.Context, desc distribution.Descri
|
||||
desc.Size = 0
|
||||
default:
|
||||
// Any other error we want propagated up the stack.
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
} else {
|
||||
if fi.IsDir() {
|
||||
return distribution.Descriptor{}, fmt.Errorf("unexpected directory at upload location %q", bw.path)
|
||||
return v1.Descriptor{}, fmt.Errorf("unexpected directory at upload location %q", bw.path)
|
||||
}
|
||||
|
||||
size = fi.Size()
|
||||
@@ -198,7 +199,7 @@ func (bw *blobWriter) validateBlob(ctx context.Context, desc distribution.Descri
|
||||
|
||||
if desc.Size > 0 {
|
||||
if desc.Size != size {
|
||||
return distribution.Descriptor{}, distribution.ErrBlobInvalidLength
|
||||
return v1.Descriptor{}, distribution.ErrBlobInvalidLength
|
||||
}
|
||||
} else {
|
||||
// if provided 0 or negative length, we can assume caller doesn't know or
|
||||
@@ -226,7 +227,7 @@ func (bw *blobWriter) validateBlob(ctx context.Context, desc distribution.Descri
|
||||
// Not using resumable digests, so we need to hash the entire layer.
|
||||
fullHash = true
|
||||
} else {
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
|
||||
if fullHash {
|
||||
@@ -249,14 +250,14 @@ func (bw *blobWriter) validateBlob(ctx context.Context, desc distribution.Descri
|
||||
// Read the file from the backend driver and validate it.
|
||||
fr, err := newFileReader(ctx, bw.driver, bw.path, desc.Size)
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
defer fr.Close()
|
||||
|
||||
tr := io.TeeReader(fr, digester.Hash())
|
||||
|
||||
if _, err := io.Copy(verifier, tr); err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
|
||||
canonical = digester.Digest()
|
||||
@@ -271,7 +272,7 @@ func (bw *blobWriter) validateBlob(ctx context.Context, desc distribution.Descri
|
||||
"provided": desc.Digest,
|
||||
}, "canonical", "provided").
|
||||
Errorf("canonical digest does match provided digest")
|
||||
return distribution.Descriptor{}, distribution.ErrBlobInvalidDigest{
|
||||
return v1.Descriptor{}, distribution.ErrBlobInvalidDigest{
|
||||
Digest: desc.Digest,
|
||||
Reason: fmt.Errorf("content does not match digest"),
|
||||
}
|
||||
@@ -290,7 +291,7 @@ func (bw *blobWriter) validateBlob(ctx context.Context, desc distribution.Descri
|
||||
// moveBlob moves the data into its final, hash-qualified destination,
|
||||
// identified by dgst. The layer should be validated before commencing the
|
||||
// move.
|
||||
func (bw *blobWriter) moveBlob(ctx context.Context, desc distribution.Descriptor) error {
|
||||
func (bw *blobWriter) moveBlob(ctx context.Context, desc v1.Descriptor) error {
|
||||
blobPath, err := pathFor(blobDataPathSpec{
|
||||
digest: desc.Digest,
|
||||
})
|
||||
|
3
registry/storage/cache/cache.go
vendored
3
registry/storage/cache/cache.go
vendored
@@ -6,6 +6,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/distribution/distribution/v3"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
// BlobDescriptorCacheProvider provides repository scoped
|
||||
@@ -18,7 +19,7 @@ type BlobDescriptorCacheProvider interface {
|
||||
|
||||
// ValidateDescriptor provides a helper function to ensure that caches have
|
||||
// common criteria for admitting descriptors.
|
||||
func ValidateDescriptor(desc distribution.Descriptor) error {
|
||||
func ValidateDescriptor(desc v1.Descriptor) error {
|
||||
if err := desc.Digest.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
21
registry/storage/cache/cache_test.go
vendored
21
registry/storage/cache/cache_test.go
vendored
@@ -7,6 +7,7 @@ import (
|
||||
|
||||
"github.com/distribution/distribution/v3"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
func TestCacheSet(t *testing.T) {
|
||||
@@ -21,7 +22,7 @@ func TestCacheSet(t *testing.T) {
|
||||
t.Fatalf("Unexpected error %v, expected %v", err, distribution.ErrBlobUnknown)
|
||||
}
|
||||
|
||||
desc := distribution.Descriptor{
|
||||
desc := v1.Descriptor{
|
||||
Digest: dgst,
|
||||
}
|
||||
if err := backend.SetDescriptor(ctx, dgst, desc); err != nil {
|
||||
@@ -43,7 +44,7 @@ func TestCacheSet(t *testing.T) {
|
||||
t.Fatalf("Unexpected descriptor %v, expected %v", cache.sets[dgst][0], desc)
|
||||
}
|
||||
|
||||
desc2 := distribution.Descriptor{
|
||||
desc2 := v1.Descriptor{
|
||||
Digest: digest.Digest("dontvalidate 2"),
|
||||
}
|
||||
cache.sets[dgst] = append(cache.sets[dgst], desc2)
|
||||
@@ -69,7 +70,7 @@ func TestCacheError(t *testing.T) {
|
||||
t.Fatalf("Unexpected error %v, expected %v", err, distribution.ErrBlobUnknown)
|
||||
}
|
||||
|
||||
desc := distribution.Descriptor{
|
||||
desc := v1.Descriptor{
|
||||
Digest: dgst,
|
||||
}
|
||||
if err := backend.SetDescriptor(ctx, dgst, desc); err != nil {
|
||||
@@ -92,36 +93,36 @@ func TestCacheError(t *testing.T) {
|
||||
func newTestStatter() *testStatter {
|
||||
return &testStatter{
|
||||
stats: []digest.Digest{},
|
||||
sets: map[digest.Digest][]distribution.Descriptor{},
|
||||
sets: map[digest.Digest][]v1.Descriptor{},
|
||||
}
|
||||
}
|
||||
|
||||
func newErrTestStatter(err error) *testStatter {
|
||||
return &testStatter{
|
||||
sets: map[digest.Digest][]distribution.Descriptor{},
|
||||
sets: map[digest.Digest][]v1.Descriptor{},
|
||||
err: err,
|
||||
}
|
||||
}
|
||||
|
||||
type testStatter struct {
|
||||
stats []digest.Digest
|
||||
sets map[digest.Digest][]distribution.Descriptor
|
||||
sets map[digest.Digest][]v1.Descriptor
|
||||
err error
|
||||
}
|
||||
|
||||
func (s *testStatter) Stat(ctx context.Context, dgst digest.Digest) (distribution.Descriptor, error) {
|
||||
func (s *testStatter) Stat(ctx context.Context, dgst digest.Digest) (v1.Descriptor, error) {
|
||||
if s.err != nil {
|
||||
return distribution.Descriptor{}, s.err
|
||||
return v1.Descriptor{}, s.err
|
||||
}
|
||||
|
||||
if set := s.sets[dgst]; len(set) > 0 {
|
||||
return set[len(set)-1], nil
|
||||
}
|
||||
|
||||
return distribution.Descriptor{}, distribution.ErrBlobUnknown
|
||||
return v1.Descriptor{}, distribution.ErrBlobUnknown
|
||||
}
|
||||
|
||||
func (s *testStatter) SetDescriptor(ctx context.Context, dgst digest.Digest, desc distribution.Descriptor) error {
|
||||
func (s *testStatter) SetDescriptor(ctx context.Context, dgst digest.Digest, desc v1.Descriptor) error {
|
||||
s.sets[dgst] = append(s.sets[dgst], desc)
|
||||
return s.err
|
||||
}
|
||||
|
9
registry/storage/cache/cachecheck/suite.go
vendored
9
registry/storage/cache/cachecheck/suite.go
vendored
@@ -8,6 +8,7 @@ import (
|
||||
"github.com/distribution/distribution/v3"
|
||||
"github.com/distribution/distribution/v3/registry/storage/cache"
|
||||
"github.com/opencontainers/go-digest"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
// CheckBlobDescriptorCache takes a cache implementation through a common set
|
||||
@@ -36,7 +37,7 @@ func checkBlobDescriptorCacheEmptyRepository(ctx context.Context, t *testing.T,
|
||||
t.Fatalf("unexpected error getting repository: %v", err)
|
||||
}
|
||||
|
||||
if err := cache.SetDescriptor(ctx, "", distribution.Descriptor{
|
||||
if err := cache.SetDescriptor(ctx, "", v1.Descriptor{
|
||||
Digest: "sha384:abc",
|
||||
Size: 10,
|
||||
MediaType: "application/octet-stream",
|
||||
@@ -44,7 +45,7 @@ func checkBlobDescriptorCacheEmptyRepository(ctx context.Context, t *testing.T,
|
||||
t.Fatalf("expected error with invalid digest: %v", err)
|
||||
}
|
||||
|
||||
if err := cache.SetDescriptor(ctx, "sha384:abc111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", distribution.Descriptor{
|
||||
if err := cache.SetDescriptor(ctx, "sha384:abc111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", v1.Descriptor{
|
||||
Digest: "",
|
||||
Size: 10,
|
||||
MediaType: "application/octet-stream",
|
||||
@@ -67,7 +68,7 @@ func checkBlobDescriptorCacheEmptyRepository(ctx context.Context, t *testing.T,
|
||||
|
||||
func checkBlobDescriptorCacheSetAndRead(ctx context.Context, t *testing.T, provider cache.BlobDescriptorCacheProvider) {
|
||||
localDigest := digest.Digest("sha384:abc111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111")
|
||||
expected := distribution.Descriptor{
|
||||
expected := v1.Descriptor{
|
||||
Digest: "sha256:abc1111111111111111111111111111111111111111111111111111111111111",
|
||||
Size: 10,
|
||||
MediaType: "application/octet-stream",
|
||||
@@ -152,7 +153,7 @@ func checkBlobDescriptorCacheSetAndRead(ctx context.Context, t *testing.T, provi
|
||||
|
||||
func checkBlobDescriptorCacheClear(ctx context.Context, t *testing.T, provider cache.BlobDescriptorCacheProvider) {
|
||||
localDigest := digest.Digest("sha384:def111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111")
|
||||
expected := distribution.Descriptor{
|
||||
expected := v1.Descriptor{
|
||||
Digest: "sha256:def1111111111111111111111111111111111111111111111111111111111111",
|
||||
Size: 10,
|
||||
MediaType: "application/octet-stream",
|
||||
|
@@ -7,6 +7,7 @@ import (
|
||||
"github.com/distribution/distribution/v3/internal/dcontext"
|
||||
prometheus "github.com/distribution/distribution/v3/metrics"
|
||||
"github.com/opencontainers/go-digest"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
type cachedBlobStatter struct {
|
||||
@@ -32,7 +33,7 @@ func NewCachedBlobStatter(cache distribution.BlobDescriptorService, backend dist
|
||||
}
|
||||
}
|
||||
|
||||
func (cbds *cachedBlobStatter) Stat(ctx context.Context, dgst digest.Digest) (distribution.Descriptor, error) {
|
||||
func (cbds *cachedBlobStatter) Stat(ctx context.Context, dgst digest.Digest) (v1.Descriptor, error) {
|
||||
cacheRequestCount.Inc(1)
|
||||
|
||||
// try getting from cache
|
||||
@@ -75,7 +76,7 @@ func (cbds *cachedBlobStatter) Clear(ctx context.Context, dgst digest.Digest) er
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cbds *cachedBlobStatter) SetDescriptor(ctx context.Context, dgst digest.Digest, desc distribution.Descriptor) error {
|
||||
func (cbds *cachedBlobStatter) SetDescriptor(ctx context.Context, dgst digest.Digest, desc v1.Descriptor) error {
|
||||
if err := cbds.cache.SetDescriptor(ctx, dgst, desc); err != nil {
|
||||
dcontext.GetLoggerWithField(ctx, "blob", dgst).WithError(err).Error("error from cache setting desc")
|
||||
}
|
||||
|
21
registry/storage/cache/memory/memory.go
vendored
21
registry/storage/cache/memory/memory.go
vendored
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/distribution/reference"
|
||||
"github.com/hashicorp/golang-lru/arc/v2"
|
||||
"github.com/opencontainers/go-digest"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -26,7 +27,7 @@ type descriptorCacheKey struct {
|
||||
}
|
||||
|
||||
type inMemoryBlobDescriptorCacheProvider struct {
|
||||
lru *arc.ARCCache[descriptorCacheKey, distribution.Descriptor]
|
||||
lru *arc.ARCCache[descriptorCacheKey, v1.Descriptor]
|
||||
}
|
||||
|
||||
// NewInMemoryBlobDescriptorCacheProvider returns a new mapped-based cache for
|
||||
@@ -35,7 +36,7 @@ func NewInMemoryBlobDescriptorCacheProvider(size int) cache.BlobDescriptorCacheP
|
||||
if size <= 0 {
|
||||
size = math.MaxInt
|
||||
}
|
||||
lruCache, err := arc.NewARC[descriptorCacheKey, distribution.Descriptor](size)
|
||||
lruCache, err := arc.NewARC[descriptorCacheKey, v1.Descriptor](size)
|
||||
if err != nil {
|
||||
// NewARC can only fail if size is <= 0, so this unreachable
|
||||
panic(err)
|
||||
@@ -62,9 +63,9 @@ func (imbdcp *inMemoryBlobDescriptorCacheProvider) RepositoryScoped(repo string)
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (imbdcp *inMemoryBlobDescriptorCacheProvider) Stat(ctx context.Context, dgst digest.Digest) (distribution.Descriptor, error) {
|
||||
func (imbdcp *inMemoryBlobDescriptorCacheProvider) Stat(ctx context.Context, dgst digest.Digest) (v1.Descriptor, error) {
|
||||
if err := dgst.Validate(); err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
|
||||
key := descriptorCacheKey{
|
||||
@@ -74,7 +75,7 @@ func (imbdcp *inMemoryBlobDescriptorCacheProvider) Stat(ctx context.Context, dgs
|
||||
if ok {
|
||||
return descriptor, nil
|
||||
}
|
||||
return distribution.Descriptor{}, distribution.ErrBlobUnknown
|
||||
return v1.Descriptor{}, distribution.ErrBlobUnknown
|
||||
}
|
||||
|
||||
func (imbdcp *inMemoryBlobDescriptorCacheProvider) Clear(ctx context.Context, dgst digest.Digest) error {
|
||||
@@ -85,7 +86,7 @@ func (imbdcp *inMemoryBlobDescriptorCacheProvider) Clear(ctx context.Context, dg
|
||||
return nil
|
||||
}
|
||||
|
||||
func (imbdcp *inMemoryBlobDescriptorCacheProvider) SetDescriptor(ctx context.Context, dgst digest.Digest, desc distribution.Descriptor) error {
|
||||
func (imbdcp *inMemoryBlobDescriptorCacheProvider) SetDescriptor(ctx context.Context, dgst digest.Digest, desc v1.Descriptor) error {
|
||||
_, err := imbdcp.Stat(ctx, dgst)
|
||||
if err == distribution.ErrBlobUnknown {
|
||||
if dgst.Algorithm() != desc.Digest.Algorithm() && dgst != desc.Digest {
|
||||
@@ -121,9 +122,9 @@ type repositoryScopedInMemoryBlobDescriptorCache struct {
|
||||
parent *inMemoryBlobDescriptorCacheProvider // allows lazy allocation of repo's map
|
||||
}
|
||||
|
||||
func (rsimbdcp *repositoryScopedInMemoryBlobDescriptorCache) Stat(ctx context.Context, dgst digest.Digest) (distribution.Descriptor, error) {
|
||||
func (rsimbdcp *repositoryScopedInMemoryBlobDescriptorCache) Stat(ctx context.Context, dgst digest.Digest) (v1.Descriptor, error) {
|
||||
if err := dgst.Validate(); err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
|
||||
key := descriptorCacheKey{
|
||||
@@ -134,7 +135,7 @@ func (rsimbdcp *repositoryScopedInMemoryBlobDescriptorCache) Stat(ctx context.Co
|
||||
if ok {
|
||||
return descriptor, nil
|
||||
}
|
||||
return distribution.Descriptor{}, distribution.ErrBlobUnknown
|
||||
return v1.Descriptor{}, distribution.ErrBlobUnknown
|
||||
}
|
||||
|
||||
func (rsimbdcp *repositoryScopedInMemoryBlobDescriptorCache) Clear(ctx context.Context, dgst digest.Digest) error {
|
||||
@@ -146,7 +147,7 @@ func (rsimbdcp *repositoryScopedInMemoryBlobDescriptorCache) Clear(ctx context.C
|
||||
return nil
|
||||
}
|
||||
|
||||
func (rsimbdcp *repositoryScopedInMemoryBlobDescriptorCache) SetDescriptor(ctx context.Context, dgst digest.Digest, desc distribution.Descriptor) error {
|
||||
func (rsimbdcp *repositoryScopedInMemoryBlobDescriptorCache) SetDescriptor(ctx context.Context, dgst digest.Digest, desc v1.Descriptor) error {
|
||||
if err := dgst.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
9
registry/storage/cache/metrics/prom.go
vendored
9
registry/storage/cache/metrics/prom.go
vendored
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/distribution/distribution/v3/registry/storage/cache"
|
||||
"github.com/docker/go-metrics"
|
||||
"github.com/opencontainers/go-digest"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
type prometheusCacheProvider struct {
|
||||
@@ -24,14 +25,14 @@ func NewPrometheusCacheProvider(wrap cache.BlobDescriptorCacheProvider, name, he
|
||||
}
|
||||
}
|
||||
|
||||
func (p *prometheusCacheProvider) Stat(ctx context.Context, dgst digest.Digest) (distribution.Descriptor, error) {
|
||||
func (p *prometheusCacheProvider) Stat(ctx context.Context, dgst digest.Digest) (v1.Descriptor, error) {
|
||||
start := time.Now()
|
||||
d, e := p.BlobDescriptorCacheProvider.Stat(ctx, dgst)
|
||||
p.latencyTimer.WithValues("Stat").UpdateSince(start)
|
||||
return d, e
|
||||
}
|
||||
|
||||
func (p *prometheusCacheProvider) SetDescriptor(ctx context.Context, dgst digest.Digest, desc distribution.Descriptor) error {
|
||||
func (p *prometheusCacheProvider) SetDescriptor(ctx context.Context, dgst digest.Digest, desc v1.Descriptor) error {
|
||||
start := time.Now()
|
||||
e := p.BlobDescriptorCacheProvider.SetDescriptor(ctx, dgst, desc)
|
||||
p.latencyTimer.WithValues("SetDescriptor").UpdateSince(start)
|
||||
@@ -43,14 +44,14 @@ type prometheusRepoCacheProvider struct {
|
||||
latencyTimer metrics.LabeledTimer
|
||||
}
|
||||
|
||||
func (p *prometheusRepoCacheProvider) Stat(ctx context.Context, dgst digest.Digest) (distribution.Descriptor, error) {
|
||||
func (p *prometheusRepoCacheProvider) Stat(ctx context.Context, dgst digest.Digest) (v1.Descriptor, error) {
|
||||
start := time.Now()
|
||||
d, e := p.BlobDescriptorService.Stat(ctx, dgst)
|
||||
p.latencyTimer.WithValues("RepoStat").UpdateSince(start)
|
||||
return d, e
|
||||
}
|
||||
|
||||
func (p *prometheusRepoCacheProvider) SetDescriptor(ctx context.Context, dgst digest.Digest, desc distribution.Descriptor) error {
|
||||
func (p *prometheusRepoCacheProvider) SetDescriptor(ctx context.Context, dgst digest.Digest, desc v1.Descriptor) error {
|
||||
start := time.Now()
|
||||
e := p.BlobDescriptorService.SetDescriptor(ctx, dgst, desc)
|
||||
p.latencyTimer.WithValues("RepoSetDescriptor").UpdateSince(start)
|
||||
|
41
registry/storage/cache/redis/redis.go
vendored
41
registry/storage/cache/redis/redis.go
vendored
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/distribution/distribution/v3/registry/storage/cache/metrics"
|
||||
"github.com/distribution/reference"
|
||||
"github.com/opencontainers/go-digest"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/redis/go-redis/v9"
|
||||
)
|
||||
|
||||
@@ -66,9 +67,9 @@ func (rbds *redisBlobDescriptorService) RepositoryScoped(repo string) (distribut
|
||||
}
|
||||
|
||||
// Stat retrieves the descriptor data from the redis hash entry.
|
||||
func (rbds *redisBlobDescriptorService) Stat(ctx context.Context, dgst digest.Digest) (distribution.Descriptor, error) {
|
||||
func (rbds *redisBlobDescriptorService) Stat(ctx context.Context, dgst digest.Digest) (v1.Descriptor, error) {
|
||||
if err := dgst.Validate(); err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
|
||||
return rbds.stat(ctx, dgst)
|
||||
@@ -91,33 +92,33 @@ func (rbds *redisBlobDescriptorService) Clear(ctx context.Context, dgst digest.D
|
||||
return nil
|
||||
}
|
||||
|
||||
func (rbds *redisBlobDescriptorService) stat(ctx context.Context, dgst digest.Digest) (distribution.Descriptor, error) {
|
||||
func (rbds *redisBlobDescriptorService) stat(ctx context.Context, dgst digest.Digest) (v1.Descriptor, error) {
|
||||
cmd := rbds.pool.HMGet(ctx, rbds.blobDescriptorHashKey(dgst), "digest", "size", "mediatype")
|
||||
reply, err := cmd.Result()
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
|
||||
// NOTE(stevvooe): The "size" field used to be "length". We treat a
|
||||
// missing "size" field here as an unknown blob, which causes a cache
|
||||
// miss, effectively migrating the field.
|
||||
if len(reply) < 3 || reply[0] == nil || reply[1] == nil { // don't care if mediatype is nil
|
||||
return distribution.Descriptor{}, distribution.ErrBlobUnknown
|
||||
return v1.Descriptor{}, distribution.ErrBlobUnknown
|
||||
}
|
||||
|
||||
var desc distribution.Descriptor
|
||||
var desc v1.Descriptor
|
||||
digestString, ok := reply[0].(string)
|
||||
if !ok {
|
||||
return distribution.Descriptor{}, fmt.Errorf("digest is not a string")
|
||||
return v1.Descriptor{}, fmt.Errorf("digest is not a string")
|
||||
}
|
||||
desc.Digest = digest.Digest(digestString)
|
||||
sizeString, ok := reply[1].(string)
|
||||
if !ok {
|
||||
return distribution.Descriptor{}, fmt.Errorf("size is not a string")
|
||||
return v1.Descriptor{}, fmt.Errorf("size is not a string")
|
||||
}
|
||||
size, err := strconv.ParseInt(sizeString, 10, 64)
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
desc.Size = size
|
||||
if reply[2] != nil {
|
||||
@@ -132,7 +133,7 @@ func (rbds *redisBlobDescriptorService) stat(ctx context.Context, dgst digest.Di
|
||||
// SetDescriptor sets the descriptor data for the given digest using a redis
|
||||
// hash. A hash is used here since we may store unrelated fields about a layer
|
||||
// in the future.
|
||||
func (rbds *redisBlobDescriptorService) SetDescriptor(ctx context.Context, dgst digest.Digest, desc distribution.Descriptor) error {
|
||||
func (rbds *redisBlobDescriptorService) SetDescriptor(ctx context.Context, dgst digest.Digest, desc v1.Descriptor) error {
|
||||
if err := dgst.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -144,7 +145,7 @@ func (rbds *redisBlobDescriptorService) SetDescriptor(ctx context.Context, dgst
|
||||
return rbds.setDescriptor(ctx, dgst, desc)
|
||||
}
|
||||
|
||||
func (rbds *redisBlobDescriptorService) setDescriptor(ctx context.Context, dgst digest.Digest, desc distribution.Descriptor) error {
|
||||
func (rbds *redisBlobDescriptorService) setDescriptor(ctx context.Context, dgst digest.Digest, desc v1.Descriptor) error {
|
||||
cmd := rbds.pool.HMSet(ctx, rbds.blobDescriptorHashKey(dgst), "digest", desc.Digest.String(), "size", desc.Size)
|
||||
if cmd.Err() != nil {
|
||||
return cmd.Err()
|
||||
@@ -171,33 +172,33 @@ var _ distribution.BlobDescriptorService = &repositoryScopedRedisBlobDescriptorS
|
||||
// Stat ensures that the digest is a member of the specified repository and
|
||||
// forwards the descriptor request to the global blob store. If the media type
|
||||
// differs for the repository, we override it.
|
||||
func (rsrbds *repositoryScopedRedisBlobDescriptorService) Stat(ctx context.Context, dgst digest.Digest) (distribution.Descriptor, error) {
|
||||
func (rsrbds *repositoryScopedRedisBlobDescriptorService) Stat(ctx context.Context, dgst digest.Digest) (v1.Descriptor, error) {
|
||||
if err := dgst.Validate(); err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
|
||||
pool := rsrbds.upstream.pool
|
||||
// Check membership to repository first
|
||||
member, err := pool.SIsMember(ctx, rsrbds.repositoryBlobSetKey(rsrbds.repo), dgst.String()).Result()
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
if !member {
|
||||
return distribution.Descriptor{}, distribution.ErrBlobUnknown
|
||||
return v1.Descriptor{}, distribution.ErrBlobUnknown
|
||||
}
|
||||
|
||||
upstream, err := rsrbds.upstream.stat(ctx, dgst)
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
|
||||
// We allow a per repository mediatype, let's look it up here.
|
||||
mediatype, err := pool.HGet(ctx, rsrbds.blobDescriptorHashKey(dgst), "mediatype").Result()
|
||||
if err != nil {
|
||||
if err == redis.Nil {
|
||||
return distribution.Descriptor{}, distribution.ErrBlobUnknown
|
||||
return v1.Descriptor{}, distribution.ErrBlobUnknown
|
||||
}
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
|
||||
if mediatype != "" {
|
||||
@@ -225,7 +226,7 @@ func (rsrbds *repositoryScopedRedisBlobDescriptorService) Clear(ctx context.Cont
|
||||
return rsrbds.upstream.Clear(ctx, dgst)
|
||||
}
|
||||
|
||||
func (rsrbds *repositoryScopedRedisBlobDescriptorService) SetDescriptor(ctx context.Context, dgst digest.Digest, desc distribution.Descriptor) error {
|
||||
func (rsrbds *repositoryScopedRedisBlobDescriptorService) SetDescriptor(ctx context.Context, dgst digest.Digest, desc v1.Descriptor) error {
|
||||
if err := dgst.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -243,7 +244,7 @@ func (rsrbds *repositoryScopedRedisBlobDescriptorService) SetDescriptor(ctx cont
|
||||
return rsrbds.setDescriptor(ctx, dgst, desc)
|
||||
}
|
||||
|
||||
func (rsrbds *repositoryScopedRedisBlobDescriptorService) setDescriptor(ctx context.Context, dgst digest.Digest, desc distribution.Descriptor) error {
|
||||
func (rsrbds *repositoryScopedRedisBlobDescriptorService) setDescriptor(ctx context.Context, dgst digest.Digest, desc v1.Descriptor) error {
|
||||
conn := rsrbds.upstream.pool
|
||||
_, err := conn.SAdd(ctx, rsrbds.repositoryBlobSetKey(rsrbds.repo), dgst.String()).Result()
|
||||
if err != nil {
|
||||
|
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/distribution/distribution/v3/registry/storage/driver"
|
||||
"github.com/distribution/reference"
|
||||
"github.com/opencontainers/go-digest"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
func emit(format string, a ...interface{}) {
|
||||
@@ -65,7 +66,7 @@ func MarkAndSweep(ctx context.Context, storageDriver driver.StorageDriver, regis
|
||||
err = manifestEnumerator.Enumerate(ctx, func(dgst digest.Digest) error {
|
||||
if opts.RemoveUntagged {
|
||||
// fetch all tags where this manifest is the latest one
|
||||
tags, err := repository.Tags(ctx).Lookup(ctx, distribution.Descriptor{Digest: dgst})
|
||||
tags, err := repository.Tags(ctx).Lookup(ctx, v1.Descriptor{Digest: dgst})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to retrieve tags for digest %v: %v", dgst, err)
|
||||
}
|
||||
|
@@ -14,6 +14,7 @@ import (
|
||||
"github.com/distribution/distribution/v3/testutil"
|
||||
"github.com/distribution/reference"
|
||||
"github.com/opencontainers/go-digest"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
type image struct {
|
||||
@@ -250,7 +251,7 @@ func TestDeleteManifestIfTagNotFound(t *testing.T) {
|
||||
|
||||
manifestEnumerator, _ := manifestService.(distribution.ManifestEnumerator)
|
||||
err = manifestEnumerator.Enumerate(ctx, func(dgst digest.Digest) error {
|
||||
return repo.Tags(ctx).Tag(ctx, "test", distribution.Descriptor{Digest: dgst})
|
||||
return repo.Tags(ctx).Tag(ctx, "test", v1.Descriptor{Digest: dgst})
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("manifest enumeration failed: %v", err)
|
||||
@@ -306,7 +307,7 @@ func TestDeleteManifestIndexWithDanglingReferences(t *testing.T) {
|
||||
image1 := uploadRandomOCIImage(t, repo)
|
||||
image2 := uploadRandomOCIImage(t, repo)
|
||||
|
||||
ii, _ := ocischema.FromDescriptors([]distribution.Descriptor{
|
||||
ii, _ := ocischema.FromDescriptors([]v1.Descriptor{
|
||||
{Digest: image1.manifestDigest}, {Digest: image2.manifestDigest},
|
||||
}, map[string]string{})
|
||||
|
||||
@@ -315,7 +316,7 @@ func TestDeleteManifestIndexWithDanglingReferences(t *testing.T) {
|
||||
t.Fatalf("manifest upload failed: %v", err)
|
||||
}
|
||||
|
||||
err = repo.Tags(ctx).Tag(ctx, "test", distribution.Descriptor{Digest: id})
|
||||
err = repo.Tags(ctx).Tag(ctx, "test", v1.Descriptor{Digest: id})
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to delete tag: %v", err)
|
||||
}
|
||||
@@ -359,7 +360,7 @@ func TestDeleteManifestIndexIfTagNotFound(t *testing.T) {
|
||||
image1 := uploadRandomOCIImage(t, repo)
|
||||
image2 := uploadRandomOCIImage(t, repo)
|
||||
|
||||
ii, _ := ocischema.FromDescriptors([]distribution.Descriptor{
|
||||
ii, _ := ocischema.FromDescriptors([]v1.Descriptor{
|
||||
{Digest: image1.manifestDigest}, {Digest: image2.manifestDigest},
|
||||
}, map[string]string{})
|
||||
|
||||
@@ -368,7 +369,7 @@ func TestDeleteManifestIndexIfTagNotFound(t *testing.T) {
|
||||
t.Fatalf("manifest upload failed: %v", err)
|
||||
}
|
||||
|
||||
err = repo.Tags(ctx).Tag(ctx, "test", distribution.Descriptor{Digest: d4})
|
||||
err = repo.Tags(ctx).Tag(ctx, "test", v1.Descriptor{Digest: d4})
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to delete tag: %v", err)
|
||||
}
|
||||
@@ -466,7 +467,7 @@ func TestGCWithUnknownRepository(t *testing.T) {
|
||||
repo := makeRepository(t, registry, "nonexistentrepo")
|
||||
image := uploadRandomSchema2Image(t, repo)
|
||||
|
||||
err := repo.Tags(ctx).Tag(ctx, "image", distribution.Descriptor{Digest: image.manifestDigest})
|
||||
err := repo.Tags(ctx).Tag(ctx, "image", v1.Descriptor{Digest: image.manifestDigest})
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to tag descriptor: %v", err)
|
||||
}
|
||||
@@ -729,7 +730,7 @@ func TestTaggedManifestlistWithUntaggedManifest(t *testing.T) {
|
||||
t.Fatalf("Failed to add manifest list: %v", err)
|
||||
}
|
||||
|
||||
err = repo.Tags(ctx).Tag(ctx, "test", distribution.Descriptor{Digest: dgst})
|
||||
err = repo.Tags(ctx).Tag(ctx, "test", v1.Descriptor{Digest: dgst})
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to delete tag: %v", err)
|
||||
}
|
||||
@@ -821,12 +822,12 @@ func TestUnTaggedManifestlistWithTaggedManifest(t *testing.T) {
|
||||
image1 := uploadRandomSchema2Image(t, repo)
|
||||
image2 := uploadRandomSchema2Image(t, repo)
|
||||
|
||||
err = repo.Tags(ctx).Tag(ctx, "image1", distribution.Descriptor{Digest: image1.manifestDigest})
|
||||
err = repo.Tags(ctx).Tag(ctx, "image1", v1.Descriptor{Digest: image1.manifestDigest})
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to delete tag: %v", err)
|
||||
}
|
||||
|
||||
err = repo.Tags(ctx).Tag(ctx, "image2", distribution.Descriptor{Digest: image2.manifestDigest})
|
||||
err = repo.Tags(ctx).Tag(ctx, "image2", v1.Descriptor{Digest: image2.manifestDigest})
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to delete tag: %v", err)
|
||||
}
|
||||
|
@@ -14,6 +14,7 @@ import (
|
||||
"github.com/distribution/reference"
|
||||
"github.com/google/uuid"
|
||||
"github.com/opencontainers/go-digest"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
// linkPathFunc describes a function that can resolve a link based on the
|
||||
@@ -45,7 +46,7 @@ type linkedBlobStore struct {
|
||||
|
||||
var _ distribution.BlobStore = &linkedBlobStore{}
|
||||
|
||||
func (lbs *linkedBlobStore) Stat(ctx context.Context, dgst digest.Digest) (distribution.Descriptor, error) {
|
||||
func (lbs *linkedBlobStore) Stat(ctx context.Context, dgst digest.Digest) (v1.Descriptor, error) {
|
||||
return lbs.blobAccessController.Stat(ctx, dgst)
|
||||
}
|
||||
|
||||
@@ -81,17 +82,17 @@ func (lbs *linkedBlobStore) ServeBlob(ctx context.Context, w http.ResponseWriter
|
||||
return lbs.blobServer.ServeBlob(ctx, w, r, canonical.Digest)
|
||||
}
|
||||
|
||||
func (lbs *linkedBlobStore) Put(ctx context.Context, mediaType string, p []byte) (distribution.Descriptor, error) {
|
||||
func (lbs *linkedBlobStore) Put(ctx context.Context, mediaType string, p []byte) (v1.Descriptor, error) {
|
||||
dgst := digest.FromBytes(p)
|
||||
// Place the data in the blob store first.
|
||||
desc, err := lbs.blobStore.Put(ctx, mediaType, p)
|
||||
if err != nil {
|
||||
dcontext.GetLogger(ctx).Errorf("error putting into main store: %v", err)
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
|
||||
if err := lbs.blobAccessController.SetDescriptor(ctx, dgst, desc); err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
|
||||
// TODO(stevvooe): Write out mediatype if incoming differs from what is
|
||||
@@ -270,24 +271,24 @@ func (lbs *linkedBlobStore) Enumerate(ctx context.Context, ingestor func(digest.
|
||||
})
|
||||
}
|
||||
|
||||
func (lbs *linkedBlobStore) mount(ctx context.Context, sourceRepo reference.Named, dgst digest.Digest, sourceStat *distribution.Descriptor) (distribution.Descriptor, error) {
|
||||
var stat distribution.Descriptor
|
||||
func (lbs *linkedBlobStore) mount(ctx context.Context, sourceRepo reference.Named, dgst digest.Digest, sourceStat *v1.Descriptor) (v1.Descriptor, error) {
|
||||
var stat v1.Descriptor
|
||||
if sourceStat == nil {
|
||||
// look up the blob info from the sourceRepo if not already provided
|
||||
repo, err := lbs.registry.Repository(ctx, sourceRepo)
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
stat, err = repo.Blobs(ctx).Stat(ctx, dgst)
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
} else {
|
||||
// use the provided blob info
|
||||
stat = *sourceStat
|
||||
}
|
||||
|
||||
desc := distribution.Descriptor{
|
||||
desc := v1.Descriptor{
|
||||
Size: stat.Size,
|
||||
|
||||
// NOTE(stevvooe): The central blob store firewalls media types from
|
||||
@@ -323,7 +324,7 @@ func (lbs *linkedBlobStore) newBlobUpload(ctx context.Context, uuid, path string
|
||||
|
||||
// linkBlob links a valid, written blob into the registry under the named
|
||||
// repository for the upload controller.
|
||||
func (lbs *linkedBlobStore) linkBlob(ctx context.Context, canonical distribution.Descriptor, aliases ...digest.Digest) error {
|
||||
func (lbs *linkedBlobStore) linkBlob(ctx context.Context, canonical v1.Descriptor, aliases ...digest.Digest) error {
|
||||
dgsts := append([]digest.Digest{canonical.Digest}, aliases...)
|
||||
|
||||
// TODO(stevvooe): Need to write out mediatype for only canonical hash
|
||||
@@ -365,19 +366,19 @@ type linkedBlobStatter struct {
|
||||
|
||||
var _ distribution.BlobDescriptorService = &linkedBlobStatter{}
|
||||
|
||||
func (lbs *linkedBlobStatter) Stat(ctx context.Context, dgst digest.Digest) (distribution.Descriptor, error) {
|
||||
func (lbs *linkedBlobStatter) Stat(ctx context.Context, dgst digest.Digest) (v1.Descriptor, error) {
|
||||
blobLinkPath, err := lbs.linkPath(lbs.repository.Named().Name(), dgst)
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
|
||||
target, err := lbs.blobStore.readlink(ctx, blobLinkPath)
|
||||
if err != nil {
|
||||
switch err := err.(type) {
|
||||
case driver.PathNotFoundError:
|
||||
return distribution.Descriptor{}, distribution.ErrBlobUnknown
|
||||
return v1.Descriptor{}, distribution.ErrBlobUnknown
|
||||
default:
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -401,7 +402,7 @@ func (lbs *linkedBlobStatter) Clear(ctx context.Context, dgst digest.Digest) (er
|
||||
return lbs.blobStore.driver.Delete(ctx, blobLinkPath)
|
||||
}
|
||||
|
||||
func (lbs *linkedBlobStatter) SetDescriptor(ctx context.Context, dgst digest.Digest, desc distribution.Descriptor) error {
|
||||
func (lbs *linkedBlobStatter) SetDescriptor(ctx context.Context, dgst digest.Digest, desc v1.Descriptor) error {
|
||||
// The canonical descriptor for a blob is set at the commit phase of upload
|
||||
return nil
|
||||
}
|
||||
|
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/distribution/distribution/v3/testutil"
|
||||
"github.com/distribution/reference"
|
||||
"github.com/opencontainers/go-digest"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
func TestLinkedBlobStoreEnumerator(t *testing.T) {
|
||||
@@ -38,7 +39,7 @@ func TestLinkedBlobStoreEnumerator(t *testing.T) {
|
||||
t.Fatalf("unexpected error copying to upload: %v", err)
|
||||
}
|
||||
|
||||
if _, err := wr.Commit(fooEnv.ctx, distribution.Descriptor{Digest: dgst}); err != nil {
|
||||
if _, err := wr.Commit(fooEnv.ctx, v1.Descriptor{Digest: dgst}); err != nil {
|
||||
t.Fatalf("unexpected error finishing upload: %v", err)
|
||||
}
|
||||
}
|
||||
@@ -95,7 +96,7 @@ func TestLinkedBlobStoreCreateWithMountFrom(t *testing.T) {
|
||||
t.Fatalf("unexpected error copying to upload: %v", err)
|
||||
}
|
||||
|
||||
if _, err := wr.Commit(fooEnv.ctx, distribution.Descriptor{Digest: dgst}); err != nil {
|
||||
if _, err := wr.Commit(fooEnv.ctx, v1.Descriptor{Digest: dgst}); err != nil {
|
||||
t.Fatalf("unexpected error finishing upload: %v", err)
|
||||
}
|
||||
}
|
||||
@@ -154,7 +155,7 @@ func TestLinkedBlobStoreCreateWithMountFrom(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
prepolutatedDescriptor := distribution.Descriptor{
|
||||
prepolutatedDescriptor := v1.Descriptor{
|
||||
Digest: dgst,
|
||||
Size: size,
|
||||
MediaType: "application/octet-stream",
|
||||
@@ -223,16 +224,16 @@ type mockBlobDescriptorService struct {
|
||||
|
||||
var _ distribution.BlobDescriptorService = &mockBlobDescriptorService{}
|
||||
|
||||
func (bs *mockBlobDescriptorService) Stat(ctx context.Context, dgst digest.Digest) (distribution.Descriptor, error) {
|
||||
func (bs *mockBlobDescriptorService) Stat(ctx context.Context, dgst digest.Digest) (v1.Descriptor, error) {
|
||||
statter, ok := bs.BlobDescriptorService.(*linkedBlobStatter)
|
||||
if !ok {
|
||||
return distribution.Descriptor{}, fmt.Errorf("unexpected blob descriptor service: %T", bs.BlobDescriptorService)
|
||||
return v1.Descriptor{}, fmt.Errorf("unexpected blob descriptor service: %T", bs.BlobDescriptorService)
|
||||
}
|
||||
|
||||
name := statter.repository.Named()
|
||||
canonical, err := reference.WithDigest(name, dgst)
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, fmt.Errorf("failed to make canonical reference: %v", err)
|
||||
return v1.Descriptor{}, fmt.Errorf("failed to make canonical reference: %v", err)
|
||||
}
|
||||
|
||||
bs.stats[canonical.String()]++
|
||||
@@ -243,7 +244,7 @@ func (bs *mockBlobDescriptorService) Stat(ctx context.Context, dgst digest.Diges
|
||||
|
||||
// statCrossMountCreateOptions ensures the expected options type is passed, and optionally pre-fills the cross-mount stat info
|
||||
type statCrossMountCreateOption struct {
|
||||
desc distribution.Descriptor
|
||||
desc v1.Descriptor
|
||||
}
|
||||
|
||||
var _ distribution.BlobCreateOption = statCrossMountCreateOption{}
|
||||
|
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/distribution/distribution/v3/manifest/manifestlist"
|
||||
"github.com/distribution/distribution/v3/manifest/ocischema"
|
||||
"github.com/opencontainers/go-digest"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
// manifestListHandler is a ManifestHandler that covers schema2 manifest lists.
|
||||
@@ -104,7 +105,7 @@ func (ms *manifestListHandler) verifyManifest(ctx context.Context, mnfst distrib
|
||||
}
|
||||
|
||||
// platformMustExist checks if a descriptor within an index should be validated as existing before accepting the manifest into the registry.
|
||||
func (ms *manifestListHandler) platformMustExist(descriptor distribution.Descriptor) bool {
|
||||
func (ms *manifestListHandler) platformMustExist(descriptor v1.Descriptor) bool {
|
||||
// If there are no image platforms configured to validate, we must check the existence of all child images.
|
||||
if len(ms.validateImageIndexes.imagePlatforms) == 0 {
|
||||
return true
|
||||
|
@@ -96,12 +96,12 @@ func testManifestStorage(t *testing.T, options ...RegistryOption) {
|
||||
m := &schema2.Manifest{
|
||||
Versioned: specs.Versioned{SchemaVersion: 2},
|
||||
MediaType: schema2.MediaTypeManifest,
|
||||
Config: distribution.Descriptor{
|
||||
Config: v1.Descriptor{
|
||||
Digest: digest.FromBytes(sampleConfig),
|
||||
Size: int64(len(sampleConfig)),
|
||||
MediaType: schema2.MediaTypeImageConfig,
|
||||
},
|
||||
Layers: []distribution.Descriptor{},
|
||||
Layers: []v1.Descriptor{},
|
||||
}
|
||||
|
||||
// Build up some test layers and add them to the manifest, saving the
|
||||
@@ -114,7 +114,7 @@ func testManifestStorage(t *testing.T, options ...RegistryOption) {
|
||||
}
|
||||
|
||||
testLayers[dgst] = rs
|
||||
layer := distribution.Descriptor{
|
||||
layer := v1.Descriptor{
|
||||
Digest: dgst,
|
||||
Size: 6323,
|
||||
MediaType: schema2.MediaTypeLayer,
|
||||
@@ -133,10 +133,10 @@ func testManifestStorage(t *testing.T, options ...RegistryOption) {
|
||||
t.Fatalf("unexpected error copying to upload: %v", err)
|
||||
}
|
||||
|
||||
if _, err := wr.Commit(env.ctx, distribution.Descriptor{Digest: dgst}); err != nil {
|
||||
if _, err := wr.Commit(env.ctx, v1.Descriptor{Digest: dgst}); err != nil {
|
||||
t.Fatalf("unexpected error finishing upload: %v", err)
|
||||
}
|
||||
if err := builder.AppendReference(distribution.Descriptor{Digest: dgst, MediaType: schema2.MediaTypeLayer}); err != nil {
|
||||
if err := builder.AppendReference(v1.Descriptor{Digest: dgst, MediaType: schema2.MediaTypeLayer}); err != nil {
|
||||
t.Fatalf("unexpected error appending references: %v", err)
|
||||
}
|
||||
}
|
||||
@@ -336,7 +336,7 @@ func testOCIManifestStorage(t *testing.T, testname string, includeMediaTypes boo
|
||||
OS: "CP/M",
|
||||
}
|
||||
|
||||
mfstDescriptors := []distribution.Descriptor{
|
||||
mfstDescriptors := []v1.Descriptor{
|
||||
createOciManifestDescriptor(t, testname, mfst, platformSpec),
|
||||
}
|
||||
|
||||
@@ -460,7 +460,7 @@ func TestIndexManifestStorageWithoutImageCheck(t *testing.T) {
|
||||
OS: "CP/M",
|
||||
}
|
||||
|
||||
ociManifestDescriptors := []distribution.Descriptor{
|
||||
ociManifestDescriptors := []v1.Descriptor{
|
||||
createOciManifestDescriptor(t, t.Name(), manifest, ociPlatformSpec),
|
||||
}
|
||||
|
||||
@@ -547,7 +547,7 @@ func TestIndexManifestStorageWithSelectivePlatforms(t *testing.T) {
|
||||
OS: "CP/M",
|
||||
}
|
||||
|
||||
manifestDescriptors := []distribution.Descriptor{
|
||||
manifestDescriptors := []v1.Descriptor{
|
||||
createOciManifestDescriptor(t, t.Name(), amdManifest, amdPlatformSpec),
|
||||
createOciManifestDescriptor(t, t.Name(), armManifest, armPlatformSpec),
|
||||
createOciManifestDescriptor(t, t.Name(), atariManifest, atariPlatformSpec),
|
||||
@@ -616,11 +616,11 @@ func createRandomImage(t *testing.T, testname string, imageMediaType string, blo
|
||||
t.Fatalf("%s: unexpected error copying to upload: %v", testname, err)
|
||||
}
|
||||
|
||||
if _, err := wr.Commit(ctx, distribution.Descriptor{Digest: dgst}); err != nil {
|
||||
if _, err := wr.Commit(ctx, v1.Descriptor{Digest: dgst}); err != nil {
|
||||
t.Fatalf("%s: unexpected error finishing upload: %v", testname, err)
|
||||
}
|
||||
|
||||
if err := builder.AppendReference(distribution.Descriptor{Digest: dgst, MediaType: v1.MediaTypeImageLayer}); err != nil {
|
||||
if err := builder.AppendReference(v1.Descriptor{Digest: dgst, MediaType: v1.MediaTypeImageLayer}); err != nil {
|
||||
t.Fatalf("%s unexpected error appending references: %v", testname, err)
|
||||
}
|
||||
}
|
||||
@@ -629,14 +629,14 @@ func createRandomImage(t *testing.T, testname string, imageMediaType string, blo
|
||||
}
|
||||
|
||||
// createOciManifestDescriptor builds a manifest descriptor from a manifest and a platform descriptor
|
||||
func createOciManifestDescriptor(t *testing.T, testname string, manifest distribution.Manifest, platformSpec *v1.Platform) distribution.Descriptor {
|
||||
func createOciManifestDescriptor(t *testing.T, testname string, manifest distribution.Manifest, platformSpec *v1.Platform) v1.Descriptor {
|
||||
manifestMediaType, manifestPayload, err := manifest.Payload()
|
||||
if err != nil {
|
||||
t.Fatalf("%s: unexpected error getting manifest payload: %v", testname, err)
|
||||
}
|
||||
manifestDigest := digest.FromBytes(manifestPayload)
|
||||
|
||||
return distribution.Descriptor{
|
||||
return v1.Descriptor{
|
||||
Digest: manifestDigest,
|
||||
Size: int64(len(manifestPayload)),
|
||||
MediaType: manifestMediaType,
|
||||
@@ -656,7 +656,7 @@ func createManifestListDescriptor(t *testing.T, testname string, manifest distri
|
||||
manifestDigest := digest.FromBytes(manifestPayload)
|
||||
|
||||
return manifestlist.ManifestDescriptor{
|
||||
Descriptor: distribution.Descriptor{
|
||||
Descriptor: v1.Descriptor{
|
||||
Digest: manifestDigest,
|
||||
Size: int64(len(manifestPayload)),
|
||||
MediaType: manifestMediaType,
|
||||
@@ -701,7 +701,7 @@ func TestLinkPathFuncs(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func ociIndexFromDesriptorsWithMediaType(descriptors []distribution.Descriptor, mediaType string) (*ocischema.DeserializedImageIndex, error) {
|
||||
func ociIndexFromDesriptorsWithMediaType(descriptors []v1.Descriptor, mediaType string) (*ocischema.DeserializedImageIndex, error) {
|
||||
manifest, err := ocischema.FromDescriptors(descriptors, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@@ -33,17 +33,17 @@ func TestVerifyOCIManifestNonDistributableLayer(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
nonDistributableLayer := distribution.Descriptor{
|
||||
nonDistributableLayer := v1.Descriptor{
|
||||
Digest: "sha256:463435349086340864309863409683460843608348608934092322395278926a",
|
||||
Size: 6323,
|
||||
MediaType: v1.MediaTypeImageLayerNonDistributableGzip, //nolint:staticcheck // ignore A1019: v1.MediaTypeImageLayerNonDistributableGzip is deprecated: Non-distributable layers are deprecated, and not recommended for future use
|
||||
}
|
||||
|
||||
emptyLayer := distribution.Descriptor{
|
||||
emptyLayer := v1.Descriptor{
|
||||
Digest: "",
|
||||
}
|
||||
|
||||
emptyGzipLayer := distribution.Descriptor{
|
||||
emptyGzipLayer := v1.Descriptor{
|
||||
Digest: "",
|
||||
MediaType: v1.MediaTypeImageLayerGzip,
|
||||
}
|
||||
@@ -55,7 +55,7 @@ func TestVerifyOCIManifestNonDistributableLayer(t *testing.T) {
|
||||
}
|
||||
|
||||
type testcase struct {
|
||||
BaseLayer distribution.Descriptor
|
||||
BaseLayer v1.Descriptor
|
||||
URLs []string
|
||||
Err error
|
||||
}
|
||||
@@ -142,7 +142,7 @@ func TestVerifyOCIManifestNonDistributableLayer(t *testing.T) {
|
||||
m := template
|
||||
l := c.BaseLayer
|
||||
l.URLs = c.URLs
|
||||
m.Layers = []distribution.Descriptor{l}
|
||||
m.Layers = []v1.Descriptor{l}
|
||||
dm, err := ocischema.FromStruct(m)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
@@ -215,7 +215,7 @@ func TestVerifyOCIManifestBlobLayerAndConfig(t *testing.T) {
|
||||
}
|
||||
|
||||
type testcase struct {
|
||||
Desc distribution.Descriptor
|
||||
Desc v1.Descriptor
|
||||
URLs []string
|
||||
Err error
|
||||
}
|
||||
@@ -223,25 +223,25 @@ func TestVerifyOCIManifestBlobLayerAndConfig(t *testing.T) {
|
||||
layercases := []testcase{
|
||||
// empty media type
|
||||
{
|
||||
distribution.Descriptor{},
|
||||
v1.Descriptor{},
|
||||
[]string{"http://foo/bar"},
|
||||
digest.ErrDigestInvalidFormat,
|
||||
},
|
||||
{
|
||||
distribution.Descriptor{},
|
||||
v1.Descriptor{},
|
||||
nil,
|
||||
digest.ErrDigestInvalidFormat,
|
||||
},
|
||||
// unknown media type, but blob is present
|
||||
{
|
||||
distribution.Descriptor{
|
||||
v1.Descriptor{
|
||||
Digest: layer.Digest,
|
||||
},
|
||||
nil,
|
||||
nil,
|
||||
},
|
||||
{
|
||||
distribution.Descriptor{
|
||||
v1.Descriptor{
|
||||
Digest: layer.Digest,
|
||||
},
|
||||
[]string{"http://foo/bar"},
|
||||
@@ -249,21 +249,21 @@ func TestVerifyOCIManifestBlobLayerAndConfig(t *testing.T) {
|
||||
},
|
||||
// gzip layer, but invalid digest
|
||||
{
|
||||
distribution.Descriptor{
|
||||
v1.Descriptor{
|
||||
MediaType: v1.MediaTypeImageLayerGzip,
|
||||
},
|
||||
nil,
|
||||
digest.ErrDigestInvalidFormat,
|
||||
},
|
||||
{
|
||||
distribution.Descriptor{
|
||||
v1.Descriptor{
|
||||
MediaType: v1.MediaTypeImageLayerGzip,
|
||||
},
|
||||
[]string{"https://foo/bar"},
|
||||
digest.ErrDigestInvalidFormat,
|
||||
},
|
||||
{
|
||||
distribution.Descriptor{
|
||||
v1.Descriptor{
|
||||
MediaType: v1.MediaTypeImageLayerGzip,
|
||||
Digest: digest.Digest("invalid"),
|
||||
},
|
||||
@@ -290,7 +290,7 @@ func TestVerifyOCIManifestBlobLayerAndConfig(t *testing.T) {
|
||||
l := c.Desc
|
||||
l.URLs = c.URLs
|
||||
|
||||
m.Layers = []distribution.Descriptor{l}
|
||||
m.Layers = []v1.Descriptor{l}
|
||||
|
||||
checkFn(m, c.Err)
|
||||
}
|
||||
@@ -304,14 +304,14 @@ func TestVerifyOCIManifestBlobLayerAndConfig(t *testing.T) {
|
||||
},
|
||||
// invalid digest
|
||||
{
|
||||
distribution.Descriptor{
|
||||
v1.Descriptor{
|
||||
MediaType: v1.MediaTypeImageConfig,
|
||||
},
|
||||
[]string{"https://foo/bar"},
|
||||
digest.ErrDigestInvalidFormat,
|
||||
},
|
||||
{
|
||||
distribution.Descriptor{
|
||||
v1.Descriptor{
|
||||
MediaType: v1.MediaTypeImageConfig,
|
||||
Digest: digest.Digest("invalid"),
|
||||
},
|
||||
|
@@ -11,6 +11,7 @@ import (
|
||||
"github.com/distribution/distribution/v3/registry/storage/driver/inmemory"
|
||||
"github.com/opencontainers/go-digest"
|
||||
"github.com/opencontainers/image-spec/specs-go"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
func TestVerifyManifestForeignLayer(t *testing.T) {
|
||||
@@ -34,13 +35,13 @@ func TestVerifyManifestForeignLayer(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
foreignLayer := distribution.Descriptor{
|
||||
foreignLayer := v1.Descriptor{
|
||||
Digest: "sha256:463435349086340864309863409683460843608348608934092322395278926a",
|
||||
Size: 6323,
|
||||
MediaType: schema2.MediaTypeForeignLayer,
|
||||
}
|
||||
|
||||
emptyLayer := distribution.Descriptor{
|
||||
emptyLayer := v1.Descriptor{
|
||||
Digest: "",
|
||||
}
|
||||
|
||||
@@ -51,7 +52,7 @@ func TestVerifyManifestForeignLayer(t *testing.T) {
|
||||
}
|
||||
|
||||
type testcase struct {
|
||||
BaseLayer distribution.Descriptor
|
||||
BaseLayer v1.Descriptor
|
||||
URLs []string
|
||||
Err error
|
||||
}
|
||||
@@ -129,7 +130,7 @@ func TestVerifyManifestForeignLayer(t *testing.T) {
|
||||
m := template
|
||||
l := c.BaseLayer
|
||||
l.URLs = c.URLs
|
||||
m.Layers = []distribution.Descriptor{l}
|
||||
m.Layers = []v1.Descriptor{l}
|
||||
dm, err := schema2.FromStruct(m)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
@@ -202,7 +203,7 @@ func TestVerifyManifestBlobLayerAndConfig(t *testing.T) {
|
||||
}
|
||||
|
||||
type testcase struct {
|
||||
Desc distribution.Descriptor
|
||||
Desc v1.Descriptor
|
||||
URLs []string
|
||||
Err error
|
||||
}
|
||||
@@ -210,25 +211,25 @@ func TestVerifyManifestBlobLayerAndConfig(t *testing.T) {
|
||||
layercases := []testcase{
|
||||
// empty media type
|
||||
{
|
||||
distribution.Descriptor{},
|
||||
v1.Descriptor{},
|
||||
[]string{"http://foo/bar"},
|
||||
digest.ErrDigestInvalidFormat,
|
||||
},
|
||||
{
|
||||
distribution.Descriptor{},
|
||||
v1.Descriptor{},
|
||||
nil,
|
||||
digest.ErrDigestInvalidFormat,
|
||||
},
|
||||
// unknown media type, but blob is present
|
||||
{
|
||||
distribution.Descriptor{
|
||||
v1.Descriptor{
|
||||
Digest: layer.Digest,
|
||||
},
|
||||
nil,
|
||||
nil,
|
||||
},
|
||||
{
|
||||
distribution.Descriptor{
|
||||
v1.Descriptor{
|
||||
Digest: layer.Digest,
|
||||
},
|
||||
[]string{"http://foo/bar"},
|
||||
@@ -236,21 +237,21 @@ func TestVerifyManifestBlobLayerAndConfig(t *testing.T) {
|
||||
},
|
||||
// gzip layer, but invalid digest
|
||||
{
|
||||
distribution.Descriptor{
|
||||
v1.Descriptor{
|
||||
MediaType: schema2.MediaTypeLayer,
|
||||
},
|
||||
nil,
|
||||
digest.ErrDigestInvalidFormat,
|
||||
},
|
||||
{
|
||||
distribution.Descriptor{
|
||||
v1.Descriptor{
|
||||
MediaType: schema2.MediaTypeLayer,
|
||||
},
|
||||
[]string{"https://foo/bar"},
|
||||
digest.ErrDigestInvalidFormat,
|
||||
},
|
||||
{
|
||||
distribution.Descriptor{
|
||||
v1.Descriptor{
|
||||
MediaType: schema2.MediaTypeLayer,
|
||||
Digest: digest.Digest("invalid"),
|
||||
},
|
||||
@@ -277,7 +278,7 @@ func TestVerifyManifestBlobLayerAndConfig(t *testing.T) {
|
||||
l := c.Desc
|
||||
l.URLs = c.URLs
|
||||
|
||||
m.Layers = []distribution.Descriptor{l}
|
||||
m.Layers = []v1.Descriptor{l}
|
||||
|
||||
checkFn(m, c.Err)
|
||||
}
|
||||
@@ -291,14 +292,14 @@ func TestVerifyManifestBlobLayerAndConfig(t *testing.T) {
|
||||
},
|
||||
// invalid digest
|
||||
{
|
||||
distribution.Descriptor{
|
||||
v1.Descriptor{
|
||||
MediaType: schema2.MediaTypeImageConfig,
|
||||
},
|
||||
[]string{"https://foo/bar"},
|
||||
digest.ErrDigestInvalidFormat,
|
||||
},
|
||||
{
|
||||
distribution.Descriptor{
|
||||
v1.Descriptor{
|
||||
MediaType: schema2.MediaTypeImageConfig,
|
||||
Digest: digest.Digest("invalid"),
|
||||
},
|
||||
|
@@ -7,6 +7,7 @@ import (
|
||||
"sync"
|
||||
|
||||
"github.com/opencontainers/go-digest"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"golang.org/x/sync/errgroup"
|
||||
|
||||
"github.com/distribution/distribution/v3"
|
||||
@@ -18,7 +19,7 @@ var _ distribution.TagService = &tagStore{}
|
||||
// tagStore provides methods to manage manifest tags in a backend storage driver.
|
||||
// This implementation uses the same on-disk layout as the (now deleted) tag
|
||||
// store. This provides backward compatibility with current registry deployments
|
||||
// which only makes use of the Digest field of the returned distribution.Descriptor
|
||||
// which only makes use of the Digest field of the returned v1.Descriptor
|
||||
// but does not enable full roundtripping of Descriptor objects
|
||||
type tagStore struct {
|
||||
repository *repository
|
||||
@@ -60,7 +61,7 @@ func (ts *tagStore) All(ctx context.Context) ([]string, error) {
|
||||
|
||||
// Tag tags the digest with the given tag, updating the store to point at
|
||||
// the current tag. The digest must point to a manifest.
|
||||
func (ts *tagStore) Tag(ctx context.Context, tag string, desc distribution.Descriptor) error {
|
||||
func (ts *tagStore) Tag(ctx context.Context, tag string, desc v1.Descriptor) error {
|
||||
currentPath, err := pathFor(manifestTagCurrentPathSpec{
|
||||
name: ts.repository.Named().Name(),
|
||||
tag: tag,
|
||||
@@ -81,26 +82,26 @@ func (ts *tagStore) Tag(ctx context.Context, tag string, desc distribution.Descr
|
||||
}
|
||||
|
||||
// resolve the current revision for name and tag.
|
||||
func (ts *tagStore) Get(ctx context.Context, tag string) (distribution.Descriptor, error) {
|
||||
func (ts *tagStore) Get(ctx context.Context, tag string) (v1.Descriptor, error) {
|
||||
currentPath, err := pathFor(manifestTagCurrentPathSpec{
|
||||
name: ts.repository.Named().Name(),
|
||||
tag: tag,
|
||||
})
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
|
||||
revision, err := ts.blobStore.readlink(ctx, currentPath)
|
||||
if err != nil {
|
||||
switch err.(type) {
|
||||
case storagedriver.PathNotFoundError:
|
||||
return distribution.Descriptor{}, distribution.ErrTagUnknown{Tag: tag}
|
||||
return v1.Descriptor{}, distribution.ErrTagUnknown{Tag: tag}
|
||||
}
|
||||
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
|
||||
return distribution.Descriptor{Digest: revision}, nil
|
||||
return v1.Descriptor{Digest: revision}, nil
|
||||
}
|
||||
|
||||
// Untag removes the tag association
|
||||
@@ -137,7 +138,7 @@ func (ts *tagStore) linkedBlobStore(ctx context.Context, tag string) *linkedBlob
|
||||
|
||||
// Lookup recovers a list of tags which refer to this digest. When a manifest is deleted by
|
||||
// digest, tag entries which point to it need to be recovered to avoid dangling tags.
|
||||
func (ts *tagStore) Lookup(ctx context.Context, desc distribution.Descriptor) ([]string, error) {
|
||||
func (ts *tagStore) Lookup(ctx context.Context, desc v1.Descriptor) ([]string, error) {
|
||||
allTags, err := ts.All(ctx)
|
||||
switch err.(type) {
|
||||
case distribution.ErrRepositoryUnknown:
|
||||
|
@@ -11,6 +11,7 @@ import (
|
||||
"github.com/distribution/reference"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
"github.com/opencontainers/image-spec/specs-go"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
type tagsTestEnv struct {
|
||||
@@ -53,7 +54,7 @@ func TestTagStoreTag(t *testing.T) {
|
||||
tags := env.ts
|
||||
ctx := env.ctx
|
||||
|
||||
d := distribution.Descriptor{}
|
||||
d := v1.Descriptor{}
|
||||
err := tags.Tag(ctx, "latest", d)
|
||||
if err == nil {
|
||||
t.Errorf("unexpected error putting malformed descriptor : %s", err)
|
||||
@@ -95,7 +96,7 @@ func TestTagStoreUnTag(t *testing.T) {
|
||||
env := testTagStore(t)
|
||||
tags := env.ts
|
||||
ctx := env.ctx
|
||||
desc := distribution.Descriptor{Digest: "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"}
|
||||
desc := v1.Descriptor{Digest: "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"}
|
||||
|
||||
err := tags.Untag(ctx, "latest")
|
||||
if err == nil {
|
||||
@@ -127,7 +128,7 @@ func TestTagStoreAll(t *testing.T) {
|
||||
alpha := "abcdefghijklmnopqrstuvwxyz"
|
||||
for i := 0; i < len(alpha); i++ {
|
||||
tag := alpha[i]
|
||||
desc := distribution.Descriptor{Digest: "sha256:eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"}
|
||||
desc := v1.Descriptor{Digest: "sha256:eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"}
|
||||
err := tagStore.Tag(ctx, string(tag), desc)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
@@ -170,8 +171,8 @@ func TestTagLookup(t *testing.T) {
|
||||
tagStore := env.ts
|
||||
ctx := env.ctx
|
||||
|
||||
descA := distribution.Descriptor{Digest: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}
|
||||
desc0 := distribution.Descriptor{Digest: "sha256:0000000000000000000000000000000000000000000000000000000000000000"}
|
||||
descA := v1.Descriptor{Digest: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}
|
||||
desc0 := v1.Descriptor{Digest: "sha256:0000000000000000000000000000000000000000000000000000000000000000"}
|
||||
|
||||
tags, err := tagStore.Lookup(ctx, descA)
|
||||
if err != nil {
|
||||
@@ -245,12 +246,12 @@ func TestTagIndexes(t *testing.T) {
|
||||
m := schema2.Manifest{
|
||||
Versioned: specs.Versioned{SchemaVersion: 2},
|
||||
MediaType: schema2.MediaTypeManifest,
|
||||
Config: distribution.Descriptor{
|
||||
Config: v1.Descriptor{
|
||||
Digest: conf.Digest,
|
||||
Size: 1,
|
||||
MediaType: schema2.MediaTypeImageConfig,
|
||||
},
|
||||
Layers: []distribution.Descriptor{
|
||||
Layers: []v1.Descriptor{
|
||||
{
|
||||
Digest: layer.Digest,
|
||||
Size: 1,
|
||||
|
Reference in New Issue
Block a user