summaryrefslogtreecommitdiff
path: root/cmd
diff options
context:
space:
mode:
authorDaniel J Walsh <dwalsh@redhat.com>2018-09-21 06:29:18 -0400
committerAtomic Bot <atomic-devel@projectatomic.io>2018-09-21 21:33:41 +0000
commit52c1365f32398b8ba0321c159e739a5416cd9ab2 (patch)
tree8a700c6cc35d1955e973d18b3ed537c380290334 /cmd
parent9e81f9daa4af9802088530a35a72814172430a36 (diff)
downloadpodman-52c1365f32398b8ba0321c159e739a5416cd9ab2.tar.gz
podman-52c1365f32398b8ba0321c159e739a5416cd9ab2.tar.bz2
podman-52c1365f32398b8ba0321c159e739a5416cd9ab2.zip
Add --mount option for `create` & `run` command
Signed-off-by: Kunal Kushwaha <kushwaha_kunal_v7@lab.ntt.co.jp> Signed-off-by: Daniel J Walsh <dwalsh@redhat.com> Closes: #1524 Approved by: mheon
Diffstat (limited to 'cmd')
-rw-r--r--cmd/podman/common.go4
-rw-r--r--cmd/podman/create.go6
-rw-r--r--cmd/podman/create_cli.go90
3 files changed, 100 insertions, 0 deletions
diff --git a/cmd/podman/common.go b/cmd/podman/common.go
index 8d20081f6..9ab0e57e5 100644
--- a/cmd/podman/common.go
+++ b/cmd/podman/common.go
@@ -418,6 +418,10 @@ var createFlags = []cli.Flag{
Usage: "UTS namespace to use",
},
cli.StringSliceFlag{
+ Name: "mount",
+ Usage: "Attach a filesystem mount to the container (default [])",
+ },
+ cli.StringSliceFlag{
Name: "volume, v",
Usage: "Bind mount a volume into the container (default [])",
},
diff --git a/cmd/podman/create.go b/cmd/podman/create.go
index ff912560b..fc0c71536 100644
--- a/cmd/podman/create.go
+++ b/cmd/podman/create.go
@@ -24,6 +24,7 @@ import (
"github.com/docker/docker/pkg/signal"
"github.com/docker/go-connections/nat"
"github.com/docker/go-units"
+ spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/selinux/go-selinux/label"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
@@ -459,6 +460,10 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim
}
blkioWeight = uint16(u)
}
+ var mountList []spec.Mount
+ if mountList, err = parseMounts(c.StringSlice("mount")); err != nil {
+ return nil, err
+ }
if err = parseVolumes(c.StringSlice("volume")); err != nil {
return nil, err
@@ -772,6 +777,7 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim
Tty: tty,
User: user,
UsernsMode: usernsMode,
+ Mounts: mountList,
Volumes: c.StringSlice("volume"),
WorkDir: workDir,
Rootfs: rootfs,
diff --git a/cmd/podman/create_cli.go b/cmd/podman/create_cli.go
index 812b62058..218e9b806 100644
--- a/cmd/podman/create_cli.go
+++ b/cmd/podman/create_cli.go
@@ -8,6 +8,8 @@ import (
cc "github.com/containers/libpod/pkg/spec"
"github.com/docker/docker/pkg/sysinfo"
+ "github.com/docker/go-units"
+ spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
@@ -74,6 +76,94 @@ func addWarning(warnings []string, msg string) []string {
return append(warnings, msg)
}
+// Format supported.
+// podman run --mount type=bind,src=/etc/resolv.conf,target=/etc/resolv.conf ...
+// podman run --mount type=tmpfs,target=/dev/shm ..
+func parseMounts(mounts []string) ([]spec.Mount, error) {
+ var mountList []spec.Mount
+ errInvalidSyntax := errors.Errorf("incorrect mount format : should be --mount type=<bind|tmpfs>,[src=<host-dir>,]target=<ctr-dir>,[options]")
+ for _, mount := range mounts {
+ var tokenCount int
+ var mountInfo spec.Mount
+
+ arr := strings.SplitN(mount, ",", 2)
+ if len(arr) < 2 {
+ return nil, errInvalidSyntax
+ }
+ kv := strings.Split(arr[0], "=")
+ if kv[0] != "type" {
+ return nil, errInvalidSyntax
+ }
+ switch kv[1] {
+ case "bind":
+ mountInfo.Type = string(cc.TypeBind)
+ case "tmpfs":
+ mountInfo.Type = string(cc.TypeTmpfs)
+ mountInfo.Source = string(cc.TypeTmpfs)
+ mountInfo.Options = append(mountInfo.Options, []string{"rprivate", "noexec", "nosuid", "nodev", "size=65536k"}...)
+
+ default:
+ return nil, errors.Errorf("invalid filesystem type %q", kv[1])
+ }
+
+ tokens := strings.Split(arr[1], ",")
+ for i, val := range tokens {
+ if i == (tokenCount - 1) {
+ //Parse tokens before options.
+ break
+ }
+ kv := strings.Split(val, "=")
+ switch kv[0] {
+ case "ro", "nosuid", "nodev", "noexec":
+ mountInfo.Options = append(mountInfo.Options, kv[0])
+ case "shared", "rshared", "private", "rprivate", "slave", "rslave", "Z", "z":
+ if mountInfo.Type != "bind" {
+ return nil, errors.Errorf("%s can only be used with bind mounts", kv[0])
+ }
+ mountInfo.Options = append(mountInfo.Options, kv[0])
+ case "tmpfs-mode":
+ if mountInfo.Type != "tmpfs" {
+ return nil, errors.Errorf("%s can only be used with tmpfs mounts", kv[0])
+ }
+ mountInfo.Options = append(mountInfo.Options, fmt.Sprintf("mode=%s", kv[1]))
+ case "tmpfs-size":
+ if mountInfo.Type != "tmpfs" {
+ return nil, errors.Errorf("%s can only be used with tmpfs mounts", kv[0])
+ }
+ shmSize, err := units.FromHumanSize(kv[1])
+ if err != nil {
+ return nil, errors.Wrapf(err, "unable to translate tmpfs-size")
+ }
+
+ mountInfo.Options = append(mountInfo.Options, fmt.Sprintf("size=%d", shmSize))
+
+ case "bind-propagation":
+ if mountInfo.Type != "bind" {
+ return nil, errors.Errorf("%s can only be used with bind mounts", kv[0])
+ }
+ mountInfo.Options = append(mountInfo.Options, kv[1])
+ case "src", "source":
+ if mountInfo.Type == "tmpfs" {
+ return nil, errors.Errorf("can not use src= on a tmpfs file system")
+ }
+ if err := validateVolumeHostDir(kv[1]); err != nil {
+ return nil, err
+ }
+ mountInfo.Source = kv[1]
+ case "target", "dst", "destination":
+ if err := validateVolumeCtrDir(kv[1]); err != nil {
+ return nil, err
+ }
+ mountInfo.Destination = kv[1]
+ default:
+ return nil, errors.Errorf("incorrect mount option : %s", kv[0])
+ }
+ }
+ mountList = append(mountList, mountInfo)
+ }
+ return mountList, nil
+}
+
func parseVolumes(volumes []string) error {
for _, volume := range volumes {
arr := strings.SplitN(volume, ":", 3)