replace uses of Descriptor alias

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn committed 2024-10-07 13:07:47 +02:00
1 parent 740b31105e
commit 0ab7f326e6
54 files changed
+417 -381

No files matched your search

+5 -5
View File
@@ -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
+5 -4
View File
@@ -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)
+34 -33
View File
@@ -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
}
+7 -7
View File
@@ -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,
+7 -7
View File
@@ -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{
+5 -6
View File
@@ -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) {
+4 -4
View File
@@ -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
}
+8 -8
View File
@@ -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
View File
@@ -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{
+5 -5
View File
@@ -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)
+9 -9
View File
@@ -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
}
+6 -7
View File
@@ -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) {
+7 -6
View File
@@ -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
}
+4 -4
View File
@@ -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 -8
View File
@@ -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
}
+3 -2
View File
@@ -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
View File
@@ -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)
}
}
+6 -5
View File
@@ -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
+1 -1
View File
@@ -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",
+3 -3
View File
@@ -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.
+6 -5
View File
@@ -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 {
+7 -6
View File
@@ -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)
}
+8 -7
View File
@@ -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,
+3 -2
View File
@@ -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
+1 -1
View File
@@ -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
+12 -11
View File
@@ -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) {
+5 -4
View File
@@ -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)
+2 -1
View File
@@ -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,
},
+6 -5
View File
@@ -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
}
+12 -11
View File
@@ -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)
}
+9 -8
View File
@@ -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)
+12 -11
View File
@@ -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
}
+18 -17
View File
@@ -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,
})
+2 -1
View File
@@ -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
}
+11 -10
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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 {
+2 -1
View File
@@ -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)
}
+10 -9
View File
@@ -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)
}
+16 -15
View File
@@ -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
}
+8 -7
View File
@@ -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{}
+2 -1
View File
@@ -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
+14 -14
View File
@@ -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
+16 -16
View File
@@ -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"),
},
+16 -15
View File
@@ -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"),
},
+9 -8
View File
@@ -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:
+8 -7
View File
@@ -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 -3
View File
@@ -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
+3 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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)
}
}