integration/liveRestore: Check volume content

Make sure that the content in the live-restored volume mounted in a new
container is the same as the content in the old container.
This checks if volume's _data directory doesn't get unmounted on
startup.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
(cherry picked from commit aef703fa1b)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Paweł Gronowski 2023-08-17 16:44:22 +02:00 committed by Sebastiaan van Stijn
parent 2db2638a96
commit ecdca2b06f
No known key found for this signature in database
GPG key ID: 76698F39D527CE8C

View file

@ -1,14 +1,17 @@
package daemon // import "github.com/docker/docker/integration/daemon"
import (
"bytes"
"context"
"fmt"
"io"
"net/http"
"net/http/httptest"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
"syscall"
"testing"
@ -16,7 +19,9 @@ import (
"github.com/docker/docker/api/types/mount"
"github.com/docker/docker/api/types/volume"
"github.com/docker/docker/daemon/config"
"github.com/docker/docker/errdefs"
"github.com/docker/docker/integration/internal/container"
"github.com/docker/docker/pkg/stdcopy"
"github.com/docker/docker/testutil/daemon"
"gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp"
@ -447,9 +452,28 @@ func testLiveRestoreVolumeReferences(t *testing.T) {
Source: v.Name,
Target: "/foo",
}
cID := container.Run(ctx, t, c, container.WithMount(m), container.WithCmd("top"))
const testContent = "hello"
cID := container.Run(ctx, t, c, container.WithMount(m), container.WithCmd("sh", "-c", "echo "+testContent+">>/foo/test.txt; sleep infinity"))
defer c.ContainerRemove(ctx, cID, types.ContainerRemoveOptions{Force: true})
// Wait until container creates a file in the volume.
poll.WaitOn(t, func(t poll.LogT) poll.Result {
stat, err := c.ContainerStatPath(ctx, cID, "/foo/test.txt")
if err != nil {
if errdefs.IsNotFound(err) {
return poll.Continue("file doesn't yet exist")
}
return poll.Error(err)
}
if int(stat.Size) != len(testContent)+1 {
return poll.Error(fmt.Errorf("unexpected test file size: %d", stat.Size))
}
return poll.Success()
})
d.Restart(t, "--live-restore", "--iptables=false")
// Try to remove the volume
@ -457,6 +481,32 @@ func testLiveRestoreVolumeReferences(t *testing.T) {
err = c.VolumeRemove(ctx, v.Name, false)
assert.ErrorContains(t, err, "volume is in use")
t.Run("volume still mounted", func(t *testing.T) {
skip.If(t, testEnv.IsRootless(), "restarted rootless daemon has a new mount namespace and it won't have the previous mounts")
// Check if a new container with the same volume has access to the previous content.
// This fails if the volume gets unmounted at startup.
cID2 := container.Run(ctx, t, c, container.WithMount(m), container.WithCmd("cat", "/foo/test.txt"))
defer c.ContainerRemove(ctx, cID2, types.ContainerRemoveOptions{Force: true})
poll.WaitOn(t, container.IsStopped(ctx, c, cID2))
inspect, err := c.ContainerInspect(ctx, cID2)
if assert.Check(t, err) {
assert.Check(t, is.Equal(inspect.State.ExitCode, 0), "volume doesn't have the same file")
}
logs, err := c.ContainerLogs(ctx, cID2, types.ContainerLogsOptions{ShowStdout: true})
assert.NilError(t, err)
defer logs.Close()
var stdoutBuf bytes.Buffer
_, err = stdcopy.StdCopy(&stdoutBuf, io.Discard, logs)
assert.NilError(t, err)
assert.Check(t, is.Equal(strings.TrimSpace(stdoutBuf.String()), testContent))
})
// Remove that container which should free the references in the volume
err = c.ContainerRemove(ctx, cID, types.ContainerRemoveOptions{Force: true})
assert.NilError(t, err)