mirror of
https://github.com/distribution/distribution.git
synced 2026-10-28 10:15:27 +08:00
replace uses of Descriptor alias
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
54 files changed
+417
-381
No files matched your search
@@ -68,7 +68,7 @@ type Descriptor = v1.Descriptor
|
||||
type BlobStatter interface {
|
||||
// Stat provides metadata about a blob identified by the digest. If the
|
||||
// blob is unknown to the describer, ErrBlobUnknown will be returned.
|
||||
Stat(ctx context.Context, dgst digest.Digest) (Descriptor, error)
|
||||
Stat(ctx context.Context, dgst digest.Digest) (v1.Descriptor, error)
|
||||
}
|
||||
|
||||
// BlobDeleter enables deleting blobs from storage.
|
||||
@@ -97,7 +97,7 @@ type BlobDescriptorService interface {
|
||||
// Such a facility can be used to map blobs between digest domains, with
|
||||
// the restriction that the algorithm of the descriptor must match the
|
||||
// canonical algorithm (ie sha256) of the annotator.
|
||||
SetDescriptor(ctx context.Context, dgst digest.Digest, desc Descriptor) error
|
||||
SetDescriptor(ctx context.Context, dgst digest.Digest, desc v1.Descriptor) error
|
||||
|
||||
// Clear enables descriptors to be unlinked
|
||||
Clear(ctx context.Context, dgst digest.Digest) error
|
||||
@@ -139,7 +139,7 @@ type BlobServer interface {
|
||||
type BlobIngester interface {
|
||||
// Put inserts the content p into the blob service, returning a descriptor
|
||||
// or an error.
|
||||
Put(ctx context.Context, mediaType string, p []byte) (Descriptor, error)
|
||||
Put(ctx context.Context, mediaType string, p []byte) (v1.Descriptor, error)
|
||||
|
||||
// Create allocates a new blob writer to add a blob to this service. The
|
||||
// returned handle can be written to and later resumed using an opaque
|
||||
@@ -168,7 +168,7 @@ type CreateOptions struct {
|
||||
From reference.Canonical
|
||||
// Stat allows to pass precalculated descriptor to link and return.
|
||||
// Blob access check will be skipped if set.
|
||||
Stat *Descriptor
|
||||
Stat *v1.Descriptor
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,7 +198,7 @@ type BlobWriter interface {
|
||||
// stream" to the blob. The returned descriptor may have a different
|
||||
// digest depending on the blob store, referred to as the canonical
|
||||
// descriptor.
|
||||
Commit(ctx context.Context, provisional Descriptor) (canonical Descriptor, err error)
|
||||
Commit(ctx context.Context, provisional v1.Descriptor) (canonical v1.Descriptor, err error)
|
||||
|
||||
// Cancel ends the blob write without storing any data and frees any
|
||||
// associated resources. Any data written thus far will be lost. Cancel
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/distribution/distribution/v3"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
type httpBlobUpload struct {
|
||||
@@ -120,11 +121,11 @@ func (hbu *httpBlobUpload) StartedAt() time.Time {
|
||||
return hbu.startedAt
|
||||
}
|
||||
|
||||
func (hbu *httpBlobUpload) Commit(ctx context.Context, desc distribution.Descriptor) (distribution.Descriptor, error) {
|
||||
func (hbu *httpBlobUpload) Commit(ctx context.Context, desc v1.Descriptor) (v1.Descriptor, error) {
|
||||
// TODO(dmcgowan): Check if already finished, if so just fetch
|
||||
req, err := http.NewRequestWithContext(hbu.ctx, http.MethodPut, hbu.location, nil)
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
|
||||
values := req.URL.Query()
|
||||
@@ -133,12 +134,12 @@ func (hbu *httpBlobUpload) Commit(ctx context.Context, desc distribution.Descrip
|
||||
|
||||
resp, err := hbu.client.Do(req)
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if err := hbu.handleErrorResponse(resp); err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
|
||||
return hbu.statter.Stat(ctx, desc.Digest)
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"github.com/distribution/distribution/v3/registry/storage/cache/memory"
|
||||
"github.com/distribution/reference"
|
||||
"github.com/opencontainers/go-digest"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
// Registry provides an interface for calling Repositories, which returns a catalog of repositories.
|
||||
@@ -249,13 +250,13 @@ func (t *tags) All(ctx context.Context) ([]string, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func descriptorFromResponse(response *http.Response) (distribution.Descriptor, error) {
|
||||
desc := distribution.Descriptor{}
|
||||
func descriptorFromResponse(response *http.Response) (v1.Descriptor, error) {
|
||||
desc := v1.Descriptor{}
|
||||
headers := response.Header
|
||||
|
||||
ctHeader := headers.Get("Content-Type")
|
||||
if ctHeader == "" {
|
||||
return distribution.Descriptor{}, errors.New("missing or empty Content-Type header")
|
||||
return v1.Descriptor{}, errors.New("missing or empty Content-Type header")
|
||||
}
|
||||
desc.MediaType = ctHeader
|
||||
|
||||
@@ -263,28 +264,28 @@ func descriptorFromResponse(response *http.Response) (distribution.Descriptor, e
|
||||
if digestHeader == "" {
|
||||
data, err := io.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
_, desc, err := distribution.UnmarshalManifest(ctHeader, data)
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
return desc, nil
|
||||
}
|
||||
|
||||
dgst, err := digest.Parse(digestHeader)
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
desc.Digest = dgst
|
||||
|
||||
lengthHeader := headers.Get("Content-Length")
|
||||
if lengthHeader == "" {
|
||||
return distribution.Descriptor{}, errors.New("missing or empty Content-Length header")
|
||||
return v1.Descriptor{}, errors.New("missing or empty Content-Length header")
|
||||
}
|
||||
length, err := strconv.ParseInt(lengthHeader, 10, 64)
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
desc.Size = length
|
||||
|
||||
@@ -294,14 +295,14 @@ func descriptorFromResponse(response *http.Response) (distribution.Descriptor, e
|
||||
// Get issues a HEAD request for a Manifest against its named endpoint in order
|
||||
// to construct a descriptor for the tag. If the registry doesn't support HEADing
|
||||
// a manifest, fallback to GET.
|
||||
func (t *tags) Get(ctx context.Context, tag string) (distribution.Descriptor, error) {
|
||||
func (t *tags) Get(ctx context.Context, tag string) (v1.Descriptor, error) {
|
||||
ref, err := reference.WithTag(t.name, tag)
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
u, err := t.ub.BuildManifestURL(ref)
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
|
||||
newRequest := func(method string) (*http.Response, error) {
|
||||
@@ -319,7 +320,7 @@ func (t *tags) Get(ctx context.Context, tag string) (distribution.Descriptor, er
|
||||
|
||||
resp, err := newRequest(http.MethodHead)
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
@@ -334,22 +335,22 @@ func (t *tags) Get(ctx context.Context, tag string) (distribution.Descriptor, er
|
||||
// - to get error details in case of a failure
|
||||
resp, err = newRequest(http.MethodGet)
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode >= 200 && resp.StatusCode < 400 {
|
||||
return descriptorFromResponse(resp)
|
||||
}
|
||||
return distribution.Descriptor{}, HandleHTTPResponseError(resp)
|
||||
return v1.Descriptor{}, HandleHTTPResponseError(resp)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *tags) Lookup(ctx context.Context, digest distribution.Descriptor) ([]string, error) {
|
||||
func (t *tags) Lookup(ctx context.Context, digest v1.Descriptor) ([]string, error) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func (t *tags) Tag(ctx context.Context, tag string, desc distribution.Descriptor) error {
|
||||
func (t *tags) Tag(ctx context.Context, tag string, desc v1.Descriptor) error {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
@@ -654,7 +655,7 @@ func sanitizeLocation(location, base string) (string, error) {
|
||||
return baseURL.ResolveReference(locationURL).String(), nil
|
||||
}
|
||||
|
||||
func (bs *blobs) Stat(ctx context.Context, dgst digest.Digest) (distribution.Descriptor, error) {
|
||||
func (bs *blobs) Stat(ctx context.Context, dgst digest.Digest) (v1.Descriptor, error) {
|
||||
return bs.statter.Stat(ctx, dgst)
|
||||
}
|
||||
|
||||
@@ -711,21 +712,21 @@ func (bs *blobs) ServeBlob(ctx context.Context, w http.ResponseWriter, r *http.R
|
||||
return err
|
||||
}
|
||||
|
||||
func (bs *blobs) Put(ctx context.Context, mediaType string, p []byte) (distribution.Descriptor, error) {
|
||||
func (bs *blobs) Put(ctx context.Context, mediaType string, p []byte) (v1.Descriptor, error) {
|
||||
writer, err := bs.Create(ctx)
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
dgstr := digest.Canonical.Digester()
|
||||
n, err := io.Copy(writer, io.TeeReader(bytes.NewReader(p), dgstr.Hash()))
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
if n < int64(len(p)) {
|
||||
return distribution.Descriptor{}, fmt.Errorf("short copy: wrote %d of %d", n, len(p))
|
||||
return v1.Descriptor{}, fmt.Errorf("short copy: wrote %d of %d", n, len(p))
|
||||
}
|
||||
|
||||
return writer.Commit(ctx, distribution.Descriptor{
|
||||
return writer.Commit(ctx, v1.Descriptor{
|
||||
MediaType: mediaType,
|
||||
Size: int64(len(p)),
|
||||
Digest: dgstr.Digest(),
|
||||
@@ -848,45 +849,45 @@ type blobStatter struct {
|
||||
client *http.Client
|
||||
}
|
||||
|
||||
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) {
|
||||
ref, err := reference.WithDigest(bs.name, dgst)
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
u, err := bs.ub.BuildBlobURL(ref)
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodHead, u, nil)
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
resp, err := bs.client.Do(req)
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode == http.StatusNotFound {
|
||||
return distribution.Descriptor{}, distribution.ErrBlobUnknown
|
||||
return v1.Descriptor{}, distribution.ErrBlobUnknown
|
||||
}
|
||||
|
||||
if err := HandleHTTPResponseError(resp); err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
|
||||
lengthHeader := resp.Header.Get("Content-Length")
|
||||
if lengthHeader == "" {
|
||||
return distribution.Descriptor{}, fmt.Errorf("missing content-length header for request: %s", u)
|
||||
return v1.Descriptor{}, fmt.Errorf("missing content-length header for request: %s", u)
|
||||
}
|
||||
|
||||
length, err := strconv.ParseInt(lengthHeader, 10, 64)
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, fmt.Errorf("error parsing content-length: %v", err)
|
||||
return v1.Descriptor{}, fmt.Errorf("error parsing content-length: %v", err)
|
||||
}
|
||||
|
||||
return distribution.Descriptor{
|
||||
return v1.Descriptor{
|
||||
MediaType: resp.Header.Get("Content-Type"),
|
||||
Size: length,
|
||||
Digest: dgst,
|
||||
@@ -931,6 +932,6 @@ func (bs *blobStatter) Clear(ctx context.Context, dgst digest.Digest) error {
|
||||
return HandleHTTPResponseError(resp)
|
||||
}
|
||||
|
||||
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 nil
|
||||
}
|
||||
@@ -274,7 +274,7 @@ func TestBlobResume(t *testing.T) {
|
||||
t.Fatalf("Unexpected ReadFrom length: %d; expected: %d", n, len(b1))
|
||||
}
|
||||
|
||||
blob, err := upload.Commit(ctx, distribution.Descriptor{
|
||||
blob, err := upload.Commit(ctx, v1.Descriptor{
|
||||
Digest: dgst,
|
||||
Size: int64(len(b1)),
|
||||
})
|
||||
@@ -538,7 +538,7 @@ func TestBlobUploadChunked(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
blob, err := upload.Commit(ctx, distribution.Descriptor{
|
||||
blob, err := upload.Commit(ctx, v1.Descriptor{
|
||||
Digest: dgst,
|
||||
Size: int64(len(b1)),
|
||||
})
|
||||
@@ -646,7 +646,7 @@ func TestBlobUploadMonolithic(t *testing.T) {
|
||||
t.Fatalf("Unexpected ReadFrom length: %d; expected: %d", n, len(b1))
|
||||
}
|
||||
|
||||
blob, err := upload.Commit(ctx, distribution.Descriptor{
|
||||
blob, err := upload.Commit(ctx, v1.Descriptor{
|
||||
Digest: dgst,
|
||||
Size: int64(len(b1)),
|
||||
})
|
||||
@@ -752,7 +752,7 @@ func TestBlobUploadMonolithicDockerUploadUUIDFromURL(t *testing.T) {
|
||||
t.Fatalf("Unexpected ReadFrom length: %d; expected: %d", n, len(b1))
|
||||
}
|
||||
|
||||
blob, err := upload.Commit(ctx, distribution.Descriptor{
|
||||
blob, err := upload.Commit(ctx, v1.Descriptor{
|
||||
Digest: dgst,
|
||||
Size: int64(len(b1)),
|
||||
})
|
||||
@@ -917,10 +917,10 @@ func TestBlobMount(t *testing.T) {
|
||||
}
|
||||
|
||||
func newRandomOCIManifest(t *testing.T, blobCount int) (*ocischema.Manifest, digest.Digest, []byte) {
|
||||
layers := make([]distribution.Descriptor, blobCount)
|
||||
layers := make([]v1.Descriptor, blobCount)
|
||||
for i := 0; i < blobCount; i++ {
|
||||
dgst, blob := newRandomBlob((i % 5) * 16)
|
||||
layers[i] = distribution.Descriptor{
|
||||
layers[i] = v1.Descriptor{
|
||||
MediaType: v1.MediaTypeImageLayer,
|
||||
Digest: dgst,
|
||||
Size: int64(len(blob)),
|
||||
@@ -930,7 +930,7 @@ func newRandomOCIManifest(t *testing.T, blobCount int) (*ocischema.Manifest, dig
|
||||
m := ocischema.Manifest{
|
||||
Versioned: specs.Versioned{SchemaVersion: 2},
|
||||
MediaType: v1.MediaTypeImageManifest,
|
||||
Config: distribution.Descriptor{
|
||||
Config: v1.Descriptor{
|
||||
Digest: "sha256:1a9ec845ee94c202b2d5da74a24f0ed2058318bfa9879fa541efaecba272e86b",
|
||||
Size: 123,
|
||||
MediaType: v1.MediaTypeImageConfig,
|
||||
|
||||
@@ -35,17 +35,17 @@ func init() {
|
||||
}
|
||||
}
|
||||
|
||||
func unmarshalManifestList(b []byte) (distribution.Manifest, distribution.Descriptor, error) {
|
||||
func unmarshalManifestList(b []byte) (distribution.Manifest, v1.Descriptor, error) {
|
||||
m := &DeserializedManifestList{}
|
||||
if err := m.UnmarshalJSON(b); err != nil {
|
||||
return nil, distribution.Descriptor{}, err
|
||||
return nil, v1.Descriptor{}, err
|
||||
}
|
||||
|
||||
if m.MediaType != MediaTypeManifestList {
|
||||
return nil, distribution.Descriptor{}, fmt.Errorf("mediaType in manifest list should be '%s' not '%s'", MediaTypeManifestList, m.MediaType)
|
||||
return nil, v1.Descriptor{}, fmt.Errorf("mediaType in manifest list should be '%s' not '%s'", MediaTypeManifestList, m.MediaType)
|
||||
}
|
||||
|
||||
return m, distribution.Descriptor{
|
||||
return m, v1.Descriptor{
|
||||
Digest: digest.FromBytes(b),
|
||||
Size: int64(len(b)),
|
||||
MediaType: MediaTypeManifestList,
|
||||
@@ -81,7 +81,7 @@ type PlatformSpec struct {
|
||||
|
||||
// A ManifestDescriptor references a platform-specific manifest.
|
||||
type ManifestDescriptor struct {
|
||||
distribution.Descriptor
|
||||
v1.Descriptor
|
||||
|
||||
// Platform specifies which platform the manifest pointed to by the
|
||||
// descriptor runs on.
|
||||
@@ -101,8 +101,8 @@ type ManifestList struct {
|
||||
|
||||
// References returns the distribution descriptors for the referenced image
|
||||
// manifests.
|
||||
func (m ManifestList) References() []distribution.Descriptor {
|
||||
dependencies := make([]distribution.Descriptor, len(m.Manifests))
|
||||
func (m ManifestList) References() []v1.Descriptor {
|
||||
dependencies := make([]v1.Descriptor, len(m.Manifests))
|
||||
for i := range m.Manifests {
|
||||
dependencies[i] = m.Manifests[i].Descriptor
|
||||
dependencies[i].Platform = &v1.Platform{
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
|
||||
"github.com/distribution/distribution/v3"
|
||||
"github.com/distribution/distribution/v3/manifest/schema2"
|
||||
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
@@ -43,7 +42,7 @@ const expectedManifestListSerialization = `{
|
||||
func makeTestManifestList(t *testing.T, mediaType string) ([]ManifestDescriptor, *DeserializedManifestList) {
|
||||
manifestDescriptors := []ManifestDescriptor{
|
||||
{
|
||||
Descriptor: distribution.Descriptor{
|
||||
Descriptor: v1.Descriptor{
|
||||
MediaType: "application/vnd.docker.distribution.manifest.v2+json",
|
||||
Digest: "sha256:1a9ec845ee94c202b2d5da74a24f0ed2058318bfa9879fa541efaecba272e86b",
|
||||
Size: 985,
|
||||
@@ -55,7 +54,7 @@ func makeTestManifestList(t *testing.T, mediaType string) ([]ManifestDescriptor,
|
||||
},
|
||||
},
|
||||
{
|
||||
Descriptor: distribution.Descriptor{
|
||||
Descriptor: v1.Descriptor{
|
||||
MediaType: "application/vnd.docker.distribution.manifest.v2+json",
|
||||
Digest: "sha256:6346340964309634683409684360934680934608934608934608934068934608",
|
||||
Size: 2392,
|
||||
@@ -178,12 +177,12 @@ func TestMediaTypes(t *testing.T) {
|
||||
|
||||
func TestValidateManifestList(t *testing.T) {
|
||||
manifest := schema2.Manifest{
|
||||
Config: distribution.Descriptor{Size: 1},
|
||||
Layers: []distribution.Descriptor{{Size: 2}},
|
||||
Config: v1.Descriptor{Size: 1},
|
||||
Layers: []v1.Descriptor{{Size: 2}},
|
||||
}
|
||||
manifestList := ManifestList{
|
||||
Manifests: []ManifestDescriptor{
|
||||
{Descriptor: distribution.Descriptor{Size: 3}},
|
||||
{Descriptor: v1.Descriptor{Size: 3}},
|
||||
},
|
||||
}
|
||||
t.Run("valid", func(t *testing.T) {
|
||||
|
||||
@@ -20,7 +20,7 @@ type Builder struct {
|
||||
|
||||
// layers is a list of layer descriptors that gets built by successive
|
||||
// calls to AppendReference.
|
||||
layers []distribution.Descriptor
|
||||
layers []v1.Descriptor
|
||||
|
||||
// Annotations contains arbitrary metadata relating to the targeted content.
|
||||
annotations map[string]string
|
||||
@@ -60,7 +60,7 @@ func (mb *Builder) Build(ctx context.Context) (distribution.Manifest, error) {
|
||||
m := Manifest{
|
||||
Versioned: specs.Versioned{SchemaVersion: 2},
|
||||
MediaType: mb.mediaType,
|
||||
Layers: make([]distribution.Descriptor, len(mb.layers)),
|
||||
Layers: make([]v1.Descriptor, len(mb.layers)),
|
||||
Annotations: mb.annotations,
|
||||
}
|
||||
copy(m.Layers, mb.layers)
|
||||
@@ -94,12 +94,12 @@ func (mb *Builder) Build(ctx context.Context) (distribution.Manifest, error) {
|
||||
}
|
||||
|
||||
// AppendReference adds a reference to the current ManifestBuilder.
|
||||
func (mb *Builder) AppendReference(ref distribution.Descriptor) error {
|
||||
func (mb *Builder) AppendReference(ref v1.Descriptor) error {
|
||||
mb.layers = append(mb.layers, ref)
|
||||
return nil
|
||||
}
|
||||
|
||||
// References returns the current references added to this builder.
|
||||
func (mb *Builder) References() []distribution.Descriptor {
|
||||
func (mb *Builder) References() []v1.Descriptor {
|
||||
return mb.layers
|
||||
}
|
||||
@@ -11,19 +11,19 @@ import (
|
||||
)
|
||||
|
||||
type mockBlobService struct {
|
||||
descriptors map[digest.Digest]distribution.Descriptor
|
||||
descriptors map[digest.Digest]v1.Descriptor
|
||||
distribution.BlobService
|
||||
}
|
||||
|
||||
func (bs *mockBlobService) Stat(ctx context.Context, dgst digest.Digest) (distribution.Descriptor, error) {
|
||||
func (bs *mockBlobService) Stat(ctx context.Context, dgst digest.Digest) (v1.Descriptor, error) {
|
||||
if descriptor, ok := bs.descriptors[dgst]; ok {
|
||||
return descriptor, nil
|
||||
}
|
||||
return distribution.Descriptor{}, distribution.ErrBlobUnknown
|
||||
return v1.Descriptor{}, distribution.ErrBlobUnknown
|
||||
}
|
||||
|
||||
func (bs *mockBlobService) Put(ctx context.Context, mediaType string, p []byte) (distribution.Descriptor, error) {
|
||||
d := distribution.Descriptor{
|
||||
func (bs *mockBlobService) Put(ctx context.Context, mediaType string, p []byte) (v1.Descriptor, error) {
|
||||
d := v1.Descriptor{
|
||||
Digest: digest.FromBytes(p),
|
||||
Size: int64(len(p)),
|
||||
MediaType: "application/octet-stream",
|
||||
@@ -90,7 +90,7 @@ func TestBuilder(t *testing.T) {
|
||||
}`)
|
||||
configDigest := digest.FromBytes(imgJSON)
|
||||
|
||||
descriptors := []distribution.Descriptor{
|
||||
descriptors := []v1.Descriptor{
|
||||
{
|
||||
MediaType: v1.MediaTypeImageLayerGzip,
|
||||
Digest: digest.Digest("sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4"),
|
||||
@@ -110,7 +110,7 @@ func TestBuilder(t *testing.T) {
|
||||
}
|
||||
annotations := map[string]string{"hot": "potato"}
|
||||
|
||||
bs := &mockBlobService{descriptors: make(map[digest.Digest]distribution.Descriptor)}
|
||||
bs := &mockBlobService{descriptors: make(map[digest.Digest]v1.Descriptor)}
|
||||
builder := NewManifestBuilder(bs, imgJSON, annotations)
|
||||
|
||||
for _, d := range descriptors {
|
||||
@@ -151,7 +151,7 @@ func TestBuilder(t *testing.T) {
|
||||
}
|
||||
|
||||
references := manifest.References()
|
||||
expected := append([]distribution.Descriptor{manifest.Target()}, descriptors...)
|
||||
expected := append([]v1.Descriptor{manifest.Target()}, descriptors...)
|
||||
if !reflect.DeepEqual(references, expected) {
|
||||
t.Fatal("References() does not match the descriptors added")
|
||||
}
|
||||
|
||||
+10
-10
@@ -30,21 +30,21 @@ func init() {
|
||||
}
|
||||
}
|
||||
|
||||
func unmarshalImageIndex(b []byte) (distribution.Manifest, distribution.Descriptor, error) {
|
||||
func unmarshalImageIndex(b []byte) (distribution.Manifest, v1.Descriptor, error) {
|
||||
if err := validateIndex(b); err != nil {
|
||||
return nil, distribution.Descriptor{}, err
|
||||
return nil, v1.Descriptor{}, err
|
||||
}
|
||||
|
||||
m := &DeserializedImageIndex{}
|
||||
if err := m.UnmarshalJSON(b); err != nil {
|
||||
return nil, distribution.Descriptor{}, err
|
||||
return nil, v1.Descriptor{}, err
|
||||
}
|
||||
|
||||
if m.MediaType != "" && m.MediaType != v1.MediaTypeImageIndex {
|
||||
return nil, distribution.Descriptor{}, fmt.Errorf("if present, mediaType in image index should be '%s' not '%s'", v1.MediaTypeImageIndex, m.MediaType)
|
||||
return nil, v1.Descriptor{}, fmt.Errorf("if present, mediaType in image index should be '%s' not '%s'", v1.MediaTypeImageIndex, m.MediaType)
|
||||
}
|
||||
|
||||
return m, distribution.Descriptor{
|
||||
return m, v1.Descriptor{
|
||||
MediaType: v1.MediaTypeImageIndex,
|
||||
Digest: digest.FromBytes(b),
|
||||
Size: int64(len(b)),
|
||||
@@ -60,7 +60,7 @@ type ImageIndex struct {
|
||||
MediaType string `json:"mediaType,omitempty"`
|
||||
|
||||
// Manifests references a list of manifests
|
||||
Manifests []distribution.Descriptor `json:"manifests"`
|
||||
Manifests []v1.Descriptor `json:"manifests"`
|
||||
|
||||
// Annotations is an optional field that contains arbitrary metadata for the
|
||||
// image index
|
||||
@@ -69,7 +69,7 @@ type ImageIndex struct {
|
||||
|
||||
// References returns the distribution descriptors for the referenced image
|
||||
// manifests.
|
||||
func (ii ImageIndex) References() []distribution.Descriptor {
|
||||
func (ii ImageIndex) References() []v1.Descriptor {
|
||||
return ii.Manifests
|
||||
}
|
||||
|
||||
@@ -86,19 +86,19 @@ type DeserializedImageIndex struct {
|
||||
// returns a DeserializedManifestList which contains the resulting manifest list
|
||||
// and its JSON representation. If annotations is nil or empty then the
|
||||
// annotations property will be omitted from the JSON representation.
|
||||
func FromDescriptors(descriptors []distribution.Descriptor, annotations map[string]string) (*DeserializedImageIndex, error) {
|
||||
func FromDescriptors(descriptors []v1.Descriptor, annotations map[string]string) (*DeserializedImageIndex, error) {
|
||||
return fromDescriptorsWithMediaType(descriptors, annotations, v1.MediaTypeImageIndex)
|
||||
}
|
||||
|
||||
// fromDescriptorsWithMediaType is for testing purposes, it's useful to be able to specify the media type explicitly
|
||||
func fromDescriptorsWithMediaType(descriptors []distribution.Descriptor, annotations map[string]string, mediaType string) (_ *DeserializedImageIndex, err error) {
|
||||
func fromDescriptorsWithMediaType(descriptors []v1.Descriptor, annotations map[string]string, mediaType string) (_ *DeserializedImageIndex, err error) {
|
||||
m := ImageIndex{
|
||||
Versioned: specs.Versioned{SchemaVersion: 2},
|
||||
MediaType: mediaType,
|
||||
Annotations: annotations,
|
||||
}
|
||||
|
||||
m.Manifests = make([]distribution.Descriptor, len(descriptors))
|
||||
m.Manifests = make([]v1.Descriptor, len(descriptors))
|
||||
copy(m.Manifests, descriptors)
|
||||
|
||||
deserialized := DeserializedImageIndex{
|
||||
|
||||
@@ -52,8 +52,8 @@ const expectedOCIImageIndexSerialization = `{
|
||||
}
|
||||
}`
|
||||
|
||||
func makeTestOCIImageIndex(t *testing.T, mediaType string) ([]distribution.Descriptor, *DeserializedImageIndex) {
|
||||
manifestDescriptors := []distribution.Descriptor{
|
||||
func makeTestOCIImageIndex(t *testing.T, mediaType string) ([]v1.Descriptor, *DeserializedImageIndex) {
|
||||
manifestDescriptors := []v1.Descriptor{
|
||||
{
|
||||
MediaType: "application/vnd.oci.image.manifest.v1+json",
|
||||
Digest: "sha256:1a9ec845ee94c202b2d5da74a24f0ed2058318bfa9879fa541efaecba272e86b",
|
||||
@@ -207,11 +207,11 @@ func TestIndexMediaTypes(t *testing.T) {
|
||||
|
||||
func TestValidateIndex(t *testing.T) {
|
||||
manifest := schema2.Manifest{
|
||||
Config: distribution.Descriptor{Size: 1},
|
||||
Layers: []distribution.Descriptor{{Size: 2}},
|
||||
Config: v1.Descriptor{Size: 1},
|
||||
Layers: []v1.Descriptor{{Size: 2}},
|
||||
}
|
||||
index := ImageIndex{
|
||||
Manifests: []distribution.Descriptor{{Size: 3}},
|
||||
Manifests: []v1.Descriptor{{Size: 3}},
|
||||
}
|
||||
t.Run("valid", func(t *testing.T) {
|
||||
b, err := json.Marshal(index)
|
||||
|
||||
@@ -30,17 +30,17 @@ func init() {
|
||||
}
|
||||
}
|
||||
|
||||
func unmarshalOCISchema(b []byte) (distribution.Manifest, distribution.Descriptor, error) {
|
||||
func unmarshalOCISchema(b []byte) (distribution.Manifest, v1.Descriptor, error) {
|
||||
if err := validateManifest(b); err != nil {
|
||||
return nil, distribution.Descriptor{}, err
|
||||
return nil, v1.Descriptor{}, err
|
||||
}
|
||||
|
||||
m := &DeserializedManifest{}
|
||||
if err := m.UnmarshalJSON(b); err != nil {
|
||||
return nil, distribution.Descriptor{}, err
|
||||
return nil, v1.Descriptor{}, err
|
||||
}
|
||||
|
||||
return m, distribution.Descriptor{
|
||||
return m, v1.Descriptor{
|
||||
MediaType: v1.MediaTypeImageManifest,
|
||||
Digest: digest.FromBytes(b),
|
||||
Size: int64(len(b)),
|
||||
@@ -56,26 +56,26 @@ type Manifest struct {
|
||||
MediaType string `json:"mediaType,omitempty"`
|
||||
|
||||
// Config references the image configuration as a blob.
|
||||
Config distribution.Descriptor `json:"config"`
|
||||
Config v1.Descriptor `json:"config"`
|
||||
|
||||
// Layers lists descriptors for the layers referenced by the
|
||||
// configuration.
|
||||
Layers []distribution.Descriptor `json:"layers"`
|
||||
Layers []v1.Descriptor `json:"layers"`
|
||||
|
||||
// Annotations contains arbitrary metadata for the image manifest.
|
||||
Annotations map[string]string `json:"annotations,omitempty"`
|
||||
}
|
||||
|
||||
// References returns the descriptors of this manifests references.
|
||||
func (m Manifest) References() []distribution.Descriptor {
|
||||
references := make([]distribution.Descriptor, 0, 1+len(m.Layers))
|
||||
func (m Manifest) References() []v1.Descriptor {
|
||||
references := make([]v1.Descriptor, 0, 1+len(m.Layers))
|
||||
references = append(references, m.Config)
|
||||
references = append(references, m.Layers...)
|
||||
return references
|
||||
}
|
||||
|
||||
// Target returns the target of this manifest.
|
||||
func (m Manifest) Target() distribution.Descriptor {
|
||||
func (m Manifest) Target() v1.Descriptor {
|
||||
return m.Config
|
||||
}
|
||||
|
||||
|
||||
@@ -8,9 +8,8 @@ import (
|
||||
|
||||
"github.com/distribution/distribution/v3"
|
||||
"github.com/distribution/distribution/v3/manifest/manifestlist"
|
||||
"github.com/opencontainers/image-spec/specs-go"
|
||||
|
||||
"github.com/opencontainers/go-digest"
|
||||
"github.com/opencontainers/image-spec/specs-go"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
@@ -44,13 +43,13 @@ func makeTestManifest(mediaType string) Manifest {
|
||||
return Manifest{
|
||||
Versioned: specs.Versioned{SchemaVersion: 2},
|
||||
MediaType: mediaType,
|
||||
Config: distribution.Descriptor{
|
||||
Config: v1.Descriptor{
|
||||
MediaType: v1.MediaTypeImageConfig,
|
||||
Digest: "sha256:1a9ec845ee94c202b2d5da74a24f0ed2058318bfa9879fa541efaecba272e86b",
|
||||
Size: 985,
|
||||
Annotations: map[string]string{"apple": "orange"},
|
||||
},
|
||||
Layers: []distribution.Descriptor{
|
||||
Layers: []v1.Descriptor{
|
||||
{
|
||||
MediaType: v1.MediaTypeImageLayerGzip,
|
||||
Digest: "sha256:62d8908bee94c202b2d35224a221aaa2058318bfa9879fa541efaecba272331b",
|
||||
@@ -217,12 +216,12 @@ func TestManifestMediaTypes(t *testing.T) {
|
||||
|
||||
func TestValidateManifest(t *testing.T) {
|
||||
mfst := Manifest{
|
||||
Config: distribution.Descriptor{Size: 1},
|
||||
Layers: []distribution.Descriptor{{Size: 2}},
|
||||
Config: v1.Descriptor{Size: 1},
|
||||
Layers: []v1.Descriptor{{Size: 2}},
|
||||
}
|
||||
index := manifestlist.ManifestList{
|
||||
Manifests: []manifestlist.ManifestDescriptor{
|
||||
{Descriptor: distribution.Descriptor{Size: 3}},
|
||||
{Descriptor: v1.Descriptor{Size: 3}},
|
||||
},
|
||||
}
|
||||
t.Run("valid", func(t *testing.T) {
|
||||
|
||||
@@ -5,25 +5,26 @@ import (
|
||||
|
||||
"github.com/distribution/distribution/v3"
|
||||
"github.com/opencontainers/image-spec/specs-go"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
// Builder is a type for constructing manifests.
|
||||
type Builder struct {
|
||||
// configDescriptor is used to describe configuration
|
||||
configDescriptor distribution.Descriptor
|
||||
configDescriptor v1.Descriptor
|
||||
|
||||
// configJSON references
|
||||
configJSON []byte
|
||||
|
||||
// dependencies is a list of descriptors that gets built by successive
|
||||
// calls to AppendReference. In case of image configuration these are layers.
|
||||
dependencies []distribution.Descriptor
|
||||
dependencies []v1.Descriptor
|
||||
}
|
||||
|
||||
// NewManifestBuilder is used to build new manifests for the current schema
|
||||
// version. It takes a BlobService so it can publish the configuration blob
|
||||
// as part of the Build process.
|
||||
func NewManifestBuilder(configDescriptor distribution.Descriptor, configJSON []byte) *Builder {
|
||||
func NewManifestBuilder(configDescriptor v1.Descriptor, configJSON []byte) *Builder {
|
||||
mb := &Builder{
|
||||
configDescriptor: configDescriptor,
|
||||
configJSON: make([]byte, len(configJSON)),
|
||||
@@ -38,7 +39,7 @@ func (mb *Builder) Build(ctx context.Context) (distribution.Manifest, error) {
|
||||
m := Manifest{
|
||||
Versioned: specs.Versioned{SchemaVersion: defaultSchemaVersion},
|
||||
MediaType: defaultMediaType,
|
||||
Layers: make([]distribution.Descriptor, len(mb.dependencies)),
|
||||
Layers: make([]v1.Descriptor, len(mb.dependencies)),
|
||||
}
|
||||
copy(m.Layers, mb.dependencies)
|
||||
|
||||
@@ -48,12 +49,12 @@ func (mb *Builder) Build(ctx context.Context) (distribution.Manifest, error) {
|
||||
}
|
||||
|
||||
// AppendReference adds a reference to the current ManifestBuilder.
|
||||
func (mb *Builder) AppendReference(ref distribution.Descriptor) error {
|
||||
func (mb *Builder) AppendReference(ref v1.Descriptor) error {
|
||||
mb.dependencies = append(mb.dependencies, ref)
|
||||
return nil
|
||||
}
|
||||
|
||||
// References returns the current references added to this builder.
|
||||
func (mb *Builder) References() []distribution.Descriptor {
|
||||
func (mb *Builder) References() []v1.Descriptor {
|
||||
return mb.dependencies
|
||||
}
|
||||
@@ -5,8 +5,8 @@ import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/distribution/distribution/v3"
|
||||
"github.com/opencontainers/go-digest"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
func TestBuilder(t *testing.T) {
|
||||
@@ -110,7 +110,7 @@ func TestBuilder(t *testing.T) {
|
||||
}`)
|
||||
configDigest := digest.FromBytes(imgJSON)
|
||||
|
||||
descriptors := []distribution.Descriptor{
|
||||
descriptors := []v1.Descriptor{
|
||||
{
|
||||
MediaType: MediaTypeLayer,
|
||||
Digest: digest.Digest("sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4"),
|
||||
@@ -128,7 +128,7 @@ func TestBuilder(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
d := distribution.Descriptor{
|
||||
d := v1.Descriptor{
|
||||
Digest: digest.FromBytes(imgJSON),
|
||||
Size: int64(len(imgJSON)),
|
||||
MediaType: MediaTypeImageConfig,
|
||||
@@ -165,7 +165,7 @@ func TestBuilder(t *testing.T) {
|
||||
}
|
||||
|
||||
references := manifest.References()
|
||||
expected := append([]distribution.Descriptor{manifest.Target()}, descriptors...)
|
||||
expected := append([]v1.Descriptor{manifest.Target()}, descriptors...)
|
||||
if !reflect.DeepEqual(references, expected) {
|
||||
t.Fatal("References() does not match the descriptors added")
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/distribution/distribution/v3/manifest"
|
||||
"github.com/opencontainers/go-digest"
|
||||
"github.com/opencontainers/image-spec/specs-go"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -57,13 +58,13 @@ func init() {
|
||||
}
|
||||
}
|
||||
|
||||
func unmarshalSchema2(b []byte) (distribution.Manifest, distribution.Descriptor, error) {
|
||||
func unmarshalSchema2(b []byte) (distribution.Manifest, v1.Descriptor, error) {
|
||||
m := &DeserializedManifest{}
|
||||
if err := m.UnmarshalJSON(b); err != nil {
|
||||
return nil, distribution.Descriptor{}, err
|
||||
return nil, v1.Descriptor{}, err
|
||||
}
|
||||
|
||||
return m, distribution.Descriptor{
|
||||
return m, v1.Descriptor{
|
||||
Digest: digest.FromBytes(b),
|
||||
Size: int64(len(b)),
|
||||
MediaType: defaultMediaType,
|
||||
@@ -78,23 +79,23 @@ type Manifest struct {
|
||||
MediaType string `json:"mediaType,omitempty"`
|
||||
|
||||
// Config references the image configuration as a blob.
|
||||
Config distribution.Descriptor `json:"config"`
|
||||
Config v1.Descriptor `json:"config"`
|
||||
|
||||
// Layers lists descriptors for the layers referenced by the
|
||||
// configuration.
|
||||
Layers []distribution.Descriptor `json:"layers"`
|
||||
Layers []v1.Descriptor `json:"layers"`
|
||||
}
|
||||
|
||||
// References returns the descriptors of this manifests references.
|
||||
func (m Manifest) References() []distribution.Descriptor {
|
||||
references := make([]distribution.Descriptor, 0, 1+len(m.Layers))
|
||||
func (m Manifest) References() []v1.Descriptor {
|
||||
references := make([]v1.Descriptor, 0, 1+len(m.Layers))
|
||||
references = append(references, m.Config)
|
||||
references = append(references, m.Layers...)
|
||||
return references
|
||||
}
|
||||
|
||||
// Target returns the target of this manifest.
|
||||
func (m Manifest) Target() distribution.Descriptor {
|
||||
func (m Manifest) Target() v1.Descriptor {
|
||||
return m.Config
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
|
||||
"github.com/distribution/distribution/v3"
|
||||
"github.com/opencontainers/image-spec/specs-go"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
const expectedManifestSerialization = `{
|
||||
@@ -31,12 +32,12 @@ func makeTestManifest(mediaType string) Manifest {
|
||||
return Manifest{
|
||||
Versioned: specs.Versioned{SchemaVersion: 2},
|
||||
MediaType: mediaType,
|
||||
Config: distribution.Descriptor{
|
||||
Config: v1.Descriptor{
|
||||
MediaType: MediaTypeImageConfig,
|
||||
Digest: "sha256:1a9ec845ee94c202b2d5da74a24f0ed2058318bfa9879fa541efaecba272e86b",
|
||||
Size: 985,
|
||||
},
|
||||
Layers: []distribution.Descriptor{
|
||||
Layers: []v1.Descriptor{
|
||||
{
|
||||
MediaType: MediaTypeLayer,
|
||||
Digest: "sha256:62d8908bee94c202b2d35224a221aaa2058318bfa9879fa541efaecba272331b",
|
||||
|
||||
+8
-7
@@ -6,6 +6,7 @@ import (
|
||||
"mime"
|
||||
|
||||
"github.com/opencontainers/go-digest"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
// Manifest represents a registry object specifying a set of
|
||||
@@ -13,13 +14,13 @@ import (
|
||||
type Manifest interface {
|
||||
// References returns a list of objects which make up this manifest.
|
||||
// A reference is anything which can be represented by a
|
||||
// distribution.Descriptor. These can consist of layers, resources or other
|
||||
// Descriptor. These can consist of layers, resources or other
|
||||
// manifests.
|
||||
//
|
||||
// While no particular order is required, implementations should return
|
||||
// them from highest to lowest priority. For example, one might want to
|
||||
// return the base layer before the top layer.
|
||||
References() []Descriptor
|
||||
References() []v1.Descriptor
|
||||
|
||||
// Payload provides the serialized format of the manifest, in addition to
|
||||
// the media type.
|
||||
@@ -54,7 +55,7 @@ type ManifestEnumerator interface {
|
||||
// described, not simply descriptors.
|
||||
type Describable interface {
|
||||
// Descriptor returns the descriptor.
|
||||
Descriptor() Descriptor
|
||||
Descriptor() v1.Descriptor
|
||||
}
|
||||
|
||||
// ManifestMediaTypes returns the supported media types for manifests.
|
||||
@@ -68,13 +69,13 @@ func ManifestMediaTypes() (mediaTypes []string) {
|
||||
}
|
||||
|
||||
// UnmarshalFunc implements manifest unmarshalling a given MediaType
|
||||
type UnmarshalFunc func([]byte) (Manifest, Descriptor, error)
|
||||
type UnmarshalFunc func([]byte) (Manifest, v1.Descriptor, error)
|
||||
|
||||
var mappings = make(map[string]UnmarshalFunc)
|
||||
|
||||
// UnmarshalManifest looks up manifest unmarshal functions based on
|
||||
// MediaType
|
||||
func UnmarshalManifest(ctHeader string, p []byte) (Manifest, Descriptor, error) {
|
||||
func UnmarshalManifest(ctHeader string, p []byte) (Manifest, v1.Descriptor, error) {
|
||||
// Need to look up by the actual media type, not the raw contents of
|
||||
// the header. Strip semicolons and anything following them.
|
||||
var mediaType string
|
||||
@@ -82,7 +83,7 @@ func UnmarshalManifest(ctHeader string, p []byte) (Manifest, Descriptor, error)
|
||||
var err error
|
||||
mediaType, _, err = mime.ParseMediaType(ctHeader)
|
||||
if err != nil {
|
||||
return nil, Descriptor{}, err
|
||||
return nil, v1.Descriptor{}, err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,7 +91,7 @@ func UnmarshalManifest(ctHeader string, p []byte) (Manifest, Descriptor, error)
|
||||
if !ok {
|
||||
unmarshalFunc, ok = mappings[""]
|
||||
if !ok {
|
||||
return nil, Descriptor{}, fmt.Errorf("unsupported manifest media type and no default available: %s", mediaType)
|
||||
return nil, v1.Descriptor{}, fmt.Errorf("unsupported manifest media type and no default available: %s", mediaType)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
events "github.com/docker/go-events"
|
||||
"github.com/google/uuid"
|
||||
"github.com/opencontainers/go-digest"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
type bridge struct {
|
||||
@@ -90,15 +91,15 @@ func (b *bridge) ManifestDeleted(repo reference.Named, dgst digest.Digest) error
|
||||
return b.createManifestDeleteEventAndWrite(EventActionDelete, repo, dgst)
|
||||
}
|
||||
|
||||
func (b *bridge) BlobPushed(repo reference.Named, desc distribution.Descriptor) error {
|
||||
func (b *bridge) BlobPushed(repo reference.Named, desc v1.Descriptor) error {
|
||||
return b.createBlobEventAndWrite(EventActionPush, repo, desc)
|
||||
}
|
||||
|
||||
func (b *bridge) BlobPulled(repo reference.Named, desc distribution.Descriptor) error {
|
||||
func (b *bridge) BlobPulled(repo reference.Named, desc v1.Descriptor) error {
|
||||
return b.createBlobEventAndWrite(EventActionPull, repo, desc)
|
||||
}
|
||||
|
||||
func (b *bridge) BlobMounted(repo reference.Named, desc distribution.Descriptor, fromRepo reference.Named) error {
|
||||
func (b *bridge) BlobMounted(repo reference.Named, desc v1.Descriptor, fromRepo reference.Named) error {
|
||||
event, err := b.createBlobEvent(EventActionMount, repo, desc)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -178,7 +179,7 @@ func (b *bridge) createBlobDeleteEventAndWrite(action string, repo reference.Nam
|
||||
return b.sink.Write(*event)
|
||||
}
|
||||
|
||||
func (b *bridge) createBlobEventAndWrite(action string, repo reference.Named, desc distribution.Descriptor) error {
|
||||
func (b *bridge) createBlobEventAndWrite(action string, repo reference.Named, desc v1.Descriptor) error {
|
||||
event, err := b.createBlobEvent(action, repo, desc)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -187,7 +188,7 @@ func (b *bridge) createBlobEventAndWrite(action string, repo reference.Named, de
|
||||
return b.sink.Write(*event)
|
||||
}
|
||||
|
||||
func (b *bridge) createBlobEvent(action string, repo reference.Named, desc distribution.Descriptor) (*Event, error) {
|
||||
func (b *bridge) createBlobEvent(action string, repo reference.Named, desc v1.Descriptor) (*Event, error) {
|
||||
event := b.createEvent(action)
|
||||
event.Target.Descriptor = desc
|
||||
event.Target.Length = desc.Size
|
||||
|
||||
@@ -30,7 +30,7 @@ var (
|
||||
request = RequestRecord{}
|
||||
tag = "latest"
|
||||
artifactType = "application/vnd.example.sbom.v1"
|
||||
cfg = distribution.Descriptor{
|
||||
cfg = v1.Descriptor{
|
||||
MediaType: artifactType,
|
||||
Size: 100,
|
||||
Digest: "cfgdgst",
|
||||
|
||||
@@ -4,8 +4,8 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/distribution/distribution/v3"
|
||||
events "github.com/docker/go-events"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
// EventAction constants used in action field of Event.
|
||||
@@ -54,7 +54,7 @@ type Event struct {
|
||||
Target struct {
|
||||
// TODO(stevvooe): Use http.DetectContentType for layers, maybe.
|
||||
|
||||
distribution.Descriptor
|
||||
v1.Descriptor
|
||||
|
||||
// Length in bytes of content. Same as Size field in Descriptor.
|
||||
// Provided for backwards compatibility.
|
||||
@@ -74,7 +74,7 @@ type Event struct {
|
||||
Tag string `json:"tag,omitempty"`
|
||||
|
||||
// References provides the references descriptors.
|
||||
References []distribution.Descriptor `json:"references,omitempty"`
|
||||
References []v1.Descriptor `json:"references,omitempty"`
|
||||
} `json:"target,omitempty"`
|
||||
|
||||
// Request covers the request that generated the event.
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/distribution/distribution/v3/internal/dcontext"
|
||||
"github.com/distribution/reference"
|
||||
"github.com/opencontainers/go-digest"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
// ManifestListener describes a set of methods for listening to events related to manifests.
|
||||
@@ -21,9 +22,9 @@ type ManifestListener interface {
|
||||
|
||||
// BlobListener describes a listener that can respond to layer related events.
|
||||
type BlobListener interface {
|
||||
BlobPushed(repo reference.Named, desc distribution.Descriptor) error
|
||||
BlobPulled(repo reference.Named, desc distribution.Descriptor) error
|
||||
BlobMounted(repo reference.Named, desc distribution.Descriptor, fromRepo reference.Named) error
|
||||
BlobPushed(repo reference.Named, desc v1.Descriptor) error
|
||||
BlobPulled(repo reference.Named, desc v1.Descriptor) error
|
||||
BlobMounted(repo reference.Named, desc v1.Descriptor, fromRepo reference.Named) error
|
||||
BlobDeleted(repo reference.Named, desc digest.Digest) error
|
||||
}
|
||||
|
||||
@@ -178,7 +179,7 @@ func (bsl *blobServiceListener) ServeBlob(ctx context.Context, w http.ResponseWr
|
||||
return err
|
||||
}
|
||||
|
||||
func (bsl *blobServiceListener) Put(ctx context.Context, mediaType string, p []byte) (distribution.Descriptor, error) {
|
||||
func (bsl *blobServiceListener) Put(ctx context.Context, mediaType string, p []byte) (v1.Descriptor, error) {
|
||||
desc, err := bsl.BlobStore.Put(ctx, mediaType, p)
|
||||
if err == nil {
|
||||
if err := bsl.parent.listener.BlobPushed(bsl.parent.Repository.Named(), desc); err != nil {
|
||||
@@ -229,7 +230,7 @@ type blobWriterListener struct {
|
||||
parent *blobServiceListener
|
||||
}
|
||||
|
||||
func (bwl *blobWriterListener) Commit(ctx context.Context, desc distribution.Descriptor) (distribution.Descriptor, error) {
|
||||
func (bwl *blobWriterListener) Commit(ctx context.Context, desc v1.Descriptor) (v1.Descriptor, error) {
|
||||
committed, err := bwl.BlobWriter.Commit(ctx, desc)
|
||||
if err == nil {
|
||||
if err := bwl.parent.parent.listener.BlobPushed(bwl.parent.parent.Repository.Named(), committed); err != nil {
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
"github.com/distribution/reference"
|
||||
"github.com/opencontainers/go-digest"
|
||||
"github.com/opencontainers/image-spec/specs-go"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
func TestListener(t *testing.T) {
|
||||
@@ -80,17 +81,17 @@ func (tl *testListener) ManifestDeleted(repo reference.Named, d digest.Digest) e
|
||||
return nil
|
||||
}
|
||||
|
||||
func (tl *testListener) BlobPushed(repo reference.Named, desc distribution.Descriptor) error {
|
||||
func (tl *testListener) BlobPushed(repo reference.Named, desc v1.Descriptor) error {
|
||||
tl.ops["layer:push"]++
|
||||
return nil
|
||||
}
|
||||
|
||||
func (tl *testListener) BlobPulled(repo reference.Named, desc distribution.Descriptor) error {
|
||||
func (tl *testListener) BlobPulled(repo reference.Named, desc v1.Descriptor) error {
|
||||
tl.ops["layer:pull"]++
|
||||
return nil
|
||||
}
|
||||
|
||||
func (tl *testListener) BlobMounted(repo reference.Named, desc distribution.Descriptor, fromRepo reference.Named) error {
|
||||
func (tl *testListener) BlobMounted(repo reference.Named, desc v1.Descriptor, fromRepo reference.Named) error {
|
||||
tl.ops["layer:mount"]++
|
||||
return nil
|
||||
}
|
||||
@@ -146,7 +147,7 @@ func checkTestRepository(t *testing.T, repository distribution.Repository, remov
|
||||
m := schema2.Manifest{
|
||||
Versioned: specs.Versioned{SchemaVersion: 2},
|
||||
MediaType: schema2.MediaTypeManifest,
|
||||
Config: distribution.Descriptor{
|
||||
Config: v1.Descriptor{
|
||||
MediaType: "foo/bar",
|
||||
Digest: configDgst,
|
||||
},
|
||||
@@ -163,7 +164,7 @@ func checkTestRepository(t *testing.T, repository distribution.Repository, remov
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
m.Layers = append(m.Layers, distribution.Descriptor{
|
||||
m.Layers = append(m.Layers, v1.Descriptor{
|
||||
MediaType: "application/octet-stream",
|
||||
Digest: dgst,
|
||||
})
|
||||
@@ -201,7 +202,7 @@ func checkTestRepository(t *testing.T, repository distribution.Repository, remov
|
||||
t.Fatal("mismatching digest from payload and put")
|
||||
}
|
||||
|
||||
if err := repository.Tags(ctx).Tag(ctx, tag, distribution.Descriptor{Digest: dgst}); err != nil {
|
||||
if err := repository.Tags(ctx).Tag(ctx, tag, v1.Descriptor{Digest: dgst}); err != nil {
|
||||
t.Fatalf("unexpected error tagging manifest: %v", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ import (
|
||||
"github.com/gorilla/handlers"
|
||||
"github.com/opencontainers/go-digest"
|
||||
"github.com/opencontainers/image-spec/specs-go"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
var headerConfig = http.Header{
|
||||
@@ -1579,12 +1580,12 @@ func testManifestAPISchema2(t *testing.T, env *testEnv, imageName reference.Name
|
||||
manifest := &schema2.Manifest{
|
||||
Versioned: specs.Versioned{SchemaVersion: 2},
|
||||
MediaType: schema2.MediaTypeManifest,
|
||||
Config: distribution.Descriptor{
|
||||
Config: v1.Descriptor{
|
||||
Digest: "sha256:1a9ec845ee94c202b2d5da74a24f0ed2058318bfa9879fa541efaecba272e86b",
|
||||
Size: 3253,
|
||||
MediaType: schema2.MediaTypeImageConfig,
|
||||
},
|
||||
Layers: []distribution.Descriptor{
|
||||
Layers: []v1.Descriptor{
|
||||
{
|
||||
Digest: "sha256:463434349086340864309863409683460843608348608934092322395278926a",
|
||||
Size: 6323,
|
||||
@@ -1902,7 +1903,7 @@ func testManifestAPIManifestList(t *testing.T, env *testEnv, args manifestArgs)
|
||||
MediaType: manifestlist.MediaTypeManifestList,
|
||||
Manifests: []manifestlist.ManifestDescriptor{
|
||||
{
|
||||
Descriptor: distribution.Descriptor{
|
||||
Descriptor: v1.Descriptor{
|
||||
Digest: "sha256:1a9ec845ee94c202b2d5da74a24f0ed2058318bfa9879fa541efaecba272e86b",
|
||||
Size: 3253,
|
||||
MediaType: schema2.MediaTypeManifest,
|
||||
@@ -2637,12 +2638,12 @@ func createRepository(env *testEnv, t *testing.T, imageName string, tag string)
|
||||
manifest := &schema2.Manifest{
|
||||
Versioned: specs.Versioned{SchemaVersion: 2},
|
||||
MediaType: schema2.MediaTypeManifest,
|
||||
Config: distribution.Descriptor{
|
||||
Config: v1.Descriptor{
|
||||
Digest: "sha256:1a9ec845ee94c202b2d5da74a24f0ed2058318bfa9879fa541efaecba272e86b",
|
||||
Size: 3253,
|
||||
MediaType: schema2.MediaTypeImageConfig,
|
||||
},
|
||||
Layers: []distribution.Descriptor{
|
||||
Layers: []v1.Descriptor{
|
||||
{
|
||||
Digest: "sha256:463434349086340864309863409683460843608348608934092322395278926a",
|
||||
Size: 6323,
|
||||
@@ -2732,12 +2733,12 @@ func TestRegistryAsCacheMutationAPIs(t *testing.T) {
|
||||
manifest := &schema2.Manifest{
|
||||
Versioned: specs.Versioned{SchemaVersion: 2},
|
||||
MediaType: schema2.MediaTypeManifest,
|
||||
Config: distribution.Descriptor{
|
||||
Config: v1.Descriptor{
|
||||
Digest: "sha256:1a9ec845ee94c202b2d5da74a24f0ed2058318bfa9879fa541efaecba272e86b",
|
||||
Size: 3253,
|
||||
MediaType: schema2.MediaTypeImageConfig,
|
||||
},
|
||||
Layers: []distribution.Descriptor{
|
||||
Layers: []v1.Descriptor{
|
||||
{
|
||||
Digest: "sha256:463434349086340864309863409683460843608348608934092322395278926a",
|
||||
Size: 6323,
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/distribution/reference"
|
||||
"github.com/gorilla/handlers"
|
||||
"github.com/opencontainers/go-digest"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
// blobUploadDispatcher constructs and returns the blob upload handler for the
|
||||
@@ -210,7 +211,7 @@ func (buh *blobUploadHandler) PutBlobUploadComplete(w http.ResponseWriter, r *ht
|
||||
return
|
||||
}
|
||||
|
||||
desc, err := buh.Upload.Commit(buh, distribution.Descriptor{
|
||||
desc, err := buh.Upload.Commit(buh, v1.Descriptor{
|
||||
Digest: dgst,
|
||||
|
||||
// TODO(stevvooe): This isn't wildly important yet, but we should
|
||||
@@ -384,7 +385,7 @@ func (buh *blobUploadHandler) createBlobMountOption(fromRepo, mountDigest string
|
||||
// writeBlobCreatedHeaders writes the standard headers describing a newly
|
||||
// created blob. A 201 Created is written as well as the canonical URL and
|
||||
// blob digest.
|
||||
func (buh *blobUploadHandler) writeBlobCreatedHeaders(w http.ResponseWriter, desc distribution.Descriptor) error {
|
||||
func (buh *blobUploadHandler) writeBlobCreatedHeaders(w http.ResponseWriter, desc v1.Descriptor) error {
|
||||
ref, err := reference.WithDigest(buh.Repository.Named(), desc.Digest)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -478,7 +478,7 @@ func (imh *manifestHandler) DeleteManifest(w http.ResponseWriter, r *http.Reques
|
||||
}
|
||||
|
||||
tagService := imh.Repository.Tags(imh)
|
||||
referencedTags, err := tagService.Lookup(imh, distribution.Descriptor{Digest: imh.Digest})
|
||||
referencedTags, err := tagService.Lookup(imh, v1.Descriptor{Digest: imh.Digest})
|
||||
if err != nil {
|
||||
imh.Errors = append(imh.Errors, err)
|
||||
return
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/opencontainers/go-digest"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
|
||||
"github.com/distribution/distribution/v3"
|
||||
"github.com/distribution/distribution/v3/internal/dcontext"
|
||||
@@ -40,24 +41,24 @@ func setResponseHeaders(h http.Header, length int64, mediaType string, digest di
|
||||
h.Set("Etag", digest.String())
|
||||
}
|
||||
|
||||
func (pbs *proxyBlobStore) copyContent(ctx context.Context, dgst digest.Digest, writer io.Writer, h http.Header) (distribution.Descriptor, error) {
|
||||
func (pbs *proxyBlobStore) copyContent(ctx context.Context, dgst digest.Digest, writer io.Writer, h http.Header) (v1.Descriptor, error) {
|
||||
desc, err := pbs.remoteStore.Stat(ctx, dgst)
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
|
||||
setResponseHeaders(h, desc.Size, desc.MediaType, dgst)
|
||||
|
||||
remoteReader, err := pbs.remoteStore.Open(ctx, dgst)
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
|
||||
defer remoteReader.Close()
|
||||
|
||||
_, err = io.CopyN(writer, remoteReader, desc.Size)
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
|
||||
proxyMetrics.BlobPull(uint64(desc.Size))
|
||||
@@ -146,18 +147,18 @@ func (pbs *proxyBlobStore) ServeBlob(ctx context.Context, w http.ResponseWriter,
|
||||
return nil
|
||||
}
|
||||
|
||||
func (pbs *proxyBlobStore) Stat(ctx context.Context, dgst digest.Digest) (distribution.Descriptor, error) {
|
||||
func (pbs *proxyBlobStore) Stat(ctx context.Context, dgst digest.Digest) (v1.Descriptor, error) {
|
||||
desc, err := pbs.localStore.Stat(ctx, dgst)
|
||||
if err == nil {
|
||||
return desc, err
|
||||
}
|
||||
|
||||
if err != distribution.ErrBlobUnknown {
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
|
||||
if err := pbs.authChallenger.tryEstablishChallenges(ctx); err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
|
||||
return pbs.remoteStore.Stat(ctx, dgst)
|
||||
@@ -186,8 +187,8 @@ func (pbs *proxyBlobStore) Get(ctx context.Context, dgst digest.Digest) ([]byte,
|
||||
}
|
||||
|
||||
// Unsupported functions
|
||||
func (pbs *proxyBlobStore) Put(ctx context.Context, mediaType string, p []byte) (distribution.Descriptor, error) {
|
||||
return distribution.Descriptor{}, distribution.ErrUnsupported
|
||||
func (pbs *proxyBlobStore) Put(ctx context.Context, mediaType string, p []byte) (v1.Descriptor, error) {
|
||||
return v1.Descriptor{}, distribution.ErrUnsupported
|
||||
}
|
||||
|
||||
func (pbs *proxyBlobStore) Create(ctx context.Context, options ...distribution.BlobCreateOption) (distribution.BlobWriter, error) {
|
||||
@@ -198,8 +199,8 @@ func (pbs *proxyBlobStore) Resume(ctx context.Context, id string) (distribution.
|
||||
return nil, distribution.ErrUnsupported
|
||||
}
|
||||
|
||||
func (pbs *proxyBlobStore) Mount(ctx context.Context, sourceRepo reference.Named, dgst digest.Digest) (distribution.Descriptor, error) {
|
||||
return distribution.Descriptor{}, distribution.ErrUnsupported
|
||||
func (pbs *proxyBlobStore) Mount(ctx context.Context, sourceRepo reference.Named, dgst digest.Digest) (v1.Descriptor, error) {
|
||||
return v1.Descriptor{}, distribution.ErrUnsupported
|
||||
}
|
||||
|
||||
func (pbs *proxyBlobStore) Open(ctx context.Context, dgst digest.Digest) (io.ReadSeekCloser, error) {
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"github.com/distribution/distribution/v3/registry/storage/driver/inmemory"
|
||||
"github.com/distribution/reference"
|
||||
"github.com/opencontainers/go-digest"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -34,7 +35,7 @@ func init() {
|
||||
randSource = *rand.New(rand.NewSource(42))
|
||||
}
|
||||
|
||||
func (sbs statsBlobStore) Put(ctx context.Context, mediaType string, p []byte) (distribution.Descriptor, error) {
|
||||
func (sbs statsBlobStore) Put(ctx context.Context, mediaType string, p []byte) (v1.Descriptor, error) {
|
||||
sbsMu.Lock()
|
||||
sbs.stats["put"]++
|
||||
sbsMu.Unlock()
|
||||
@@ -82,7 +83,7 @@ func (sbs statsBlobStore) ServeBlob(ctx context.Context, w http.ResponseWriter,
|
||||
return sbs.blobs.ServeBlob(ctx, w, r, dgst)
|
||||
}
|
||||
|
||||
func (sbs statsBlobStore) Stat(ctx context.Context, dgst digest.Digest) (distribution.Descriptor, error) {
|
||||
func (sbs statsBlobStore) Stat(ctx context.Context, dgst digest.Digest) (v1.Descriptor, error) {
|
||||
sbsMu.Lock()
|
||||
sbs.stats["stat"]++
|
||||
sbsMu.Unlock()
|
||||
@@ -100,7 +101,7 @@ func (sbs statsBlobStore) Delete(ctx context.Context, dgst digest.Digest) error
|
||||
|
||||
type testEnv struct {
|
||||
numUnique int
|
||||
inRemote []distribution.Descriptor
|
||||
inRemote []v1.Descriptor
|
||||
store proxyBlobStore
|
||||
ctx context.Context
|
||||
}
|
||||
@@ -202,7 +203,7 @@ func makeBlob(size int) []byte {
|
||||
}
|
||||
|
||||
func populate(t *testing.T, te *testEnv, blobCount, size, numUnique int) {
|
||||
var inRemote []distribution.Descriptor
|
||||
var inRemote []v1.Descriptor
|
||||
|
||||
for i := 0; i < numUnique; i++ {
|
||||
bytes := makeBlob(size)
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"github.com/distribution/reference"
|
||||
"github.com/opencontainers/go-digest"
|
||||
"github.com/opencontainers/image-spec/specs-go"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
type statsManifest struct {
|
||||
@@ -158,7 +159,7 @@ func populateRepo(ctx context.Context, t *testing.T, repository distribution.Rep
|
||||
m := schema2.Manifest{
|
||||
Versioned: specs.Versioned{SchemaVersion: 2},
|
||||
MediaType: schema2.MediaTypeManifest,
|
||||
Config: distribution.Descriptor{
|
||||
Config: v1.Descriptor{
|
||||
MediaType: "foo/bar",
|
||||
Digest: configDigest,
|
||||
},
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/distribution/distribution/v3"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
// proxyTagService supports local and remote lookup of tags.
|
||||
@@ -18,14 +19,14 @@ var _ distribution.TagService = proxyTagService{}
|
||||
// Get attempts to get the most recent digest for the tag by checking the remote
|
||||
// tag service first and then caching it locally. If the remote is unavailable
|
||||
// the local association is returned
|
||||
func (pt proxyTagService) Get(ctx context.Context, tag string) (distribution.Descriptor, error) {
|
||||
func (pt proxyTagService) Get(ctx context.Context, tag string) (v1.Descriptor, error) {
|
||||
err := pt.authChallenger.tryEstablishChallenges(ctx)
|
||||
if err == nil {
|
||||
desc, err := pt.remoteTags.Get(ctx, tag)
|
||||
if err == nil {
|
||||
err := pt.localTags.Tag(ctx, tag, desc)
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
return desc, nil
|
||||
}
|
||||
@@ -33,12 +34,12 @@ func (pt proxyTagService) Get(ctx context.Context, tag string) (distribution.Des
|
||||
|
||||
desc, err := pt.localTags.Get(ctx, tag)
|
||||
if err != nil {
|
||||
return distribution.Descriptor{}, err
|
||||
return v1.Descriptor{}, err
|
||||
}
|
||||
return desc, nil
|
||||
}
|
||||
|
||||
func (pt proxyTagService) Tag(ctx context.Context, tag string, desc distribution.Descriptor) error {
|
||||
func (pt proxyTagService) Tag(ctx context.Context, tag string, desc v1.Descriptor) error {
|
||||
return distribution.ErrUnsupported
|
||||
}
|
||||
|
||||
@@ -61,6 +62,6 @@ func (pt proxyTagService) All(ctx context.Context) ([]string, error) {
|
||||
return pt.localTags.All(ctx)
|
||||
}
|
||||
|
||||
func (pt proxyTagService) Lookup(ctx context.Context, digest distribution.Descriptor) ([]string, error) {
|
||||
func (pt proxyTagService) Lookup(ctx context.Context, digest v1.Descriptor) ([]string, error) {
|
||||
return []string{}, distribution.ErrUnsupported
|
||||
}
|
||||
@@ -8,25 +8,26 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/distribution/distribution/v3"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
type mockTagStore struct {
|
||||
mapping map[string]distribution.Descriptor
|
||||
mapping map[string]v1.Descriptor
|
||||
sync.Mutex
|
||||
distribution.TagService
|
||||
}
|
||||
|
||||
func (m *mockTagStore) Get(ctx context.Context, tag string) (distribution.Descriptor, error) {
|
||||
func (m *mockTagStore) Get(ctx context.Context, tag string) (v1.Descriptor, error) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
|
||||
if d, ok := m.mapping[tag]; ok {
|
||||
return d, nil
|
||||
}
|
||||
return distribution.Descriptor{}, distribution.ErrTagUnknown{}
|
||||
return v1.Descriptor{}, distribution.ErrTagUnknown{}
|
||||
}
|
||||
|
||||
func (m *mockTagStore) Tag(ctx context.Context, tag string, desc distribution.Descriptor) error {
|
||||
func (m *mockTagStore) Tag(ctx context.Context, tag string, desc v1.Descriptor) error {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
|
||||
@@ -57,12 +58,12 @@ func (m *mockTagStore) All(ctx context.Context) ([]string, error) {
|
||||
return tags, nil
|
||||
}
|
||||
|
||||
func testProxyTagService(local, remote map[string]distribution.Descriptor) *proxyTagService {
|
||||
func testProxyTagService(local, remote map[string]v1.Descriptor) *proxyTagService {
|
||||
if local == nil {
|
||||
local = make(map[string]distribution.Descriptor)
|
||||
local = make(map[string]v1.Descriptor)
|
||||
}
|
||||
if remote == nil {
|
||||
remote = make(map[string]distribution.Descriptor)
|
||||
remote = make(map[string]v1.Descriptor)
|
||||
}
|
||||
return &proxyTagService{
|
||||
localTags: &mockTagStore{mapping: local},
|
||||
@@ -72,9 +73,9 @@ func testProxyTagService(local, remote map[string]distribution.Descriptor) *prox
|
||||
}
|
||||
|
||||
func TestGet(t *testing.T) {
|
||||
remoteDesc := distribution.Descriptor{Size: 42}
|
||||
remoteDesc := v1.Descriptor{Size: 42}
|
||||
remoteTag := "remote"
|
||||
proxyTags := testProxyTagService(map[string]distribution.Descriptor{remoteTag: remoteDesc}, nil)
|
||||
proxyTags := testProxyTagService(map[string]v1.Descriptor{remoteTag: remoteDesc}, nil)
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
@@ -102,7 +103,7 @@ func TestGet(t *testing.T) {
|
||||
}
|
||||
|
||||
// Manually overwrite remote tag
|
||||
newRemoteDesc := distribution.Descriptor{Size: 43}
|
||||
newRemoteDesc := v1.Descriptor{Size: 43}
|
||||
err = proxyTags.remoteTags.Tag(ctx, remoteTag, newRemoteDesc)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -152,7 +153,7 @@ func TestGet(t *testing.T) {
|
||||
}
|
||||
|
||||
// Add another tag. Ensure both tags appear in 'All'
|
||||
err = proxyTags.remoteTags.Tag(ctx, "funtag", distribution.Descriptor{Size: 42})
|
||||
err = proxyTags.remoteTags.Tag(ctx, "funtag", v1.Descriptor{Size: 42})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
|
||||
Vendored
+2
-1
@@ -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
|
||||
}
|
||||
|
||||
Vendored
+11
-10
@@ -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
|
||||
}
|
||||
|
||||
+5
-4
@@ -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",
|
||||
|
||||
+3
-2
@@ -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")
|
||||
}
|
||||
|
||||
+11
-10
@@ -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
|
||||
}
|
||||
|
||||
+5
-4
@@ -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)
|
||||
|
||||
+21
-20
@@ -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,
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/opencontainers/go-digest"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
// TagService provides access to information about tagged objects.
|
||||
@@ -12,11 +13,11 @@ type TagService interface {
|
||||
// implementations may differentiate between "trusted" tags and
|
||||
// "untrusted" tags. If a tag is "untrusted", the mapping will be returned
|
||||
// as an ErrTagUntrusted error, with the target descriptor.
|
||||
Get(ctx context.Context, tag string) (Descriptor, error)
|
||||
Get(ctx context.Context, tag string) (v1.Descriptor, error)
|
||||
|
||||
// Tag associates the tag with the provided descriptor, updating the
|
||||
// current association, if needed.
|
||||
Tag(ctx context.Context, tag string, desc Descriptor) error
|
||||
Tag(ctx context.Context, tag string, desc v1.Descriptor) error
|
||||
|
||||
// Untag removes the given tag association
|
||||
Untag(ctx context.Context, tag string) error
|
||||
@@ -25,7 +26,7 @@ type TagService interface {
|
||||
All(ctx context.Context) ([]string, error)
|
||||
|
||||
// Lookup returns the set of tags referencing the given digest.
|
||||
Lookup(ctx context.Context, digest Descriptor) ([]string, error)
|
||||
Lookup(ctx context.Context, digest v1.Descriptor) ([]string, error)
|
||||
}
|
||||
|
||||
// TagManifestsProvider provides method to retrieve the digests of manifests that a tag historically
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/distribution/distribution/v3/manifest/ocischema"
|
||||
"github.com/distribution/distribution/v3/manifest/schema2"
|
||||
"github.com/opencontainers/go-digest"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
// MakeManifestList constructs a manifest list out of a list of manifest digests
|
||||
@@ -51,7 +52,7 @@ func MakeSchema2Manifest(repository distribution.Repository, digests []digest.Di
|
||||
}
|
||||
builder := schema2.NewManifestBuilder(d, configJSON)
|
||||
for _, dgst := range digests {
|
||||
if err := builder.AppendReference(distribution.Descriptor{Digest: dgst}); err != nil {
|
||||
if err := builder.AppendReference(v1.Descriptor{Digest: dgst}); err != nil {
|
||||
return nil, fmt.Errorf("unexpected error building schema2 manifest: %v", err)
|
||||
}
|
||||
}
|
||||
@@ -72,7 +73,7 @@ func MakeOCIManifest(repository distribution.Repository, digests []digest.Digest
|
||||
|
||||
builder := ocischema.NewManifestBuilder(blobStore, configJSON, make(map[string]string))
|
||||
for _, dgst := range digests {
|
||||
if err := builder.AppendReference(distribution.Descriptor{Digest: dgst}); err != nil {
|
||||
if err := builder.AppendReference(v1.Descriptor{Digest: dgst}); err != nil {
|
||||
return nil, fmt.Errorf("unexpected error building OCI manifest: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -7,6 +7,7 @@ import (
|
||||
|
||||
"github.com/distribution/distribution/v3"
|
||||
"github.com/opencontainers/go-digest"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
// PushBlob pushes a blob with the given digest to the given repository.
|
||||
@@ -28,7 +29,7 @@ func PushBlob(ctx context.Context, repository distribution.Repository, blobReade
|
||||
return fmt.Errorf("unexpected error uploading: %v", err)
|
||||
}
|
||||
|
||||
if _, err := wr.Commit(ctx, distribution.Descriptor{Digest: dgst}); err != nil {
|
||||
if _, err := wr.Commit(ctx, v1.Descriptor{Digest: dgst}); err != nil {
|
||||
return fmt.Errorf("unexpected error finishing upload: %v", err)
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/distribution/distribution/v3"
|
||||
"github.com/distribution/distribution/v3/internal/dcontext"
|
||||
"github.com/opencontainers/go-digest"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
// CreateRandomTarFile creates a random tarfile, returning it as an
|
||||
@@ -107,7 +108,7 @@ func UploadBlobs(repository distribution.Repository, layers map[digest.Digest]io
|
||||
return fmt.Errorf("unexpected error copying to upload: %v", err)
|
||||
}
|
||||
|
||||
if _, err := wr.Commit(ctx, distribution.Descriptor{Digest: dgst}); err != nil {
|
||||
if _, err := wr.Commit(ctx, v1.Descriptor{Digest: dgst}); err != nil {
|
||||
return fmt.Errorf("unexpected error committinng upload: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user