Skip to content

Commit

Permalink
Fix bind mounts when in project volumes definition
Browse files Browse the repository at this point in the history
Signed-off-by: Ulysses Souza <[email protected]>
  • Loading branch information
ulyssessouza committed Jun 2, 2022
1 parent 6756732 commit 919f351
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 5 deletions.
25 changes: 20 additions & 5 deletions pkg/compose/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -718,9 +718,15 @@ MOUNTS:
// so `Bind` API is used here with raw volume string
// see https:/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
}
}
}
}
Expand Down Expand Up @@ -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,
Expand All @@ -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 {
Expand All @@ -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 {
Expand Down
14 changes: 14 additions & 0 deletions pkg/e2e/fixtures/project-volume-bind-test/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
services:
frontend:
image: nginx
container_name: frontend
volumes:
- project_data:/data

volumes:
project_data:
driver: local
driver_opts:
type: none
o: bind
device: "${TEST_DIR}"
13 changes: 13 additions & 0 deletions pkg/e2e/framework.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
30 changes: 30 additions & 0 deletions pkg/e2e/volumes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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 on project volume with bind specification", func(t *testing.T) {
tmpDir, err := os.MkdirTemp("", projectName)
assert.NilError(t, err)
defer os.RemoveAll(tmpDir) // nolint

c.RunDockerComposeCmd("--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-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"))
})
}

0 comments on commit 919f351

Please sign in to comment.