@@ -27,12 +27,17 @@ import (
2727 "reflect"
2828 "runtime"
2929 "testing"
30+ "time"
3031
3132 . "github.com/containerd/containerd"
3233 "github.com/containerd/containerd/archive/compression"
3334 "github.com/containerd/containerd/archive/tartest"
3435 "github.com/containerd/containerd/images"
3536 "github.com/containerd/containerd/images/archive"
37+ "github.com/containerd/containerd/leases"
38+ "github.com/containerd/containerd/oci"
39+ "github.com/containerd/containerd/platforms"
40+
3641 digest "github.com/opencontainers/go-digest"
3742 specs "github.com/opencontainers/image-spec/specs-go"
3843 ocispec "github.com/opencontainers/image-spec/specs-go/v1"
@@ -41,6 +46,18 @@ import (
4146// TestExportAndImport exports testImage as a tar stream,
4247// and import the tar stream as a new image.
4348func TestExportAndImport (t * testing.T ) {
49+ testExportImport (t , testImage )
50+ }
51+
52+ // TestExportAndImportMultiLayer exports testMultiLayeredImage as a tar stream,
53+ // and import the tar stream as a new image. This should ensure that imported
54+ // images remain sane, and that the Garbage Collector won't delete part of its
55+ // content.
56+ func TestExportAndImportMultiLayer (t * testing.T ) {
57+ testExportImport (t , testMultiLayeredImage )
58+ }
59+
60+ func testExportImport (t * testing.T , imageName string ) {
4461 if testing .Short () {
4562 t .Skip ()
4663 }
@@ -53,17 +70,19 @@ func TestExportAndImport(t *testing.T) {
5370 }
5471 defer client .Close ()
5572
56- _ , err = client .Fetch (ctx , testImage )
73+ _ , err = client .Fetch (ctx , imageName )
5774 if err != nil {
5875 t .Fatal (err )
5976 }
6077
6178 wb := bytes .NewBuffer (nil )
62- err = client .Export (ctx , wb , archive .WithAllPlatforms () , archive .WithImage (client .ImageService (), testImage ))
79+ err = client .Export (ctx , wb , archive .WithPlatform ( platforms . Default ()) , archive .WithImage (client .ImageService (), imageName ))
6380 if err != nil {
6481 t .Fatal (err )
6582 }
6683
84+ client .ImageService ().Delete (ctx , imageName )
85+
6786 opts := []ImportOpt {
6887 WithImageRefTranslator (archive .AddRefPrefix ("foo/bar" )),
6988 }
@@ -72,6 +91,41 @@ func TestExportAndImport(t *testing.T) {
7291 t .Fatalf ("Import failed: %+v" , err )
7392 }
7493
94+ // We need to unpack the image, especially if it's multilayered.
95+ for _ , img := range imgrecs {
96+ image := NewImage (client , img )
97+
98+ // TODO: Show unpack status
99+ t .Logf ("unpacking %s (%s)..." , img .Name , img .Target .Digest )
100+ err = image .Unpack (ctx , "" )
101+ if err != nil {
102+ t .Fatalf ("Error while unpacking image: %+v" , err )
103+ }
104+ t .Log ("done" )
105+ }
106+
107+ // we're triggering the Garbage Collector to do its job.
108+ ls := client .LeasesService ()
109+ l , err := ls .Create (ctx , leases .WithRandomID (), leases .WithExpiration (time .Hour ))
110+ if err != nil {
111+ t .Fatalf ("Error while creating lease: %+v" , err )
112+ }
113+ if err = ls .Delete (ctx , l , leases .SynchronousDelete ); err != nil {
114+ t .Fatalf ("Error while deleting lease: %+v" , err )
115+ }
116+
117+ image , err := client .GetImage (ctx , imageName )
118+ if err != nil {
119+ t .Fatal (err )
120+ }
121+
122+ id := t .Name ()
123+ container , err := client .NewContainer (ctx , id , WithNewSnapshot (id , image ), WithNewSpec (oci .WithImageConfig (image )))
124+ if err != nil {
125+ t .Fatalf ("Error while creating container: %+v" , err )
126+ }
127+ container .Delete (ctx , WithSnapshotCleanup )
128+
75129 for _ , imgrec := range imgrecs {
76130 if imgrec .Name == testImage {
77131 continue
0 commit comments