| package daemon | |
| import ( | |
| "bytes" | |
| "io" | |
| "runtime" | |
| "testing" | |
| "github.com/moby/moby/client" | |
| "github.com/moby/moby/v2/integration/internal/container" | |
| "github.com/moby/moby/v2/internal/testutil" | |
| "github.com/moby/moby/v2/internal/testutil/daemon" | |
| "github.com/moby/moby/v2/internal/testutil/fixtures/load" | |
| "gotest.tools/v3/assert" | |
| "gotest.tools/v3/skip" | |
| ) | |
| func TestMigrateOverlaySnapshotter(t *testing.T) { | |
| testMigrateSnapshotter(t, "overlay2", "overlayfs") | |
| } | |
| func TestMigrateNativeSnapshotter(t *testing.T) { | |
| testMigrateSnapshotter(t, "vfs", "native") | |
| } | |
| func testMigrateSnapshotter(t *testing.T, graphdriver, snapshotter string) { | |
| skip.If(t, runtime.GOOS != "linux") | |
| t.Setenv("DOCKER_MIGRATE_SNAPSHOTTER_THRESHOLD", "200M") | |
| t.Setenv("DOCKER_DRIVER", "") | |
| ctx := testutil.StartSpan(baseContext, t) | |
| d := daemon.New(t) | |
| defer d.Stop(t) | |
| d.Start(t, "--iptables=false", "--ip6tables=false", "-s", graphdriver) | |
| info := d.Info(t) | |
| id := info.ID | |
| assert.Check(t, id != "") | |
| assert.Equal(t, info.Containers, 0) | |
| assert.Equal(t, info.Images, 0) | |
| assert.Equal(t, info.Driver, graphdriver) | |
| load.FrozenImagesLinux(ctx, d.NewClientT(t), "busybox:latest") | |
| info = d.Info(t) | |
| allImages := info.Images | |
| assert.Check(t, allImages > 0) | |
| apiClient := d.NewClientT(t) | |
| containerID := container.Run(ctx, t, apiClient, func(c *container.TestContainerConfig) { | |
| c.Name = "Migration-1-" + snapshotter | |
| c.Config.Image = "busybox:latest" | |
| c.Config.Cmd = []string{"top"} | |
| }) | |
| d.Stop(t) | |
| // Start with migration feature but with a container which will prevent migration | |
| d.Start(t, "--iptables=false", "--ip6tables=false", "-s", graphdriver, "--feature", "containerd-migration") | |
| info = d.Info(t) | |
| assert.Equal(t, info.ID, id) | |
| assert.Equal(t, info.Driver, graphdriver) | |
| assert.Equal(t, info.Containers, 1) | |
| assert.Equal(t, info.Images, allImages) | |
| container.Remove(ctx, t, apiClient, containerID, client.ContainerRemoveOptions{ | |
| Force: true, | |
| }) | |
| d.Stop(t) | |
| d.Start(t, "--iptables=false", "--ip6tables=false", "-s", graphdriver, "--feature", "containerd-migration") | |
| info = d.Info(t) | |
| assert.Equal(t, info.ID, id) | |
| assert.Equal(t, info.Containers, 0) | |
| assert.Equal(t, info.Driver, snapshotter, "expected migrate to switch from %s to %s", graphdriver, snapshotter) | |
| assert.Equal(t, info.Images, allImages) | |
| result := container.RunAttach(ctx, t, apiClient, func(c *container.TestContainerConfig) { | |
| c.Name = "Migration-2-" + snapshotter | |
| c.Config.Image = "busybox:latest" | |
| c.Config.Cmd = []string{"echo", "hello"} | |
| }) | |
| assert.Equal(t, result.ExitCode, 0) | |
| container.Remove(ctx, t, apiClient, result.ContainerID, client.ContainerRemoveOptions{}) | |
| } | |
| func TestMigrateSaveLoad(t *testing.T) { | |
| skip.If(t, runtime.GOOS != "linux") | |
| t.Setenv("DOCKER_MIGRATE_SNAPSHOTTER_THRESHOLD", "200M") | |
| t.Setenv("DOCKER_DRIVER", "") | |
| var ( | |
| ctx = testutil.StartSpan(baseContext, t) | |
| d = daemon.New(t) | |
| graphdriver = "overlay2" | |
| snapshotter = "overlayfs" | |
| ) | |
| defer d.Stop(t) | |
| d.Start(t, "--iptables=false", "--ip6tables=false", "-s", graphdriver) | |
| info := d.Info(t) | |
| id := info.ID | |
| assert.Check(t, id != "") | |
| assert.Equal(t, info.Containers, 0) | |
| assert.Equal(t, info.Images, 0) | |
| assert.Equal(t, info.Driver, graphdriver) | |
| load.FrozenImagesLinux(ctx, d.NewClientT(t), "busybox:latest") | |
| info = d.Info(t) | |
| allImages := info.Images | |
| assert.Check(t, allImages > 0) | |
| d.Stop(t) | |
| d.Start(t, "--iptables=false", "--ip6tables=false", "-s", graphdriver, "--feature", "containerd-migration") | |
| info = d.Info(t) | |
| assert.Equal(t, info.ID, id) | |
| assert.Equal(t, info.Containers, 0) | |
| assert.Equal(t, info.Driver, snapshotter, "expected migrate to switch from %s to %s", graphdriver, snapshotter) | |
| assert.Equal(t, info.Images, allImages) | |
| apiClient := d.NewClientT(t) | |
| // Save image to buffer | |
| rdr, err := apiClient.ImageSave(ctx, []string{"busybox:latest"}) | |
| assert.NilError(t, err) | |
| buf := bytes.NewBuffer(nil) | |
| _, _ = io.Copy(buf, rdr) | |
| defer func() { _ = rdr.Close() }() | |
| // Delete all images | |
| list, err := apiClient.ImageList(ctx, client.ImageListOptions{}) | |
| assert.NilError(t, err) | |
| for _, i := range list.Items { | |
| _, err = apiClient.ImageRemove(ctx, i.ID, client.ImageRemoveOptions{Force: true}) | |
| assert.NilError(t, err) | |
| } | |
| // Check zero images | |
| info = d.Info(t) | |
| assert.Equal(t, info.Images, 0) | |
| // Import | |
| resp, err := apiClient.ImageLoad(ctx, bytes.NewReader(buf.Bytes()), client.ImageLoadWithQuiet(true)) | |
| assert.NilError(t, err) | |
| _, _ = io.Copy(io.Discard, resp) | |
| _ = resp.Close() | |
| result := container.RunAttach(ctx, t, apiClient, func(c *container.TestContainerConfig) { | |
| c.Name = "Migration-save-load-" + snapshotter | |
| c.Config.Image = "busybox:latest" | |
| c.Config.Cmd = []string{"echo", "hello"} | |
| }) | |
| assert.Equal(t, result.ExitCode, 0) | |
| container.Remove(ctx, t, apiClient, result.ContainerID, client.ContainerRemoveOptions{}) | |
| } |