-
Notifications
You must be signed in to change notification settings - Fork 201
Description
What happened in your environment?
We use OCI images to package eBPF programs in Inspektor Gadget. We have an ig image export
command that creates an oci layout file with the image. I wanted to use oras cp
to copy the image to a remote registry, however it fails with:
$ oras cp --from-oci-layout ./mygadget.tar.folder:ghcr.io/inspektor-gadget/gadget/mygadget:latest localhost:5000/foo:latest --debug
Error: invalid argument "./mygadget.tar.folder:ghcr.io/inspektor-gadget/gadget/mygadget:latest": failed to find path "./mygadget.tar.folder:ghcr.io/inspektor-gadget/gadget/mygadget": stat ./mygadget.tar.folder:ghcr.io/inspektor-gadget/gadget/mygadget: no such file or directory
The issue seems to be related to the fact that the org.opencontainers.image.ref.name
annotation is set to ghcr.io/inspektor-gadget/gadget/mygadget:latest
in index.json:
mygadget.tar.folder/index.json:
{
"schemaVersion": 2,
"manifests": [
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"digest": "sha256:69fb10d45f448525a39bb26ae2af71e57fe2b7aa774547eb57da38ddf08b12e0",
"size": 1278,
"annotations": {
"org.opencontainers.image.created": "2024-09-19T13:06:53-05:00",
"org.opencontainers.image.description": "TODO: Fill the gadget description",
"org.opencontainers.image.documentation": "TODO: Fill the gadget documentation URL",
"org.opencontainers.image.source": "TODO: Fill the gadget source code URL",
"org.opencontainers.image.title": "TODO: Fill the gadget name",
"org.opencontainers.image.url": "TODO: Fill the gadget homepage URL"
},
"platform": {
"architecture": "arm64",
"os": "linux"
}
},
{
"mediaType": "application/vnd.oci.image.index.v1+json",
"digest": "sha256:f31a444623261efcc68601704dd3d980692a73a55f5031c8ddca58cc8a23876e",
"size": 1816,
"annotations": {
"org.opencontainers.image.created": "2024-09-19T13:06:53-05:00",
"org.opencontainers.image.description": "TODO: Fill the gadget description",
"org.opencontainers.image.documentation": "TODO: Fill the gadget documentation URL",
"org.opencontainers.image.ref.name": "ghcr.io/inspektor-gadget/gadget/mygadget:latest",
"org.opencontainers.image.source": "TODO: Fill the gadget source code URL",
"org.opencontainers.image.title": "TODO: Fill the gadget name",
"org.opencontainers.image.url": "TODO: Fill the gadget homepage URL"
}
},
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"digest": "sha256:f99e163810194bd7fc50e23c9f1d7d827e464aac1766892f3747b1764301c3ae",
"size": 1278,
"annotations": {
"org.opencontainers.image.created": "2024-09-19T13:06:53-05:00",
"org.opencontainers.image.description": "TODO: Fill the gadget description",
"org.opencontainers.image.documentation": "TODO: Fill the gadget documentation URL",
"org.opencontainers.image.source": "TODO: Fill the gadget source code URL",
"org.opencontainers.image.title": "TODO: Fill the gadget name",
"org.opencontainers.image.url": "TODO: Fill the gadget homepage URL"
},
"platform": {
"architecture": "amd64",
"os": "linux"
}
}
]
}
According to https://github.com/opencontainers/image-spec/blob/v1.1.0-rc5/annotations.md, ghcr.io/inspektor-gadget/gadget/mygadget:latest
is a valid value for the annotation.
Possible Fix
The following diff fixes the issue:
diff --git a/cmd/oras/internal/option/target.go b/cmd/oras/internal/option/target.go
index 489eeb8..33b83af 100644
--- a/cmd/oras/internal/option/target.go
+++ b/cmd/oras/internal/option/target.go
@@ -38,7 +38,6 @@ import (
"oras.land/oras-go/v2/registry/remote/auth"
"oras.land/oras-go/v2/registry/remote/errcode"
oerrors "oras.land/oras/cmd/oras/internal/errors"
- "oras.land/oras/cmd/oras/internal/fileref"
)
const (
@@ -120,6 +119,20 @@ func (opts *Target) Parse(cmd *cobra.Command) error {
}
}
+// Parse parses file reference on unix.
+func parseModified(reference string, defaultMetadata string) (filePath, metadata string, err error) {
+ i := strings.Index(reference, ":")
+ if i < 0 {
+ filePath, metadata = reference, defaultMetadata
+ } else {
+ filePath, metadata = reference[:i], reference[i+1:]
+ }
+ if filePath == "" {
+ return "", "", fmt.Errorf("found empty file path in %q", reference)
+ }
+ return filePath, metadata, nil
+}
+
// parseOCILayoutReference parses the raw in format of <path>[:<tag>|@<digest>]
func (opts *Target) parseOCILayoutReference() error {
raw := opts.RawReference
@@ -132,7 +145,7 @@ func (opts *Target) parseOCILayoutReference() error {
} else {
// find `tag`
var err error
- path, ref, err = fileref.Parse(raw, "")
+ path, ref, err = parseModified(raw, "")
if err != nil {
return errors.Join(err, errdef.ErrInvalidReference)
}
I'm willing to open a fix once we agree on a solution.
What did you expect to happen?
oras cp
should have copied the image to the remote repository
How can we reproduce it?
Set the org.opencontainers.image.ref.name
annotation to something like foo:bar
in index.json and try to run oras cp --from-oci-layout ./myfolder:foo:bar localhost:5000/foo:latest
What is the version of your ORAS CLI?
Manually compiled from 961e9f8
What is your OS environment?
Ubuntu 22.04 (it really doesn't matter for this bug)
Are you willing to submit PRs to fix it?
- Yes, I am willing to fix it.