From ef026e83fa2ce9a13d397f3465a347e76c591eb4 Mon Sep 17 00:00:00 2001 From: Evan Hazlett Date: Mon, 22 May 2017 12:47:31 -0400 Subject: [PATCH] add --mount option to ctr Signed-off-by: Evan Hazlett --- cmd/ctr/run.go | 4 ++++ cmd/ctr/run_unix.go | 8 ++++++++ cmd/ctr/utils.go | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+) diff --git a/cmd/ctr/run.go b/cmd/ctr/run.go index 53bf6054a..ff274f797 100644 --- a/cmd/ctr/run.go +++ b/cmd/ctr/run.go @@ -54,6 +54,10 @@ var runCommand = cli.Command{ Name: "net-host", Usage: "enable host networking for the container", }, + cli.StringSliceFlag{ + Name: "mount", + Usage: "specify additional container mount (ex: type=bind,src=/tmp,dest=/host,options=rbind:ro)", + }, cli.BoolFlag{ Name: "keep", Usage: "keep container after running", diff --git a/cmd/ctr/run_unix.go b/cmd/ctr/run_unix.go index a26eb73be..e771ff9b9 100644 --- a/cmd/ctr/run_unix.go +++ b/cmd/ctr/run_unix.go @@ -222,6 +222,14 @@ func spec(id string, config *ocispec.ImageConfig, context *cli.Context, rootfs s Type: "network", }) } + for _, mount := range context.StringSlice("mount") { + m, err := parseMountFlag(mount) + if err != nil { + return nil, err + } + + s.Mounts = append(s.Mounts, m) + } return s, nil } diff --git a/cmd/ctr/utils.go b/cmd/ctr/utils.go index 2f88940bf..ebf135f79 100644 --- a/cmd/ctr/utils.go +++ b/cmd/ctr/utils.go @@ -2,6 +2,7 @@ package main import ( gocontext "context" + "encoding/csv" "fmt" "io/ioutil" "os" @@ -26,6 +27,7 @@ import ( imagesservice "github.com/containerd/containerd/services/images" snapshotservice "github.com/containerd/containerd/services/snapshot" "github.com/containerd/containerd/snapshot" + specs "github.com/opencontainers/runtime-spec/specs-go" "github.com/urfave/cli" "google.golang.org/grpc" ) @@ -152,3 +154,38 @@ func stopCatch(sigc chan os.Signal) { signal.Stop(sigc) close(sigc) } + +// parseMountFlag parses a mount string in the form "type=foo,source=/path,destination=/target,options=rbind:rw" +func parseMountFlag(m string) (specs.Mount, error) { + mount := specs.Mount{} + r := csv.NewReader(strings.NewReader(m)) + + fields, err := r.Read() + if err != nil { + return mount, err + } + + for _, field := range fields { + v := strings.Split(field, "=") + if len(v) != 2 { + return mount, fmt.Errorf("invalid mount specification: expected key=val") + } + + key := v[0] + val := v[1] + switch key { + case "type": + mount.Type = val + case "source", "src": + mount.Source = val + case "destination", "dst": + mount.Destination = val + case "options": + mount.Options = strings.Split(val, ":") + default: + return mount, fmt.Errorf("mount option %q not supported", key) + } + } + + return mount, nil +}