diff options
author | Jason T. Greene <jason.greene@redhat.com> | 2022-03-24 22:07:55 -0500 |
---|---|---|
committer | Jason T. Greene <jason.greene@redhat.com> | 2022-04-25 13:52:27 -0500 |
commit | b0d36f63513ee64fa1c1eff4d1045a7633804f12 (patch) | |
tree | 3bb66bef188e12daae252a18234e544a9be1b145 /pkg/specgenutil | |
parent | 3b6ffcd290978f5e0110e925c212d6396accee10 (diff) | |
download | podman-b0d36f63513ee64fa1c1eff4d1045a7633804f12.tar.gz podman-b0d36f63513ee64fa1c1eff4d1045a7633804f12.tar.bz2 podman-b0d36f63513ee64fa1c1eff4d1045a7633804f12.zip |
Implements Windows volume/mount support
Based on WSL2 9p support: remaps windows paths to /mnt/<drive> locations for
both podman and Docker API clients.
Signed-off-by: Jason T. Greene <jason.greene@redhat.com>
Diffstat (limited to 'pkg/specgenutil')
-rw-r--r-- | pkg/specgenutil/specgenutil_test.go | 77 | ||||
-rw-r--r-- | pkg/specgenutil/volumes.go | 21 |
2 files changed, 90 insertions, 8 deletions
diff --git a/pkg/specgenutil/specgenutil_test.go b/pkg/specgenutil/specgenutil_test.go new file mode 100644 index 000000000..5867b0ae0 --- /dev/null +++ b/pkg/specgenutil/specgenutil_test.go @@ -0,0 +1,77 @@ +//go:build linux +// +build linux + +package specgenutil + +import ( + "testing" + + "github.com/containers/common/pkg/machine" + "github.com/containers/podman/v4/pkg/domain/entities" + "github.com/containers/podman/v4/pkg/specgen" + "github.com/stretchr/testify/assert" +) + +func TestWinPath(t *testing.T) { + const ( + fail = false + pass = true + ) + tests := []struct { + vol string + source string + dest string + isN bool + outcome bool + mach string + }{ + {`C:\Foo:/blah`, "/mnt/c/Foo", "/blah", false, pass, "wsl"}, + {`C:\Foo:/blah`, "/mnt/c/Foo", "/blah", false, fail, ""}, + {`\\?\C:\Foo:/blah`, "/mnt/c/Foo", "/blah", false, pass, "wsl"}, + {`/c/bar:/blah`, "/mnt/c/bar", "/blah", false, pass, "wsl"}, + {`/c/bar:/blah`, "/c/bar", "/blah", false, pass, ""}, + {`/test/this:/blah`, "/test/this", "/blah", false, pass, "wsl"}, + {`c:/bar/something:/other`, "/mnt/c/bar/something", "/other", false, pass, "wsl"}, + {`c:/foo:ro`, "c", "/foo", true, pass, ""}, + {`\\computer\loc:/dest`, "", "", false, fail, "wsl"}, + {`\\.\drive\loc:/target`, "/mnt/wsl/drive/loc", "/target", false, pass, "wsl"}, + } + + f := func(vol string, mach string) (*specgen.SpecGenerator, error) { + machine := machine.GetMachineMarker() + oldEnable, oldType := machine.Enabled, machine.Type + machine.Enabled, machine.Type = len(mach) > 0, mach + sg := specgen.NewSpecGenerator("nothing", false) + err := FillOutSpecGen(sg, &entities.ContainerCreateOptions{ + ImageVolume: "ignore", + Volume: []string{vol}}, []string{}, + ) + machine.Enabled, machine.Type = oldEnable, oldType + return sg, err + } + + for _, test := range tests { + msg := "Checking: " + test.vol + sg, err := f(test.vol, test.mach) + if test.outcome == fail { + assert.NotNil(t, err, msg) + continue + } + if !assert.Nil(t, err, msg) { + continue + } + if test.isN { + if !assert.Equal(t, 1, len(sg.Volumes), msg) { + continue + } + assert.Equal(t, test.source, sg.Volumes[0].Name, msg) + assert.Equal(t, test.dest, sg.Volumes[0].Dest, msg) + } else { + if !assert.Equal(t, 1, len(sg.Mounts), msg) { + continue + } + assert.Equal(t, test.source, sg.Mounts[0].Source, msg) + assert.Equal(t, test.dest, sg.Mounts[0].Destination, msg) + } + } +} diff --git a/pkg/specgenutil/volumes.go b/pkg/specgenutil/volumes.go index 95ce420f8..50d745380 100644 --- a/pkg/specgenutil/volumes.go +++ b/pkg/specgenutil/volumes.go @@ -3,7 +3,7 @@ package specgenutil import ( "encoding/csv" "fmt" - "path/filepath" + "path" "strings" "github.com/containers/common/pkg/parse" @@ -123,7 +123,7 @@ func parseVolumes(volumeFlag, mountFlag, tmpfsFlag []string, addReadOnlyTmpfs bo finalMounts := make([]spec.Mount, 0, len(unifiedMounts)) for _, mount := range unifiedMounts { if mount.Type == define.TypeBind { - absSrc, err := filepath.Abs(mount.Source) + absSrc, err := specgen.ConvertWinMountPath(mount.Source) if err != nil { return nil, nil, nil, nil, errors.Wrapf(err, "error getting absolute path of %s", mount.Source) } @@ -334,7 +334,7 @@ func getBindMount(args []string) (spec.Mount, error) { if err := parse.ValidateVolumeCtrDir(kv[1]); err != nil { return newMount, err } - newMount.Destination = filepath.Clean(kv[1]) + newMount.Destination = unixPathClean(kv[1]) setDest = true case "relabel": if setRelabel { @@ -456,7 +456,7 @@ func getTmpfsMount(args []string) (spec.Mount, error) { if err := parse.ValidateVolumeCtrDir(kv[1]); err != nil { return newMount, err } - newMount.Destination = filepath.Clean(kv[1]) + newMount.Destination = unixPathClean(kv[1]) setDest = true case "U", "chown": if setOwnership { @@ -507,7 +507,7 @@ func getDevptsMount(args []string) (spec.Mount, error) { if err := parse.ValidateVolumeCtrDir(kv[1]); err != nil { return newMount, err } - newMount.Destination = filepath.Clean(kv[1]) + newMount.Destination = unixPathClean(kv[1]) setDest = true default: return newMount, errors.Wrapf(util.ErrBadMntOption, "%s", kv[0]) @@ -572,7 +572,7 @@ func getNamedVolume(args []string) (*specgen.NamedVolume, error) { if err := parse.ValidateVolumeCtrDir(kv[1]); err != nil { return nil, err } - newVolume.Dest = filepath.Clean(kv[1]) + newVolume.Dest = unixPathClean(kv[1]) setDest = true case "U", "chown": if setOwnership { @@ -624,7 +624,7 @@ func getImageVolume(args []string) (*specgen.ImageVolume, error) { if err := parse.ValidateVolumeCtrDir(kv[1]); err != nil { return nil, err } - newVolume.Destination = filepath.Clean(kv[1]) + newVolume.Destination = unixPathClean(kv[1]) case "rw", "readwrite": switch kv[1] { case "true": @@ -670,7 +670,7 @@ func getTmpfsMounts(tmpfsFlag []string) (map[string]spec.Mount, error) { } mount := spec.Mount{ - Destination: filepath.Clean(destPath), + Destination: unixPathClean(destPath), Type: define.TypeTmpfs, Options: options, Source: define.TypeTmpfs, @@ -700,3 +700,8 @@ func validChownFlag(flag string) (bool, error) { return true, nil } + +// Use path instead of filepath to preserve Unix style paths on Windows +func unixPathClean(p string) string { + return path.Clean(p) +} |