Skip to content

Commit

Permalink
mount: Add volume-subpath option
Browse files Browse the repository at this point in the history
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
  • Loading branch information
vvoland committed Feb 8, 2024
1 parent 79fa65e commit 9f52b2f
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 0 deletions.
53 changes: 53 additions & 0 deletions e2e/container/run_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package container

import (
"fmt"
"strings"
"testing"

"github.com/docker/cli/e2e/internal/fixtures"
Expand Down Expand Up @@ -149,3 +150,55 @@ func TestRunWithCgroupNamespace(t *testing.T) {
"/bin/grep", "-q", "':memory:/$'", "/proc/1/cgroup")
result.Assert(t, icmd.Success)
}

func TestMountSubvolume(t *testing.T) {
environment.SkipIfAPIOlder(t, "1.45")
volName := "test-volume-" + t.Name()
icmd.RunCommand("docker", "volume", "create", volName).Assert(t, icmd.Success)

t.Cleanup(func() {
icmd.RunCommand("docker", "volume", "remove", "-f", volName).Assert(t, icmd.Success)
})

defaultMountOpts := []string{
"type=volume",
"src=" + volName,
"dst=/volume",
}

// Populate the volume with test data.
icmd.RunCommand("docker", "run", "--rm", "--mount", strings.Join(defaultMountOpts, ","), fixtures.AlpineImage, "sh", "-c",
"echo foo > /volume/bar.txt && "+
"mkdir /volume/etc && echo root > /volume/etc/passwd && "+
"mkdir /volume/subdir && echo world > /volume/subdir/hello.txt;",
).Assert(t, icmd.Success)

runMount := func(cmd string, mountOpts ...string) *icmd.Result {
mountArg := strings.Join(append(defaultMountOpts, mountOpts...), ",")
return icmd.RunCommand("docker", "run", "--rm", "--mount", mountArg, fixtures.AlpineImage, cmd, "/volume")
}

for _, tc := range []struct {
name string
cmd string
subpath string

expectedOut string
expectedErr string
expectedCode int
}{
{name: "absolute", cmd: "cat", subpath: "/etc/passwd", expectedErr: "subpath must be a relative path within the volume", expectedCode: 125},
{name: "subpath not exists", cmd: "ls", subpath: "some-path/that/doesnt-exist", expectedErr: "cannot access path ", expectedCode: 127},
{name: "subdirectory mount", cmd: "ls", subpath: "subdir", expectedOut: "hello.txt"},
{name: "file mount", cmd: "cat", subpath: "bar.txt", expectedOut: "foo"},
} {
tc := tc
t.Run(tc.name, func(t *testing.T) {
runMount(tc.cmd, "volume-subpath="+tc.subpath).Assert(t, icmd.Expected{
Err: tc.expectedErr,
ExitCode: tc.expectedCode,
Out: tc.expectedOut,
})
})
}
}
13 changes: 13 additions & 0 deletions internal/test/environment/testenv.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"testing"
"time"

"github.com/docker/docker/api/types/versions"
"github.com/docker/docker/client"
"github.com/pkg/errors"
"gotest.tools/v3/icmd"
Expand Down Expand Up @@ -108,3 +109,15 @@ func SkipIfNotPlatform(t *testing.T, platform string) {
daemonPlatform := strings.TrimSpace(result.Stdout())
skip.If(t, daemonPlatform != platform, "running against a non %s daemon", platform)
}

func SkipIfAPIOlder(t *testing.T, minimumVersion string) {
t.Helper()
// Use Client.APIVersion instead of Server.APIVersion.
// The latter is the maximum version that the server supports
// while the Client.APIVersion contains the negotiated version.
result := icmd.RunCmd(icmd.Command("docker", "version", "--format", "{{.Client.APIVersion}}"))
result.Assert(t, icmd.Expected{Err: icmd.None})
negotiatedVersion := strings.TrimSpace(result.Stdout())

skip.If(t, versions.LessThan(negotiatedVersion, minimumVersion), "API too old (%s < %s)", negotiatedVersion, minimumVersion)
}
2 changes: 2 additions & 0 deletions opts/mount.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,8 @@ func (m *MountOpt) Set(value string) error {
return fmt.Errorf("invalid value for %s: %s (must be \"enabled\", \"disabled\", \"writable\", or \"readonly\")",
key, val)
}
case "volume-subpath":
volumeOptions().Subpath = val
case "volume-nocopy":
volumeOptions().NoCopy, err = strconv.ParseBool(val)
if err != nil {
Expand Down

0 comments on commit 9f52b2f

Please sign in to comment.