1
0
Эх сурвалжийг харах

Fix bind mounts when in project volumes definition

Signed-off-by: Ulysses Souza <[email protected]>
Ulysses Souza 3 жил өмнө
parent
commit
0ba46049db

+ 20 - 5
pkg/compose/create.go

@@ -718,9 +718,15 @@ MOUNTS:
 			// so `Bind` API is used here with raw volume string
 			// see https://github.com/moby/moby/issues/43483
 			for _, v := range service.Volumes {
-				if v.Target == m.Target && v.Bind != nil && v.Bind.CreateHostPath {
-					binds = append(binds, v.String())
-					continue MOUNTS
+				if v.Target == m.Target {
+					switch {
+					case string(m.Type) != v.Type:
+						v.Source = m.Source
+						fallthrough
+					case v.Bind != nil && v.Bind.CreateHostPath:
+						binds = append(binds, v.String())
+						continue MOUNTS
+					}
 				}
 			}
 		}
@@ -911,10 +917,14 @@ func buildMount(project types.Project, volume types.ServiceVolumeConfig) (mount.
 		}
 	}
 
-	bind, vol, tmpfs := buildMountOptions(volume)
+	bind, vol, tmpfs := buildMountOptions(project, volume)
 
 	volume.Target = path.Clean(volume.Target)
 
+	if bind != nil {
+		volume.Type = types.VolumeTypeBind
+	}
+
 	return mount.Mount{
 		Type:          mount.Type(volume.Type),
 		Source:        source,
@@ -927,7 +937,7 @@ func buildMount(project types.Project, volume types.ServiceVolumeConfig) (mount.
 	}, nil
 }
 
-func buildMountOptions(volume types.ServiceVolumeConfig) (*mount.BindOptions, *mount.VolumeOptions, *mount.TmpfsOptions) {
+func buildMountOptions(project types.Project, volume types.ServiceVolumeConfig) (*mount.BindOptions, *mount.VolumeOptions, *mount.TmpfsOptions) {
 	switch volume.Type {
 	case "bind":
 		if volume.Volume != nil {
@@ -944,6 +954,11 @@ func buildMountOptions(volume types.ServiceVolumeConfig) (*mount.BindOptions, *m
 		if volume.Tmpfs != nil {
 			logrus.Warnf("mount of type `volume` should not define `tmpfs` option")
 		}
+		if v, ok := project.Volumes[volume.Source]; ok && v.DriverOpts["o"] == types.VolumeTypeBind {
+			return buildBindOption(&types.ServiceVolumeBind{
+				CreateHostPath: true,
+			}), nil, nil
+		}
 		return nil, buildVolumeOptions(volume.Volume), nil
 	case "tmpfs":
 		if volume.Bind != nil {

+ 13 - 0
pkg/e2e/framework.go

@@ -167,6 +167,19 @@ func (c *E2eCLI) NewCmd(command string, args ...string) icmd.Cmd {
 	}
 }
 
+// NewCmdWithEnv creates a cmd object configured with the test environment set with additional env vars
+func (c *E2eCLI) NewCmdWithEnv(envvars []string, command string, args ...string) icmd.Cmd {
+	env := append(os.Environ(),
+		append(envvars,
+			"DOCKER_CONFIG="+c.ConfigDir,
+			"KUBECONFIG=invalid")...
+	)
+	return icmd.Cmd{
+		Command: append([]string{command}, args...),
+		Env:     env,
+	}
+}
+
 // MetricsSocket get the path where test metrics will be sent
 func (c *E2eCLI) MetricsSocket() string {
 	return filepath.Join(c.ConfigDir, "./docker-cli.sock")

+ 30 - 0
pkg/e2e/volumes_test.go

@@ -18,11 +18,14 @@ package e2e
 
 import (
 	"net/http"
+	"os"
+	"path/filepath"
 	"strings"
 	"testing"
 	"time"
 
 	"gotest.tools/v3/assert"
+	"gotest.tools/v3/icmd"
 )
 
 func TestLocalComposeVolume(t *testing.T) {
@@ -88,3 +91,30 @@ func TestLocalComposeVolume(t *testing.T) {
 		assert.Assert(t, !strings.Contains(ls, "myvolume"))
 	})
 }
+
+func TestProjectVolumeBind(t *testing.T) {
+	if composeStandaloneMode {
+		t.Skip()
+	}
+	c := NewParallelE2eCLI(t, binDir)
+	const projectName = "compose-e2e-project-volume-bind"
+
+	t.Run("up with build and no image name, volume", func(t *testing.T) {
+		tmpDir, err := os.MkdirTemp("", projectName)
+		assert.NilError(t, err)
+		defer os.RemoveAll(tmpDir)
+
+		c.RunDockerComposeCmd("--project-directory", "fixtures/project-volume-bind-test", "--project-name", projectName, "down")
+
+		c.RunDockerOrExitError("volume", "rm", "-f", projectName+"_project_data").Assert(t, icmd.Success)
+		cmd := c.NewCmdWithEnv([]string{"TEST_DIR=" + tmpDir},
+			"docker", "compose", "--project-directory", "fixtures/project-volume-bind-test", "--project-name", projectName, "up", "-d")
+		icmd.RunCmd(cmd).Assert(t, icmd.Success)
+		defer c.RunDockerComposeCmd("--project-directory", "fixtures/project-volume-bind-test", "--project-name", projectName, "down")
+
+		c.RunCmd("sh", "-c", "echo SUCCESS > "+filepath.Join(tmpDir, "resultfile")).Assert(t, icmd.Success)
+
+		ret := c.RunDockerOrExitError("exec", "frontend", "bash", "-c", "cat /data/resultfile").Assert(t, icmd.Success)
+		assert.Assert(t, strings.Contains(ret.Stdout(), "SUCCESS"))
+	})
+}