Skip to content

Commit 20d69ce

Browse files
fixed OCI image import bug (#59)
2 parents b5497ab + f743ee2 commit 20d69ce

File tree

2 files changed

+63
-24
lines changed

2 files changed

+63
-24
lines changed

uriget/example_test.go

+21-9
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ func ExampleWithHttpClient() {
5252
// Output: failed to make get request: Get "https://example.com": no proxy
5353
}
5454
func ExampleGetFile_oci() {
55-
testUrl := "oci://ghcr.io/score-spec/score-compose:0.18.0"
55+
testUrl := "oci://ghcr.io/score-spec/score-compose-community-provisioners:v0.1.0#00-service.provisioners.yaml"
5656
buff, err := GetFile(context.Background(), testUrl)
5757
if err != nil {
5858
fmt.Println("failed to pull OCI image:", err)
@@ -63,26 +63,38 @@ func ExampleGetFile_oci() {
6363
// true
6464
}
6565

66-
func ExampleGetFile_ociNoTag() {
67-
testUrl := "oci://ghcr.io/score-spec/score-compose"
68-
buff, err := GetFile(context.Background(), testUrl)
66+
func ExampleGetFile_oci_git() {
67+
ociTestUrl := "oci://ghcr.io/score-spec/score-compose-community-provisioners:v0.1.0#00-service.provisioners.yaml"
68+
ociBuff, err := GetFile(context.Background(), ociTestUrl)
6969
if err != nil {
7070
fmt.Println("failed to pull OCI image:", err)
7171
return
7272
}
73-
fmt.Println(len(buff) > 0)
73+
gitTestUrl := "git-https://github.com/score-spec/community-provisioners.git/score-compose/00-service.provisioners.yaml"
74+
gitBuff, err := GetFile(context.Background(), gitTestUrl)
75+
if err != nil {
76+
fmt.Println("failed to pull file in git:", err)
77+
return
78+
}
79+
fmt.Println(len(ociBuff) == len(gitBuff))
7480
// Output:
7581
// true
7682
}
7783

78-
func ExampleGetFile_ociWithDigest() {
79-
testUrl := "oci://ghcr.io/score-spec/score-compose@sha256:f3d8d5485a751cbdc91e073df1b6fbcde83f85a86ee3bc7d53e05b00452baedd"
80-
buff, err := GetFile(context.Background(), testUrl)
84+
func ExampleGetFile_oci_https() {
85+
ociTestUrl := "oci://ghcr.io/score-spec/score-compose-community-provisioners:v0.1.0#00-service.provisioners.yaml"
86+
ociBuff, err := GetFile(context.Background(), ociTestUrl)
8187
if err != nil {
8288
fmt.Println("failed to pull OCI image:", err)
8389
return
8490
}
85-
fmt.Println(len(buff) > 0)
91+
httpsTestUrl := "https://github.com/score-spec/community-provisioners/raw/v0.1.0/score-compose/00-service.provisioners.yaml"
92+
httpsbuff, err := GetFile(context.Background(), httpsTestUrl)
93+
if err != nil {
94+
fmt.Println("failed to pull file by HTTPS:", err)
95+
return
96+
}
97+
fmt.Println(len(ociBuff) == len(httpsbuff))
8698
// Output:
8799
// true
88100
}

uriget/uriget.go

+42-15
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package uriget
66

77
import (
88
"context"
9+
"encoding/json"
910
"fmt"
1011
"io"
1112
"log"
@@ -17,8 +18,7 @@ import (
1718
"strings"
1819
"time"
1920

20-
"oras.land/oras-go/v2"
21-
"oras.land/oras-go/v2/content/oci"
21+
v1 "github.com/opencontainers/image-spec/specs-go/v1"
2222
"oras.land/oras-go/v2/registry"
2323
"oras.land/oras-go/v2/registry/remote"
2424
)
@@ -244,25 +244,52 @@ func (o *options) getGit(ctx context.Context, u *url.URL) ([]byte, error) {
244244
func (o *options) getOci(ctx context.Context, u *url.URL) ([]byte, error) {
245245
ref, err := registry.ParseReference(u.Host + u.Path)
246246
if err != nil {
247-
return nil, fmt.Errorf("can't parse artifact URL into a valid reference: %w", err)
247+
return nil, fmt.Errorf("invalid artifact URL: %w", err)
248248
}
249-
store, err := oci.New(o.tempDir)
250-
if err != nil {
251-
return nil, fmt.Errorf("failed to create OCI layout store: %w", err)
249+
if ref.Reference == "" {
250+
ref.Reference = "latest"
252251
}
252+
specifiedFile := strings.TrimPrefix(u.Fragment, "#")
253253
remoteRepo, err := remote.NewRepository(ref.String())
254254
if err != nil {
255-
return nil, fmt.Errorf("failed to connect to remote repository: %w", err)
255+
return nil, fmt.Errorf("connection to remote repository failed: %w", err)
256+
}
257+
_, rc, err := remoteRepo.Manifests().FetchReference(ctx, ref.Reference)
258+
if err != nil {
259+
return nil, fmt.Errorf("manifest fetch failed: %w", err)
260+
}
261+
defer rc.Close()
262+
var manifest v1.Manifest
263+
if err = json.NewDecoder(rc).Decode(&manifest); err != nil {
264+
return nil, fmt.Errorf("manifest decode failed: %w", err)
265+
}
266+
var selectedLayer *v1.Descriptor
267+
yamlFileCount := 0
268+
for _, layer := range manifest.Layers {
269+
title := layer.Annotations[v1.AnnotationTitle]
270+
if strings.HasSuffix(title, ".yaml") {
271+
yamlFileCount++
272+
if specifiedFile == "" && yamlFileCount > 1 {
273+
return nil, fmt.Errorf("manifest contains %d .yaml files; specify a specific file in the URL fragment", yamlFileCount)
274+
}
275+
if specifiedFile == "" || title == specifiedFile {
276+
selectedLayer = &layer
277+
break
278+
}
279+
}
256280
}
257-
tag := "latest"
258-
if ref.Reference != "" {
259-
tag = ref.Reference
281+
if selectedLayer == nil {
282+
return nil, fmt.Errorf("no matching .yaml file found in layers")
260283
}
261-
manifestDescriptor, err := oras.Copy(ctx, remoteRepo, tag, store, tag, oras.DefaultCopyOptions)
284+
_, rc, err = remoteRepo.Blobs().FetchReference(ctx, selectedLayer.Digest.String())
262285
if err != nil {
263-
return nil, fmt.Errorf("failed to pull OCI image: %w", err)
286+
return nil, fmt.Errorf("blob fetch failed: %w", err)
264287
}
265-
266-
o.logger.Printf("Pulled OCI image: %s with manifest descriptor: %v", u.String(), manifestDescriptor.Digest)
267-
return []byte(manifestDescriptor.Digest), nil
288+
defer rc.Close()
289+
buff, err := readLimited(rc, o.limit)
290+
if err != nil {
291+
return nil, fmt.Errorf("blob read failed: %w", err)
292+
}
293+
o.logger.Printf("Read %d bytes from %s", len(buff), specifiedFile)
294+
return buff, nil
268295
}

0 commit comments

Comments
 (0)