diff --git a/common/libimage/pull.go b/common/libimage/pull.go index 1e8cc42c2d..bdf172d17b 100644 --- a/common/libimage/pull.go +++ b/common/libimage/pull.go @@ -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) diff --git a/common/libimage/pull_test.go b/common/libimage/pull_test.go index 28c4a86b82..94695ac2cf 100644 --- a/common/libimage/pull_test.go +++ b/common/libimage/pull_test.go @@ -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., ) + 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) +}