Skip to content

oras cp fails if org.opencontainers.image.ref.name contains a full reference #1505

@mauriciovasquezbernal

Description

@mauriciovasquezbernal

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingenhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions