Skip to content

Commit

Permalink
[PRFix fix comments]
Browse files Browse the repository at this point in the history
Signed-off-by: Zoey Li <zoeyli@microsoft.com>
  • Loading branch information
lizMSFT committed Aug 2, 2022
1 parent 219d676 commit 39386ac
Show file tree
Hide file tree
Showing 5 changed files with 208 additions and 37 deletions.
17 changes: 12 additions & 5 deletions content.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,22 +44,29 @@ func Tag(ctx context.Context, target Target, src, dst string) error {
return target.Tag(ctx, desc, dst)
}

var (
// DefaultResolveOptions provides the default ResolveOptions.
DefaultResolveOptions = ResolveOptions{
TargetPlatform: nil,
}
)

// ResolveOptions contains parameters for oras.Resolve.
type ResolveOptions struct {
// MatchPlaform is the target platform.
// TargetPlatform is the target platform.
// Will do the platform selection if specified.
MatchPlatform *ocispec.Platform
TargetPlatform *ocispec.Platform
}

// Resolve returns the resolved descriptor.
// Resolve resolves a descriptor with provided reference from the target.
func Resolve(ctx context.Context, target Target, ref string, opts ResolveOptions) (ocispec.Descriptor, error) {
desc, err := target.Resolve(ctx, ref)
if err != nil {
return ocispec.Descriptor{}, err
}

if opts.MatchPlatform != nil {
desc, err = selectPlatform(ctx, target, desc, opts.MatchPlatform)
if opts.TargetPlatform != nil {
desc, err = selectPlatform(ctx, target, desc, opts.TargetPlatform)
if err != nil {
return ocispec.Descriptor{}, err
}
Expand Down
159 changes: 159 additions & 0 deletions content_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"bytes"
"context"
"encoding/json"
"errors"
"net/http"
"net/http/httptest"
"net/url"
Expand All @@ -30,6 +31,7 @@ import (
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"oras.land/oras-go/v2"
"oras.land/oras-go/v2/content/memory"
"oras.land/oras-go/v2/errdef"
"oras.land/oras-go/v2/registry/remote"
)

Expand Down Expand Up @@ -186,3 +188,160 @@ func TestTag_Repository(t *testing.T) {
t.Errorf("Repository.TagReference() = %v, want %v", gotIndex, index)
}
}

func TestResolve_WithOptions(t *testing.T) {
target := memory.New()

// generate test content
var blobs [][]byte
var descs []ocispec.Descriptor
appendBlob := func(mediaType string, blob []byte) {
blobs = append(blobs, blob)
descs = append(descs, ocispec.Descriptor{
MediaType: mediaType,
Digest: digest.FromBytes(blob),
Size: int64(len(blob)),
})
}
generateManifest := func(config ocispec.Descriptor, layers ...ocispec.Descriptor) {
manifest := ocispec.Manifest{
Config: config,
Layers: layers,
}
manifestJSON, err := json.Marshal(manifest)
if err != nil {
t.Fatal(err)
}
appendBlob(ocispec.MediaTypeImageManifest, manifestJSON)
}

appendBlob(ocispec.MediaTypeImageConfig, []byte("config")) // Blob 0
appendBlob(ocispec.MediaTypeImageLayer, []byte("foo")) // Blob 1
appendBlob(ocispec.MediaTypeImageLayer, []byte("bar")) // Blob 2
generateManifest(descs[0], descs[1:3]...) // Blob 3

ctx := context.Background()
for i := range blobs {
err := target.Push(ctx, descs[i], bytes.NewReader(blobs[i]))
if err != nil {
t.Fatalf("failed to push test content to src: %d: %v", i, err)
}
}

manifestDesc := descs[3]
ref := "foobar"
err := target.Tag(ctx, manifestDesc, ref)
if err != nil {
t.Fatal("fail to tag manifestDesc node", err)
}

// test Resolve with TargetPlatform
resolveOptions := oras.DefaultResolveOptions
gotDesc, err := oras.Resolve(ctx, target, ref, resolveOptions)

if err != nil {
t.Fatal("oras.Resolve() error =", err)
}
if !reflect.DeepEqual(gotDesc, manifestDesc) {
t.Errorf("oras.Resolve() = %v, want %v", gotDesc, manifestDesc)
}
}

func TestResolve_WithTargetPlatformOptions(t *testing.T) {
target := memory.New()
arc_1 := "test-arc-1"
os_1 := "test-os-1"
variant_1 := "v1"
variant_2 := "v2"

// generate test content
var blobs [][]byte
var descs []ocispec.Descriptor
appendBlob := func(mediaType string, blob []byte) {
blobs = append(blobs, blob)
descs = append(descs, ocispec.Descriptor{
MediaType: mediaType,
Digest: digest.FromBytes(blob),
Size: int64(len(blob)),
})
}
appendManifest := func(arc, os, variant string, mediaType string, blob []byte) {
blobs = append(blobs, blob)
descs = append(descs, ocispec.Descriptor{
MediaType: mediaType,
Digest: digest.FromBytes(blob),
Size: int64(len(blob)),
Platform: &ocispec.Platform{
Architecture: arc,
OS: os,
Variant: variant,
},
})
}
generateManifest := func(arc, os, variant string, config ocispec.Descriptor, layers ...ocispec.Descriptor) {
manifest := ocispec.Manifest{
Config: config,
Layers: layers,
}
manifestJSON, err := json.Marshal(manifest)
if err != nil {
t.Fatal(err)
}
appendManifest(arc, os, variant, ocispec.MediaTypeImageManifest, manifestJSON)
}

appendBlob(ocispec.MediaTypeImageConfig, []byte(`{"mediaType":"application/vnd.oci.image.config.v1+json",
"created":"2022-07-29T08:13:55Z",
"author":"test author",
"architecture":"test-arc-1",
"os":"test-os-1",
"variant":"test-variant"}`)) // Blob 0
appendBlob(ocispec.MediaTypeImageLayer, []byte("foo")) // Blob 1
appendBlob(ocispec.MediaTypeImageLayer, []byte("bar")) // Blob 2
generateManifest(arc_1, os_1, variant_1, descs[0], descs[1:3]...) // Blob 3

ctx := context.Background()
for i := range blobs {
err := target.Push(ctx, descs[i], bytes.NewReader(blobs[i]))
if err != nil {
t.Fatalf("failed to push test content to src: %d: %v", i, err)
}
}

manifestDesc := descs[3]
ref := "foobar"
err := target.Tag(ctx, manifestDesc, ref)
if err != nil {
t.Fatal("fail to tag manifestDesc node", err)
}

// test Resolve with TargetPlatform
resolveOptions := oras.ResolveOptions{
TargetPlatform: &ocispec.Platform{
Architecture: arc_1,
OS: os_1,
},
}
gotDesc, err := oras.Resolve(ctx, target, ref, resolveOptions)

if err != nil {
t.Fatal("oras.Resolve() error =", err)
}
if !reflect.DeepEqual(gotDesc, manifestDesc) {
t.Errorf("oras.Resolve() = %v, want %v", gotDesc, manifestDesc)
}

// test Resolve with TargetPlatform but there is no matching node
// Should return not found error
resolveOptions = oras.ResolveOptions{
TargetPlatform: &ocispec.Platform{
Architecture: arc_1,
OS: os_1,
Variant: variant_2,
},
}
_, err = oras.Resolve(ctx, target, ref, resolveOptions)
if !errors.Is(err, errdef.ErrNotFound) {
t.Fatalf("oras.Resolve() error = %v, wantErr %v", err, errdef.ErrNotFound)
}
}
5 changes: 2 additions & 3 deletions copy.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,11 @@ func selectPlatform(ctx context.Context, src content.Storage, root ocispec.Descr
if err != nil {
return ocispec.Descriptor{}, err
}
defer rc.Close()
var currPlatform ocispec.Platform
err = json.NewDecoder(rc).Decode(&currPlatform)
if err != nil {
if err = json.NewDecoder(rc).Decode(&currPlatform); err != nil {
return ocispec.Descriptor{}, err
}
defer rc.Close()

if platform.Match(&currPlatform, p) {
return root, nil
Expand Down
48 changes: 27 additions & 21 deletions copy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -660,6 +660,12 @@ func TestCopy_WithOptions(t *testing.T) {

func TestCopy_WithPlatformFilterOptions(t *testing.T) {
src := memory.New()
arc_1 := "test-arc-1"
os_1 := "test-os-1"
variant_1 := "v1"
arc_2 := "test-arc-2"
os_2 := "test-os-2"
variant_2 := "v2"

// generate test content
var blobs [][]byte
Expand Down Expand Up @@ -713,14 +719,14 @@ func TestCopy_WithPlatformFilterOptions(t *testing.T) {
"architecture":"test-arc-1",
"os":"test-os-1",
"variant":"test-variant"}`)) // Blob 0
appendBlob(ocispec.MediaTypeImageLayer, []byte("foo")) // Blob 1
appendBlob(ocispec.MediaTypeImageLayer, []byte("bar")) // Blob 2
generateManifest("test-arc-1", "test-os-1", "v1", descs[0], descs[1:3]...) // Blob 3
appendBlob(ocispec.MediaTypeImageLayer, []byte("hello1")) // Blob 4
generateManifest("test-arc-2", "test-os-2", "v1", descs[0], descs[4]) // Blob 5
appendBlob(ocispec.MediaTypeImageLayer, []byte("hello2")) // Blob 6
generateManifest("test-arc-1", "test-os-1", "v2", descs[0], descs[6]) // Blob 7
generateIndex(descs[3], descs[5], descs[7]) // Blob 8
appendBlob(ocispec.MediaTypeImageLayer, []byte("foo")) // Blob 1
appendBlob(ocispec.MediaTypeImageLayer, []byte("bar")) // Blob 2
generateManifest(arc_1, os_1, variant_1, descs[0], descs[1:3]...) // Blob 3
appendBlob(ocispec.MediaTypeImageLayer, []byte("hello1")) // Blob 4
generateManifest(arc_2, os_2, variant_1, descs[0], descs[4]) // Blob 5
appendBlob(ocispec.MediaTypeImageLayer, []byte("hello2")) // Blob 6
generateManifest(arc_1, os_1, variant_2, descs[0], descs[6]) // Blob 7
generateIndex(descs[3], descs[5], descs[7]) // Blob 8

ctx := context.Background()
for i := range blobs {
Expand All @@ -741,8 +747,8 @@ func TestCopy_WithPlatformFilterOptions(t *testing.T) {
dst := memory.New()
opts := oras.CopyOptions{}
targetPlatform := ocispec.Platform{
Architecture: "test-arc-2",
OS: "test-os-2",
Architecture: arc_2,
OS: os_2,
}
opts.WithPlatformFilter(&targetPlatform)
wantDesc := descs[5]
Expand Down Expand Up @@ -779,8 +785,8 @@ func TestCopy_WithPlatformFilterOptions(t *testing.T) {
// matching entry.
dst = memory.New()
targetPlatform = ocispec.Platform{
Architecture: "test-arc-1",
OS: "test-os-1",
Architecture: arc_1,
OS: os_1,
}
opts = oras.CopyOptions{}
opts.WithPlatformFilter(&targetPlatform)
Expand Down Expand Up @@ -827,8 +833,8 @@ func TestCopy_WithPlatformFilterOptions(t *testing.T) {
},
}
targetPlatform = ocispec.Platform{
Architecture: "test-arc-1",
OS: "test-os-3",
Architecture: arc_1,
OS: os_2,
}
opts.WithPlatformFilter(&targetPlatform)

Expand All @@ -841,8 +847,8 @@ func TestCopy_WithPlatformFilterOptions(t *testing.T) {
dst = memory.New()
opts = oras.CopyOptions{}
targetPlatform = ocispec.Platform{
Architecture: "test-arc-1",
OS: "test-os-1",
Architecture: arc_1,
OS: os_1,
}
opts.WithPlatformFilter(&targetPlatform)

Expand Down Expand Up @@ -886,9 +892,9 @@ func TestCopy_WithPlatformFilterOptions(t *testing.T) {
dst = memory.New()
opts = oras.CopyOptions{}
targetPlatform = ocispec.Platform{
Architecture: "test-arc-1",
OS: "test-os-1",
Variant: "wrong-variant",
Architecture: arc_1,
OS: os_1,
Variant: variant_2,
}
opts.WithPlatformFilter(&targetPlatform)

Expand All @@ -902,8 +908,8 @@ func TestCopy_WithPlatformFilterOptions(t *testing.T) {
dst = memory.New()
opts = oras.CopyOptions{}
targetPlatform = ocispec.Platform{
Architecture: "test-arc-1",
OS: "test-os-1",
Architecture: arc_1,
OS: os_1,
}
opts.WithPlatformFilter(&targetPlatform)

Expand Down
16 changes: 8 additions & 8 deletions internal/platform/platform_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ import (

func TestMatch(t *testing.T) {
tests := []struct {
curr ocispec.Platform
target ocispec.Platform
want bool
got ocispec.Platform
want ocispec.Platform
isMatched bool
}{{
ocispec.Platform{Architecture: "amd64", OS: "linux"},
ocispec.Platform{Architecture: "amd64", OS: "linux"},
Expand Down Expand Up @@ -90,12 +90,12 @@ func TestMatch(t *testing.T) {
}}

for _, tt := range tests {
currPlatforJSON, _ := json.Marshal(tt.curr)
targetPlatforJSON, _ := json.Marshal(tt.target)
name := string(currPlatforJSON) + string(targetPlatforJSON)
gotPlatformJSON, _ := json.Marshal(tt.got)
wantPlatformJSON, _ := json.Marshal(tt.want)
name := string(gotPlatformJSON) + string(wantPlatformJSON)
t.Run(name, func(t *testing.T) {
if got := Match(&tt.curr, &tt.target); got != tt.want {
t.Errorf("MatchPlatform() = %v, want %v", got, tt.want)
if actual := Match(&tt.got, &tt.want); actual != tt.isMatched {
t.Errorf("Match() = %v, want %v", actual, tt.isMatched)
}
})
}
Expand Down

0 comments on commit 39386ac

Please sign in to comment.