github.com/Prakhar-Agarwal-byte/moby@v0.0.0-20231027092010-a14e3e8ab87e/integration/container/checkpoint_test.go (about) 1 package container // import "github.com/Prakhar-Agarwal-byte/moby/integration/container" 2 3 import ( 4 "context" 5 "os/exec" 6 "regexp" 7 "sort" 8 "testing" 9 "time" 10 11 "github.com/Prakhar-Agarwal-byte/moby/api/types/checkpoint" 12 containertypes "github.com/Prakhar-Agarwal-byte/moby/api/types/container" 13 mounttypes "github.com/Prakhar-Agarwal-byte/moby/api/types/mount" 14 "github.com/Prakhar-Agarwal-byte/moby/client" 15 "github.com/Prakhar-Agarwal-byte/moby/integration/internal/container" 16 "github.com/Prakhar-Agarwal-byte/moby/testutil/request" 17 "gotest.tools/v3/assert" 18 is "gotest.tools/v3/assert/cmp" 19 "gotest.tools/v3/poll" 20 "gotest.tools/v3/skip" 21 ) 22 23 //nolint:unused // false positive: linter detects this as "unused" 24 func containerExec(ctx context.Context, t *testing.T, client client.APIClient, cID string, cmd []string) { 25 t.Logf("Exec: %s", cmd) 26 r, err := container.Exec(ctx, client, cID, cmd) 27 assert.NilError(t, err) 28 t.Log(r.Combined()) 29 assert.Equal(t, r.ExitCode, 0) 30 } 31 32 func TestCheckpoint(t *testing.T) { 33 t.Skip("TestCheckpoint is broken; see https://github.com/moby/moby/issues/38963") 34 skip.If(t, testEnv.DaemonInfo.OSType == "windows") 35 skip.If(t, !testEnv.DaemonInfo.ExperimentalBuild) 36 37 ctx := setupTest(t) 38 39 stdoutStderr, err := exec.Command("criu", "check").CombinedOutput() 40 t.Logf("%s", stdoutStderr) 41 assert.NilError(t, err) 42 43 apiClient := request.NewAPIClient(t) 44 45 t.Log("Start a container") 46 cID := container.Run(ctx, t, apiClient, container.WithMount(mounttypes.Mount{ 47 Type: mounttypes.TypeTmpfs, 48 Target: "/tmp", 49 })) 50 51 // FIXME: ipv6 iptables modules are not uploaded in the test environment 52 stdoutStderr, err = exec.Command("bash", "-c", "set -x; "+ 53 "mount --bind $(type -P true) $(type -P ip6tables-restore) && "+ 54 "mount --bind $(type -P true) $(type -P ip6tables-save)", 55 ).CombinedOutput() 56 t.Logf("%s", stdoutStderr) 57 assert.NilError(t, err) 58 59 defer func() { 60 stdoutStderr, err = exec.Command("bash", "-c", "set -x; "+ 61 "umount -c -i -l $(type -P ip6tables-restore); "+ 62 "umount -c -i -l $(type -P ip6tables-save)", 63 ).CombinedOutput() 64 t.Logf("%s", stdoutStderr) 65 assert.NilError(t, err) 66 }() 67 68 t.Log("Do a checkpoint and leave the container running") 69 err = apiClient.CheckpointCreate(ctx, cID, checkpoint.CreateOptions{ 70 Exit: false, 71 CheckpointID: "test", 72 }) 73 if err != nil { 74 // An error can contain a path to a dump file 75 t.Log(err) 76 re := regexp.MustCompile("path= (.*): ") 77 m := re.FindStringSubmatch(err.Error()) 78 if len(m) >= 2 { 79 dumpLog := m[1] 80 t.Logf("%s", dumpLog) 81 cmd := exec.Command("cat", dumpLog) 82 stdoutStderr, err = cmd.CombinedOutput() 83 t.Logf("%s", stdoutStderr) 84 } 85 } 86 assert.NilError(t, err) 87 88 inspect, err := apiClient.ContainerInspect(ctx, cID) 89 assert.NilError(t, err) 90 assert.Check(t, is.Equal(true, inspect.State.Running)) 91 92 checkpoints, err := apiClient.CheckpointList(ctx, cID, checkpoint.ListOptions{}) 93 assert.NilError(t, err) 94 assert.Equal(t, len(checkpoints), 1) 95 assert.Equal(t, checkpoints[0].Name, "test") 96 97 // Create a test file on a tmpfs mount. 98 containerExec(ctx, t, apiClient, cID, []string{"touch", "/tmp/test-file"}) 99 100 // Do a second checkpoint 101 t.Log("Do a checkpoint and stop the container") 102 err = apiClient.CheckpointCreate(ctx, cID, checkpoint.CreateOptions{ 103 Exit: true, 104 CheckpointID: "test2", 105 }) 106 assert.NilError(t, err) 107 108 poll.WaitOn(t, 109 container.IsInState(ctx, apiClient, cID, "exited"), 110 poll.WithDelay(100*time.Millisecond), 111 ) 112 113 inspect, err = apiClient.ContainerInspect(ctx, cID) 114 assert.NilError(t, err) 115 assert.Check(t, is.Equal(false, inspect.State.Running)) 116 117 // Check that both checkpoints are listed. 118 checkpoints, err = apiClient.CheckpointList(ctx, cID, checkpoint.ListOptions{}) 119 assert.NilError(t, err) 120 assert.Equal(t, len(checkpoints), 2) 121 cptNames := make([]string, 2) 122 for i, c := range checkpoints { 123 cptNames[i] = c.Name 124 } 125 sort.Strings(cptNames) 126 assert.Equal(t, cptNames[0], "test") 127 assert.Equal(t, cptNames[1], "test2") 128 129 // Restore the container from a second checkpoint. 130 t.Log("Restore the container") 131 err = apiClient.ContainerStart(ctx, cID, containertypes.StartOptions{ 132 CheckpointID: "test2", 133 }) 134 assert.NilError(t, err) 135 136 inspect, err = apiClient.ContainerInspect(ctx, cID) 137 assert.NilError(t, err) 138 assert.Check(t, is.Equal(true, inspect.State.Running)) 139 140 // Check that the test file has been restored. 141 containerExec(ctx, t, apiClient, cID, []string{"test", "-f", "/tmp/test-file"}) 142 143 for _, id := range []string{"test", "test2"} { 144 err = apiClient.CheckpointDelete(ctx, cID, checkpoint.DeleteOptions{ 145 CheckpointID: id, 146 }) 147 assert.NilError(t, err) 148 } 149 }