libimage: preserve optional name when pulling from OCI transport

When pulling from an OCI source, make sure to preseve the optional name.
For instance, a `podman pull oci:/tmp/foo:quay.io/foo/bar:latest` should
pull the image and name it `quay.io/foo/bar:latest`.

While at it, also fix a bug when pulling an OCI without the optional
name.  Previously, we used the path to name the image which will error
in most cases due to invalid characters (e.g., capital ones).  Hence,
apply the same trick as for the `dir` transport and generate a sha.

Signed-off-by: Valentin Rothberg <vrothberg@redhat.com>
This commit is contained in:
Valentin Rothberg 2023-08-30 09:19:42 +02:00
parent 40924835d8
commit 02a72eb33e
2 changed files with 61 additions and 2 deletions

View File

@ -230,8 +230,18 @@ func (r *Runtime) copyFromDefault(ctx context.Context, ref types.ImageReference,
case ociTransport.Transport.Name():
split := strings.SplitN(ref.StringWithinTransport(), ":", 2)
storageName = toLocalImageName(split[0])
imageName = storageName
if len(split) == 1 || split[1] == "" {
// Same trick as for the dir transport: we cannot use
// the path to a directory as the name.
storageName, err = getImageID(ctx, ref, nil)
if err != nil {
return nil, err
}
imageName = "sha256:" + storageName[1:]
} else { // If the OCI-reference includes an image reference, use it
storageName = split[1]
imageName = storageName
}
case ociArchiveTransport.Transport.Name():
manifestDescriptor, err := ociArchiveTransport.LoadManifestDescriptorWithContext(r.SystemContext(), ref)

View File

@ -220,3 +220,52 @@ func TestShortNameAndIDconflict(t *testing.T) {
require.NoError(t, err)
require.Equal(t, busybox[0].ID(), img.ID())
}
func TestPullOCINoReference(t *testing.T) {
// Exercise pulling from the OCI transport and make sure that a
// specified reference is preserved in the image name.
busybox := "docker.io/library/busybox:latest"
runtime, cleanup := testNewRuntime(t)
defer cleanup()
ctx := context.Background()
pullOptions := &PullOptions{}
pullOptions.Writer = os.Stdout
images, err := runtime.Pull(ctx, busybox, config.PullPolicyAlways, pullOptions)
require.NoError(t, err)
require.Len(t, images, 1)
// Push one image without the optional reference
ociPathNoRef := "oci:" + t.TempDir() + "noRef"
_, err = runtime.Push(ctx, busybox, ociPathNoRef, nil)
require.NoError(t, err)
// Push another image _with_ the optional reference which allows for
// preserving the name.
ociPathWithRef := "oci:" + t.TempDir() + "withRef:" + busybox
_, err = runtime.Push(ctx, busybox, ociPathWithRef, nil)
require.NoError(t, err)
_, errors := runtime.RemoveImages(ctx, []string{busybox}, nil)
require.Nil(t, errors)
images, err = runtime.Pull(ctx, ociPathNoRef, config.PullPolicyAlways, pullOptions)
require.NoError(t, err)
require.Len(t, images, 1)
exists, err := runtime.Exists(busybox) // busybox does not exist
require.NoError(t, err)
require.False(t, exists)
names := images[0].Names() // The image has no names (i.e., <none>)
require.Nil(t, names)
images, err = runtime.Pull(ctx, ociPathWithRef, config.PullPolicyAlways, pullOptions)
require.NoError(t, err)
require.Len(t, images, 1)
exists, err = runtime.Exists(busybox) // busybox does exist now
require.NoError(t, err)
require.True(t, exists)
}