Skip to content

Commit e8225cb

Browse files
authored
fix: OCI store resolve returns full descriptor (#468)
Based on discussion on #457, this PR returns a full descriptor on Resolve when the method it's called by tag and it returns a plain descriptor when the method it's called by digest. Signed-off-by: oanatmaria <[email protected]>
1 parent c1bf59e commit e8225cb

File tree

4 files changed

+112
-9
lines changed

4 files changed

+112
-9
lines changed

content/oci/oci.go

+11-2
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,11 @@ func (s *Store) tag(ctx context.Context, desc ocispec.Descriptor, reference stri
165165
return nil
166166
}
167167

168-
// Resolve resolves a reference to a descriptor.
168+
// Resolve resolves a reference to a descriptor. If the reference to be resolved
169+
// is a tag, the returned descriptor will be a full descriptor declared by
170+
// github.com/opencontainers/image-spec/specs-go/v1. If the reference is a
171+
// digest the returned descriptor will be a plain descriptor (containing only
172+
// the digest, media type and size).
169173
func (s *Store) Resolve(ctx context.Context, reference string) (ocispec.Descriptor, error) {
170174
if reference == "" {
171175
return ocispec.Descriptor{}, errdef.ErrMissingReference
@@ -180,7 +184,12 @@ func (s *Store) Resolve(ctx context.Context, reference string) (ocispec.Descript
180184
}
181185
return ocispec.Descriptor{}, err
182186
}
183-
return descriptor.Plain(desc), nil
187+
188+
if reference == desc.Digest.String() {
189+
return descriptor.Plain(desc), nil
190+
}
191+
192+
return desc, nil
184193
}
185194

186195
// Predecessors returns the nodes directly pointing to the current node.

content/oci/oci_test.go

+78-1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import (
3939
"oras.land/oras-go/v2/content/memory"
4040
"oras.land/oras-go/v2/errdef"
4141
"oras.land/oras-go/v2/internal/cas"
42+
"oras.land/oras-go/v2/internal/descriptor"
4243
"oras.land/oras-go/v2/registry"
4344
)
4445

@@ -452,6 +453,82 @@ func TestStore_ContentBadPush(t *testing.T) {
452453
}
453454
}
454455

456+
func TestStore_ResolveByTagReturnsFullDescriptor(t *testing.T) {
457+
content := []byte("hello world")
458+
ref := "hello-world:0.0.1"
459+
annotations := map[string]string{"name": "Hello"}
460+
desc := ocispec.Descriptor{
461+
MediaType: "test",
462+
Digest: digest.FromBytes(content),
463+
Size: int64(len(content)),
464+
Annotations: annotations,
465+
}
466+
467+
tempDir := t.TempDir()
468+
s, err := New(tempDir)
469+
if err != nil {
470+
t.Fatal("New() error =", err)
471+
}
472+
ctx := context.Background()
473+
474+
err = s.Push(ctx, desc, bytes.NewReader(content))
475+
if err != nil {
476+
t.Errorf("Store.Push() error = %v, wantErr %v", err, false)
477+
}
478+
479+
err = s.Tag(ctx, desc, ref)
480+
if err != nil {
481+
t.Errorf("error tagging descriptor error = %v, wantErr %v", err, false)
482+
}
483+
484+
resolvedDescr, err := s.Resolve(ctx, ref)
485+
if err != nil {
486+
t.Errorf("error resolving descriptor error = %v, wantErr %v", err, false)
487+
}
488+
489+
if !reflect.DeepEqual(resolvedDescr, desc) {
490+
t.Errorf("Store.Resolve() = %v, want %v", resolvedDescr, desc)
491+
}
492+
}
493+
494+
func TestStore_ResolveByDigestReturnsPlainDescriptor(t *testing.T) {
495+
content := []byte("hello world")
496+
ref := "hello-world:0.0.1"
497+
desc := ocispec.Descriptor{
498+
MediaType: "test",
499+
Digest: digest.FromBytes(content),
500+
Size: int64(len(content)),
501+
Annotations: map[string]string{"name": "Hello"},
502+
}
503+
plainDescriptor := descriptor.Plain(desc)
504+
505+
tempDir := t.TempDir()
506+
s, err := New(tempDir)
507+
if err != nil {
508+
t.Fatal("New() error =", err)
509+
}
510+
ctx := context.Background()
511+
512+
err = s.Push(ctx, desc, bytes.NewReader(content))
513+
if err != nil {
514+
t.Errorf("Store.Push() error = %v, wantErr %v", err, false)
515+
}
516+
517+
err = s.Tag(ctx, desc, ref)
518+
if err != nil {
519+
t.Errorf("error tagging descriptor error = %v, wantErr %v", err, false)
520+
}
521+
522+
resolvedDescr, err := s.Resolve(ctx, string(desc.Digest))
523+
if err != nil {
524+
t.Errorf("error resolving descriptor error = %v, wantErr %v", err, false)
525+
}
526+
527+
if !reflect.DeepEqual(resolvedDescr, plainDescriptor) {
528+
t.Errorf("Store.Resolve() = %v, want %v", resolvedDescr, plainDescriptor)
529+
}
530+
}
531+
455532
func TestStore_TagNotFound(t *testing.T) {
456533
ref := "foobar"
457534

@@ -1092,7 +1169,7 @@ func TestStore_ExistingStore(t *testing.T) {
10921169
if err != nil {
10931170
t.Fatal("Store: Resolve() error =", err)
10941171
}
1095-
if !reflect.DeepEqual(gotDesc, indexRoot) {
1172+
if !content.Equal(gotDesc, indexRoot) {
10961173
t.Errorf("Store.Resolve() = %v, want %v", gotDesc, indexRoot)
10971174
}
10981175

content/oci/readonlyoci.go

+11-2
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,11 @@ func (s *ReadOnlyStore) Exists(ctx context.Context, target ocispec.Descriptor) (
8383
return s.storage.Exists(ctx, target)
8484
}
8585

86-
// Resolve resolves a reference to a descriptor.
86+
// Resolve resolves a reference to a descriptor. If the reference to be resolved
87+
// is a tag, the returned descriptor will be a full descriptor declared by
88+
// github.com/opencontainers/image-spec/specs-go/v1. If the reference is a
89+
// digest the returned descriptor will be a plain descriptor (containing only
90+
// the digest, media type and size).
8791
func (s *ReadOnlyStore) Resolve(ctx context.Context, reference string) (ocispec.Descriptor, error) {
8892
if reference == "" {
8993
return ocispec.Descriptor{}, errdef.ErrMissingReference
@@ -98,7 +102,12 @@ func (s *ReadOnlyStore) Resolve(ctx context.Context, reference string) (ocispec.
98102
}
99103
return ocispec.Descriptor{}, err
100104
}
101-
return descriptor.Plain(desc), nil
105+
106+
if reference == desc.Digest.String() {
107+
return descriptor.Plain(desc), nil
108+
}
109+
110+
return desc, nil
102111
}
103112

104113
// Predecessors returns the nodes directly pointing to the current node.

content/oci/readonlyoci_test.go

+12-4
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import (
3434
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
3535
"golang.org/x/sync/errgroup"
3636
"oras.land/oras-go/v2"
37+
"oras.land/oras-go/v2/content"
3738
"oras.land/oras-go/v2/content/memory"
3839
"oras.land/oras-go/v2/internal/docker"
3940
"oras.land/oras-go/v2/registry"
@@ -148,10 +149,17 @@ func TestReadOnlyStore(t *testing.T) {
148149
if err != nil {
149150
t.Error("ReadOnlyStore.Resolve() error =", err)
150151
}
151-
if want := descs[2]; !reflect.DeepEqual(gotDesc, want) {
152+
if want := descs[2]; !content.Equal(gotDesc, want) {
152153
t.Errorf("ReadOnlyStore.Resolve() = %v, want %v", gotDesc, want)
153154
}
154155

156+
// descriptor resolved by tag should have annotations
157+
if gotDesc.Annotations[ocispec.AnnotationRefName] != subjectTag {
158+
t.Errorf("ReadOnlyStore.Resolve() returned descriptor without annotations %v, want %v",
159+
gotDesc.Annotations,
160+
map[string]string{ocispec.AnnotationRefName: subjectTag})
161+
}
162+
155163
// test resolving artifact by digest
156164
gotDesc, err = s.Resolve(ctx, descs[3].Digest.String())
157165
if err != nil {
@@ -318,7 +326,7 @@ func TestReadOnlyStore_DirFS(t *testing.T) {
318326
if err != nil {
319327
t.Fatal("ReadOnlyStore: Resolve() error =", err)
320328
}
321-
if !reflect.DeepEqual(gotDesc, indexRoot) {
329+
if !content.Equal(gotDesc, indexRoot) {
322330
t.Errorf("ReadOnlyStore.Resolve() = %v, want %v", gotDesc, indexRoot)
323331
}
324332

@@ -613,7 +621,7 @@ func TestReadOnlyStore_Copy_OCIToMemory(t *testing.T) {
613621
if err != nil {
614622
t.Fatalf("Copy() error = %v, wantErr %v", err, false)
615623
}
616-
if !reflect.DeepEqual(gotDesc, root) {
624+
if !content.Equal(gotDesc, root) {
617625
t.Errorf("Copy() = %v, want %v", gotDesc, root)
618626
}
619627

@@ -633,7 +641,7 @@ func TestReadOnlyStore_Copy_OCIToMemory(t *testing.T) {
633641
if err != nil {
634642
t.Fatal("dst.Resolve() error =", err)
635643
}
636-
if !reflect.DeepEqual(gotDesc, root) {
644+
if !content.Equal(gotDesc, root) {
637645
t.Errorf("dst.Resolve() = %v, want %v", gotDesc, root)
638646
}
639647
}

0 commit comments

Comments
 (0)