Sfoglia il codice sorgente

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>
Paweł Gronowski 1 anno fa
parent
commit
aef703fa1b
1 ha cambiato i file con 51 aggiunte e 1 eliminazioni
  1. 51 1
      integration/daemon/daemon_test.go

+ 51 - 1
integration/daemon/daemon_test.go

@@ -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"
 
@@ -17,7 +20,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"
@@ -432,9 +437,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
@@ -442,6 +466,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)