From 52c1365f32398b8ba0321c159e739a5416cd9ab2 Mon Sep 17 00:00:00 2001 From: Daniel J Walsh Date: Fri, 21 Sep 2018 06:29:18 -0400 Subject: Add --mount option for `create` & `run` command Signed-off-by: Kunal Kushwaha Signed-off-by: Daniel J Walsh Closes: #1524 Approved by: mheon --- pkg/spec/createconfig.go | 76 ++++++++++++++++++++++++++---------------------- pkg/spec/spec.go | 64 +++++++++++++++++++++++----------------- 2 files changed, 79 insertions(+), 61 deletions(-) (limited to 'pkg') diff --git a/pkg/spec/createconfig.go b/pkg/spec/createconfig.go index a9c7d2967..887ef8e95 100644 --- a/pkg/spec/createconfig.go +++ b/pkg/spec/createconfig.go @@ -122,6 +122,7 @@ type CreateConfig struct { UsernsMode namespaces.UsernsMode //userns User string //user UtsMode namespaces.UTSMode //uts + Mounts []spec.Mount //mounts Volumes []string //volume VolumesFrom []string WorkDir string //workdir @@ -142,54 +143,59 @@ func (c *CreateConfig) CreateBlockIO() (*spec.LinuxBlockIO, error) { return c.createBlockIO() } +func processOptions(options []string) []string { + var ( + foundrw, foundro bool + rootProp string + ) + options = append(options, "rbind") + for _, opt := range options { + switch opt { + case "rw": + foundrw = true + case "ro": + foundro = true + case "private", "rprivate", "slave", "rslave", "shared", "rshared": + rootProp = opt + } + } + if !foundrw && !foundro { + options = append(options, "rw") + } + if rootProp == "" { + options = append(options, "rprivate") + } + return options +} + +func (c *CreateConfig) initFSMounts() []spec.Mount { + var mounts []spec.Mount + for _, m := range c.Mounts { + m.Options = processOptions(m.Options) + if m.Type == "tmpfs" { + m.Options = append(m.Options, "tmpcopyup") + } else { + mounts = append(mounts, m) + } + } + return mounts +} + //GetVolumeMounts takes user provided input for bind mounts and creates Mount structs func (c *CreateConfig) GetVolumeMounts(specMounts []spec.Mount) ([]spec.Mount, error) { var m []spec.Mount for _, i := range c.Volumes { - var ( - options []string - foundrw, foundro, foundz, foundZ bool - rootProp string - ) - - // We need to handle SELinux options better here, specifically :Z + var options []string spliti := strings.Split(i, ":") if len(spliti) > 2 { options = strings.Split(spliti[2], ",") } - options = append(options, "rbind") - for _, opt := range options { - switch opt { - case "rw": - foundrw = true - case "ro": - foundro = true - case "z": - foundz = true - case "Z": - foundZ = true - case "private", "rprivate", "slave", "rslave", "shared", "rshared": - rootProp = opt - } - } - if !foundrw && !foundro { - options = append(options, "rw") - } - if foundz { - options = append(options, "z") - } - if foundZ { - options = append(options, "Z") - } - if rootProp == "" { - options = append(options, "rprivate") - } m = append(m, spec.Mount{ Destination: spliti[1], Type: string(TypeBind), Source: spliti[0], - Options: options, + Options: processOptions(options), }) logrus.Debugf("User mount %s:%s options %v", spliti[0], spliti[1], options) diff --git a/pkg/spec/spec.go b/pkg/spec/spec.go index e115bba7f..ad14ea65d 100644 --- a/pkg/spec/spec.go +++ b/pkg/spec/spec.go @@ -18,6 +18,34 @@ import ( const cpuPeriod = 100000 +func supercedeUserMounts(mounts []spec.Mount, configMount []spec.Mount) []spec.Mount { + if len(mounts) > 0 { + // If we have overlappings mounts, remove them from the spec in favor of + // the user-added volume mounts + destinations := make(map[string]bool) + for _, mount := range mounts { + destinations[path.Clean(mount.Destination)] = true + } + // Copy all mounts from spec to defaultMounts, except for + // - mounts overridden by a user supplied mount; + // - all mounts under /dev if a user supplied /dev is present; + mountDev := destinations["/dev"] + for _, mount := range configMount { + if _, ok := destinations[path.Clean(mount.Destination)]; !ok { + if mountDev && strings.HasPrefix(mount.Destination, "/dev/") { + // filter out everything under /dev if /dev is user-mounted + continue + } + + logrus.Debugf("Adding mount %s", mount.Destination) + mounts = append(mounts, mount) + } + } + return mounts + } + return configMount +} + // CreateConfigToOCISpec parses information needed to create a container into an OCI runtime spec func CreateConfigToOCISpec(config *CreateConfig) (*spec.Spec, error) { //nolint cgroupPerm := "ro" @@ -246,6 +274,12 @@ func CreateConfigToOCISpec(config *CreateConfig) (*spec.Spec, error) { //nolint g.AddMount(tmpfsMnt) } + for _, m := range config.Mounts { + if m.Type == "tmpfs" { + g.AddMount(m) + } + } + for name, val := range config.Env { g.AddProcessEnv(name, val) } @@ -305,36 +339,14 @@ func CreateConfigToOCISpec(config *CreateConfig) (*spec.Spec, error) { //nolint return nil, errors.Wrap(err, "error getting volume mounts from --volumes-from flag") } - mounts, err := config.GetVolumeMounts(configSpec.Mounts) + volumeMounts, err := config.GetVolumeMounts(configSpec.Mounts) if err != nil { return nil, errors.Wrapf(err, "error getting volume mounts") } - if len(mounts) > 0 { - // If we have overlappings mounts, remove them from the spec in favor of - // the user-added volume mounts - destinations := make(map[string]bool) - for _, mount := range mounts { - destinations[path.Clean(mount.Destination)] = true - } - - // Copy all mounts from spec to defaultMounts, except for - // - mounts overridden by a user supplied mount; - // - all mounts under /dev if a user supplied /dev is present; - mountDev := destinations["/dev"] - for _, mount := range configSpec.Mounts { - if _, ok := destinations[path.Clean(mount.Destination)]; !ok { - if mountDev && strings.HasPrefix(mount.Destination, "/dev/") { - // filter out everything under /dev if /dev is user-mounted - continue - } - - logrus.Debugf("Adding mount %s", mount.Destination) - mounts = append(mounts, mount) - } - } - configSpec.Mounts = mounts - } + configSpec.Mounts = supercedeUserMounts(volumeMounts, configSpec.Mounts) + //--mount + configSpec.Mounts = supercedeUserMounts(config.initFSMounts(), configSpec.Mounts) if canAddResources { // BLOCK IO blkio, err := config.CreateBlockIO() -- cgit v1.2.3-54-g00ecf