libimage: add save tests
Add save tests. Also fix a bug when saving a single image but with multiple tags. Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
This commit is contained in:
parent
73305281fd
commit
9c6c0eab43
|
|
@ -57,9 +57,13 @@ func (r *Runtime) Save(ctx context.Context, names []string, format, path string,
|
|||
// Dispatch the save operations.
|
||||
switch format {
|
||||
case "oci-archive", "oci-dir", "docker-dir":
|
||||
if len(names) > 1 {
|
||||
return errors.Errorf("%q does not support saving multiple images (%v)", format, names)
|
||||
}
|
||||
return r.saveSingleImage(ctx, names[0], format, path, options)
|
||||
|
||||
case "docker-archive":
|
||||
options.ManifestMIMEType = manifest.DockerV2Schema2MediaType
|
||||
return r.saveDockerArchive(ctx, names, path, options)
|
||||
}
|
||||
|
||||
|
|
@ -134,6 +138,18 @@ func (r *Runtime) saveDockerArchive(ctx context.Context, names []string, path st
|
|||
tags []reference.NamedTagged
|
||||
}
|
||||
|
||||
additionalTags := []reference.NamedTagged{}
|
||||
for _, tag := range options.AdditionalTags {
|
||||
named, err := NormalizeName(tag)
|
||||
if err == nil {
|
||||
tagged, withTag := named.(reference.NamedTagged)
|
||||
if !withTag {
|
||||
return errors.Errorf("invalid additional tag %q: normalized to untagged %q", tag, named.String())
|
||||
}
|
||||
additionalTags = append(additionalTags, tagged)
|
||||
}
|
||||
}
|
||||
|
||||
orderedIDs := []string{} // to preserve the relative order
|
||||
localImages := make(map[string]*localImage) // to assemble tags
|
||||
visitedNames := make(map[string]bool) // filters duplicate names
|
||||
|
|
@ -153,6 +169,7 @@ func (r *Runtime) saveDockerArchive(ctx context.Context, names []string, path st
|
|||
local, exists := localImages[image.ID()]
|
||||
if !exists {
|
||||
local = &localImage{image: image}
|
||||
local.tags = additionalTags
|
||||
orderedIDs = append(orderedIDs, image.ID())
|
||||
}
|
||||
// Add the tag if the locally resolved name is properly tagged
|
||||
|
|
|
|||
|
|
@ -0,0 +1,109 @@
|
|||
package libimage
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/containers/common/pkg/config"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestSave(t *testing.T) {
|
||||
runtime, cleanup := testNewRuntime(t)
|
||||
defer cleanup()
|
||||
ctx := context.Background()
|
||||
|
||||
// Prefetch alpine, busybox.
|
||||
pullOptions := &PullOptions{}
|
||||
pullOptions.Writer = os.Stdout
|
||||
_, err := runtime.Pull(ctx, "docker.io/library/alpine:latest", config.PullPolicyAlways, pullOptions)
|
||||
require.NoError(t, err)
|
||||
_, err = runtime.Pull(ctx, "docker.io/library/busybox:latest", config.PullPolicyAlways, pullOptions)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Save the two images into a multi-image archive. This way, we can
|
||||
// reload the images for each test.
|
||||
saveOptions := &SaveOptions{}
|
||||
saveOptions.Writer = os.Stdout
|
||||
imageCache, err := ioutil.TempFile("", "saveimagecache")
|
||||
require.NoError(t, err)
|
||||
imageCache.Close()
|
||||
defer os.Remove(imageCache.Name())
|
||||
err = runtime.Save(ctx, []string{"alpine", "busybox"}, "docker-archive", imageCache.Name(), saveOptions)
|
||||
require.NoError(t, err)
|
||||
|
||||
loadOptions := &LoadOptions{}
|
||||
loadOptions.Writer = os.Stdout
|
||||
|
||||
// The table tests are smoke tests to exercise the different code
|
||||
// paths. More detailed tests follow below.
|
||||
for _, test := range []struct {
|
||||
names []string
|
||||
tags []string
|
||||
format string
|
||||
isDir bool
|
||||
expectError bool
|
||||
}{
|
||||
// No `names`
|
||||
{nil, nil, "", false, true},
|
||||
{[]string{}, nil, "", false, true},
|
||||
// Invalid/unsupported format
|
||||
{[]string{"something"}, nil, "", false, true},
|
||||
{[]string{"something"}, nil, "else", false, true},
|
||||
// oci
|
||||
{[]string{"busybox"}, nil, "oci-dir", true, false},
|
||||
{[]string{"busybox"}, nil, "oci-archive", false, false},
|
||||
// oci-archive doesn't support multi-image archives
|
||||
{[]string{"busybox", "alpine"}, nil, "oci-archive", false, true},
|
||||
// docker
|
||||
{[]string{"busybox"}, nil, "docker-archive", false, false},
|
||||
{[]string{"busybox"}, []string{"localhost/tag:1", "quay.io/repo/image:tag"}, "docker-archive", false, false},
|
||||
{[]string{"busybox"}, nil, "docker-dir", true, false},
|
||||
{[]string{"busybox", "alpine"}, nil, "docker-archive", false, false},
|
||||
// additional tags and multi-images conflict
|
||||
{[]string{"busybox", "alpine"}, []string{"tag"}, "docker-archive", false, true},
|
||||
} {
|
||||
// First clean up all images and load the cache.
|
||||
_, rmErrors := runtime.RemoveImages(ctx, nil, nil)
|
||||
require.Nil(t, rmErrors)
|
||||
_, err = runtime.Load(ctx, imageCache.Name(), loadOptions)
|
||||
require.NoError(t, err)
|
||||
|
||||
tmp, err := ioutil.TempDir("", "libimagesavetest")
|
||||
require.NoError(t, err)
|
||||
defer os.RemoveAll(tmp)
|
||||
if !test.isDir {
|
||||
tmp += "/archive.tar"
|
||||
}
|
||||
|
||||
saveOptions.AdditionalTags = test.tags
|
||||
err = runtime.Save(ctx, test.names, test.format, tmp, saveOptions)
|
||||
if test.expectError {
|
||||
require.Error(t, err, "%v", test)
|
||||
continue
|
||||
}
|
||||
require.NoError(t, err, "%v", test)
|
||||
|
||||
// Now remove all images again and attempt to load the
|
||||
// previously saved ones.
|
||||
_, rmErrors = runtime.RemoveImages(ctx, nil, nil)
|
||||
require.Nil(t, rmErrors)
|
||||
|
||||
namesAndTags := append(test.names, test.tags...)
|
||||
loadedImages, err := runtime.Load(ctx, tmp, loadOptions)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, loadedImages, len(namesAndTags))
|
||||
|
||||
// Now make sure that all specified names (and tags) resolve to
|
||||
// an image the local containers storage. Note that names are
|
||||
// only preserved in archives.
|
||||
if strings.HasSuffix(test.format, "-dir") {
|
||||
continue
|
||||
}
|
||||
_, err = runtime.ListImages(ctx, namesAndTags, nil)
|
||||
require.NoError(t, err, "%v", test)
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue