github.com/rumpl/bof@v23.0.0-rc.2+incompatible/integration/container/checkpoint_test.go (about)

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