integration: Adds test for multilayer image import
This test will make sure there aren't any issues with multilayered images during import. Keep in mind that in the case of multilayered images, they have to be unpacked first in order to be usable. Signed-off-by: Claudiu Belu <cbelu@cloudbasesolutions.com>
This commit is contained in:
parent
45e0e5a77e
commit
7a7a9a282c
@ -32,9 +32,10 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
testImage = "ghcr.io/containerd/busybox:1.32"
|
testImage = "ghcr.io/containerd/busybox:1.32"
|
||||||
shortCommand = withProcessArgs("true")
|
testMultiLayeredImage = "gcr.io/k8s-cri-containerd/volume-copy-up:2.1"
|
||||||
longCommand = withProcessArgs("/bin/sh", "-c", "while true; do sleep 1; done")
|
shortCommand = withProcessArgs("true")
|
||||||
|
longCommand = withProcessArgs("/bin/sh", "-c", "while true; do sleep 1; done")
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestImagePullSchema1WithEmptyLayers(t *testing.T) {
|
func TestImagePullSchema1WithEmptyLayers(t *testing.T) {
|
||||||
|
@ -30,11 +30,12 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
defaultRoot = filepath.Join(os.Getenv("programfiles"), "containerd", "root-test")
|
defaultRoot = filepath.Join(os.Getenv("programfiles"), "containerd", "root-test")
|
||||||
defaultState = filepath.Join(os.Getenv("programfiles"), "containerd", "state-test")
|
defaultState = filepath.Join(os.Getenv("programfiles"), "containerd", "state-test")
|
||||||
testImage string
|
testImage string
|
||||||
shortCommand = withTrue()
|
testMultiLayeredImage = "gcr.io/k8s-cri-containerd/volume-copy-up:2.1"
|
||||||
longCommand = withProcessArgs("ping", "-t", "localhost")
|
shortCommand = withTrue()
|
||||||
|
longCommand = withProcessArgs("ping", "-t", "localhost")
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -27,12 +27,17 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
. "github.com/containerd/containerd"
|
. "github.com/containerd/containerd"
|
||||||
"github.com/containerd/containerd/archive/compression"
|
"github.com/containerd/containerd/archive/compression"
|
||||||
"github.com/containerd/containerd/archive/tartest"
|
"github.com/containerd/containerd/archive/tartest"
|
||||||
"github.com/containerd/containerd/images"
|
"github.com/containerd/containerd/images"
|
||||||
"github.com/containerd/containerd/images/archive"
|
"github.com/containerd/containerd/images/archive"
|
||||||
|
"github.com/containerd/containerd/leases"
|
||||||
|
"github.com/containerd/containerd/oci"
|
||||||
|
"github.com/containerd/containerd/platforms"
|
||||||
|
|
||||||
digest "github.com/opencontainers/go-digest"
|
digest "github.com/opencontainers/go-digest"
|
||||||
specs "github.com/opencontainers/image-spec/specs-go"
|
specs "github.com/opencontainers/image-spec/specs-go"
|
||||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
@ -41,6 +46,18 @@ import (
|
|||||||
// TestExportAndImport exports testImage as a tar stream,
|
// TestExportAndImport exports testImage as a tar stream,
|
||||||
// and import the tar stream as a new image.
|
// and import the tar stream as a new image.
|
||||||
func TestExportAndImport(t *testing.T) {
|
func TestExportAndImport(t *testing.T) {
|
||||||
|
testExportImport(t, testImage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestExportAndImportMultiLayer exports testMultiLayeredImage as a tar stream,
|
||||||
|
// and import the tar stream as a new image. This should ensure that imported
|
||||||
|
// images remain sane, and that the Garbage Collector won't delete part of its
|
||||||
|
// content.
|
||||||
|
func TestExportAndImportMultiLayer(t *testing.T) {
|
||||||
|
testExportImport(t, testMultiLayeredImage)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testExportImport(t *testing.T, imageName string) {
|
||||||
if testing.Short() {
|
if testing.Short() {
|
||||||
t.Skip()
|
t.Skip()
|
||||||
}
|
}
|
||||||
@ -53,17 +70,19 @@ func TestExportAndImport(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer client.Close()
|
defer client.Close()
|
||||||
|
|
||||||
_, err = client.Fetch(ctx, testImage)
|
_, err = client.Fetch(ctx, imageName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
wb := bytes.NewBuffer(nil)
|
wb := bytes.NewBuffer(nil)
|
||||||
err = client.Export(ctx, wb, archive.WithAllPlatforms(), archive.WithImage(client.ImageService(), testImage))
|
err = client.Export(ctx, wb, archive.WithPlatform(platforms.Default()), archive.WithImage(client.ImageService(), imageName))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
client.ImageService().Delete(ctx, imageName)
|
||||||
|
|
||||||
opts := []ImportOpt{
|
opts := []ImportOpt{
|
||||||
WithImageRefTranslator(archive.AddRefPrefix("foo/bar")),
|
WithImageRefTranslator(archive.AddRefPrefix("foo/bar")),
|
||||||
}
|
}
|
||||||
@ -72,6 +91,41 @@ func TestExportAndImport(t *testing.T) {
|
|||||||
t.Fatalf("Import failed: %+v", err)
|
t.Fatalf("Import failed: %+v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We need to unpack the image, especially if it's multilayered.
|
||||||
|
for _, img := range imgrecs {
|
||||||
|
image := NewImage(client, img)
|
||||||
|
|
||||||
|
// TODO: Show unpack status
|
||||||
|
t.Logf("unpacking %s (%s)...", img.Name, img.Target.Digest)
|
||||||
|
err = image.Unpack(ctx, "")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error while unpacking image: %+v", err)
|
||||||
|
}
|
||||||
|
t.Log("done")
|
||||||
|
}
|
||||||
|
|
||||||
|
// we're triggering the Garbage Collector to do its job.
|
||||||
|
ls := client.LeasesService()
|
||||||
|
l, err := ls.Create(ctx, leases.WithRandomID(), leases.WithExpiration(time.Hour))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error while creating lease: %+v", err)
|
||||||
|
}
|
||||||
|
if err = ls.Delete(ctx, l, leases.SynchronousDelete); err != nil {
|
||||||
|
t.Fatalf("Error while deleting lease: %+v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
image, err := client.GetImage(ctx, imageName)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
id := t.Name()
|
||||||
|
container, err := client.NewContainer(ctx, id, WithNewSnapshot(id, image), WithNewSpec(oci.WithImageConfig(image)))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error while creating container: %+v", err)
|
||||||
|
}
|
||||||
|
container.Delete(ctx, WithSnapshotCleanup)
|
||||||
|
|
||||||
for _, imgrec := range imgrecs {
|
for _, imgrec := range imgrecs {
|
||||||
if imgrec.Name == testImage {
|
if imgrec.Name == testImage {
|
||||||
continue
|
continue
|
||||||
|
Loading…
Reference in New Issue
Block a user