diff options
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/namespaces/namespaces.go | 87 | ||||
-rw-r--r-- | pkg/spec/spec.go | 37 | ||||
-rw-r--r-- | pkg/spec/storage.go | 31 |
3 files changed, 105 insertions, 50 deletions
diff --git a/pkg/namespaces/namespaces.go b/pkg/namespaces/namespaces.go index 35298796f..9d1033b93 100644 --- a/pkg/namespaces/namespaces.go +++ b/pkg/namespaces/namespaces.go @@ -4,17 +4,30 @@ import ( "strings" ) +const ( + bridgeType = "bridge" + containerType = "container" + defaultType = "default" + hostType = "host" + noneType = "none" + nsType = "ns" + podType = "pod" + privateType = "private" + shareableType = "shareable" + slirpType = "slirp4netns" +) + // CgroupMode represents cgroup mode in the container. type CgroupMode string // IsHost indicates whether the container uses the host's cgroup. func (n CgroupMode) IsHost() bool { - return n == "host" + return n == hostType } // IsNS indicates a cgroup namespace passed in by path (ns:<path>) func (n CgroupMode) IsNS() bool { - return strings.HasPrefix(string(n), "ns:") + return strings.HasPrefix(string(n), nsType) } // NS gets the path associated with a ns:<path> cgroup ns @@ -29,13 +42,13 @@ func (n CgroupMode) NS() string { // IsContainer indicates whether the container uses a new cgroup namespace. func (n CgroupMode) IsContainer() bool { parts := strings.SplitN(string(n), ":", 2) - return len(parts) > 1 && parts[0] == "container" + return len(parts) > 1 && parts[0] == containerType } // Container returns the name of the container whose cgroup namespace is going to be used. func (n CgroupMode) Container() string { parts := strings.SplitN(string(n), ":", 2) - if len(parts) > 1 { + if len(parts) > 1 && parts[0] == containerType { return parts[1] } return "" @@ -43,15 +56,15 @@ func (n CgroupMode) Container() string { // IsPrivate indicates whether the container uses the a private cgroup. func (n CgroupMode) IsPrivate() bool { - return n == "private" + return n == privateType } // Valid indicates whether the Cgroup namespace is valid. func (n CgroupMode) Valid() bool { parts := strings.Split(string(n), ":") switch mode := parts[0]; mode { - case "", "host", "private", "ns": - case "container": + case "", hostType, privateType, nsType: + case containerType: if len(parts) != 2 || parts[1] == "" { return false } @@ -66,7 +79,7 @@ type UsernsMode string // IsHost indicates whether the container uses the host's userns. func (n UsernsMode) IsHost() bool { - return n == "host" + return n == hostType } // IsKeepID indicates whether container uses a mapping where the (uid, gid) on the host is lept inside of the namespace. @@ -83,8 +96,8 @@ func (n UsernsMode) IsPrivate() bool { func (n UsernsMode) Valid() bool { parts := strings.Split(string(n), ":") switch mode := parts[0]; mode { - case "", "host", "keep-id", "ns": - case "container": + case "", hostType, "keep-id", nsType: + case containerType: if len(parts) != 2 || parts[1] == "" { return false } @@ -111,13 +124,13 @@ func (n UsernsMode) NS() string { // IsContainer indicates whether container uses a container userns. func (n UsernsMode) IsContainer() bool { parts := strings.SplitN(string(n), ":", 2) - return len(parts) > 1 && parts[0] == "container" + return len(parts) > 1 && parts[0] == containerType } // Container is the id of the container which network this container is connected to. func (n UsernsMode) Container() string { parts := strings.SplitN(string(n), ":", 2) - if len(parts) > 1 { + if len(parts) > 1 && parts[0] == containerType { return parts[1] } return "" @@ -133,19 +146,19 @@ func (n UTSMode) IsPrivate() bool { // IsHost indicates whether the container uses the host's UTS namespace. func (n UTSMode) IsHost() bool { - return n == "host" + return n == hostType } // IsContainer indicates whether the container uses a container's UTS namespace. func (n UTSMode) IsContainer() bool { parts := strings.SplitN(string(n), ":", 2) - return len(parts) > 1 && parts[0] == "container" + return len(parts) > 1 && parts[0] == containerType } // Container returns the name of the container whose uts namespace is going to be used. func (n UTSMode) Container() string { parts := strings.SplitN(string(n), ":", 2) - if len(parts) > 1 { + if len(parts) > 1 && parts[0] == containerType { return parts[1] } return "" @@ -155,8 +168,8 @@ func (n UTSMode) Container() string { func (n UTSMode) Valid() bool { parts := strings.Split(string(n), ":") switch mode := parts[0]; mode { - case "", "host": - case "container": + case "", hostType: + case containerType: if len(parts) != 2 || parts[1] == "" { return false } @@ -171,28 +184,28 @@ type IpcMode string // IsPrivate indicates whether the container uses its own private ipc namespace which cannot be shared. func (n IpcMode) IsPrivate() bool { - return n == "private" + return n == privateType } // IsHost indicates whether the container shares the host's ipc namespace. func (n IpcMode) IsHost() bool { - return n == "host" + return n == hostType } // IsShareable indicates whether the container's ipc namespace can be shared with another container. func (n IpcMode) IsShareable() bool { - return n == "shareable" + return n == shareableType } // IsContainer indicates whether the container uses another container's ipc namespace. func (n IpcMode) IsContainer() bool { parts := strings.SplitN(string(n), ":", 2) - return len(parts) > 1 && parts[0] == "container" + return len(parts) > 1 && parts[0] == containerType } // IsNone indicates whether container IpcMode is set to "none". func (n IpcMode) IsNone() bool { - return n == "none" + return n == noneType } // IsEmpty indicates whether container IpcMode is empty @@ -208,7 +221,7 @@ func (n IpcMode) Valid() bool { // Container returns the name of the container ipc stack is going to be used. func (n IpcMode) Container() string { parts := strings.SplitN(string(n), ":", 2) - if len(parts) > 1 && parts[0] == "container" { + if len(parts) > 1 && parts[0] == containerType { return parts[1] } return "" @@ -224,21 +237,21 @@ func (n PidMode) IsPrivate() bool { // IsHost indicates whether the container uses the host's pid namespace. func (n PidMode) IsHost() bool { - return n == "host" + return n == hostType } // IsContainer indicates whether the container uses a container's pid namespace. func (n PidMode) IsContainer() bool { parts := strings.SplitN(string(n), ":", 2) - return len(parts) > 1 && parts[0] == "container" + return len(parts) > 1 && parts[0] == containerType } // Valid indicates whether the pid namespace is valid. func (n PidMode) Valid() bool { parts := strings.Split(string(n), ":") switch mode := parts[0]; mode { - case "", "host": - case "container": + case "", hostType: + case containerType: if len(parts) != 2 || parts[1] == "" { return false } @@ -251,7 +264,7 @@ func (n PidMode) Valid() bool { // Container returns the name of the container whose pid namespace is going to be used. func (n PidMode) Container() string { parts := strings.SplitN(string(n), ":", 2) - if len(parts) > 1 { + if len(parts) > 1 && parts[0] == containerType { return parts[1] } return "" @@ -262,17 +275,17 @@ type NetworkMode string // IsNone indicates whether container isn't using a network stack. func (n NetworkMode) IsNone() bool { - return n == "none" + return n == noneType } // IsHost indicates whether the container uses the host's network stack. func (n NetworkMode) IsHost() bool { - return n == "host" + return n == hostType } // IsDefault indicates whether container uses the default network stack. func (n NetworkMode) IsDefault() bool { - return n == "default" + return n == defaultType } // IsPrivate indicates whether container uses its private network stack. @@ -283,13 +296,13 @@ func (n NetworkMode) IsPrivate() bool { // IsContainer indicates whether container uses a container network stack. func (n NetworkMode) IsContainer() bool { parts := strings.SplitN(string(n), ":", 2) - return len(parts) > 1 && parts[0] == "container" + return len(parts) > 1 && parts[0] == containerType } // Container is the id of the container which network this container is connected to. func (n NetworkMode) Container() string { parts := strings.SplitN(string(n), ":", 2) - if len(parts) > 1 { + if len(parts) > 1 && parts[0] == containerType { return parts[1] } return "" @@ -305,17 +318,17 @@ func (n NetworkMode) UserDefined() string { // IsBridge indicates whether container uses the bridge network stack func (n NetworkMode) IsBridge() bool { - return n == "bridge" + return n == bridgeType } // IsSlirp4netns indicates if we are running a rootless network stack func (n NetworkMode) IsSlirp4netns() bool { - return n == "slirp4netns" + return n == slirpType } // IsNS indicates a network namespace passed in by path (ns:<path>) func (n NetworkMode) IsNS() bool { - return strings.HasPrefix(string(n), "ns:") + return strings.HasPrefix(string(n), nsType) } // NS gets the path associated with a ns:<path> network ns @@ -329,7 +342,7 @@ func (n NetworkMode) NS() string { // IsPod returns whether the network refers to pod networking func (n NetworkMode) IsPod() bool { - return n == "pod" + return n == podType } // IsUserDefined indicates user-created network diff --git a/pkg/spec/spec.go b/pkg/spec/spec.go index c94746767..156d6849d 100644 --- a/pkg/spec/spec.go +++ b/pkg/spec/spec.go @@ -174,10 +174,20 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM } hostname := config.Hostname - if hostname == "" && (config.NetMode.IsHost() || config.UtsMode.IsHost()) { - hostname, err = os.Hostname() - if err != nil { - return nil, errors.Wrap(err, "unable to retrieve hostname") + if hostname == "" { + if utsCtrID := config.UtsMode.Container(); utsCtrID != "" { + utsCtr, err := runtime.GetContainer(utsCtrID) + if err != nil { + return nil, errors.Wrapf(err, "unable to retrieve hostname from dependency container %s", utsCtrID) + } + hostname = utsCtr.Hostname() + } else if config.NetMode.IsHost() || config.UtsMode.IsHost() { + hostname, err = os.Hostname() + if err != nil { + return nil, errors.Wrap(err, "unable to retrieve hostname of the host") + } + } else { + logrus.Debug("No hostname set; container's hostname will default to runtime default") } } g.RemoveHostname() @@ -541,8 +551,8 @@ func addPidNS(config *CreateConfig, g *generate.Generator) error { if pidMode.IsHost() { return g.RemoveLinuxNamespace(string(spec.PIDNamespace)) } - if pidMode.IsContainer() { - logrus.Debug("using container pidmode") + if pidCtr := pidMode.Container(); pidCtr != "" { + logrus.Debugf("using container %s pidmode", pidCtr) } if IsPod(string(pidMode)) { logrus.Debug("using pod pidmode") @@ -579,8 +589,8 @@ func addNetNS(config *CreateConfig, g *generate.Generator) error { } else if netMode.IsBridge() { logrus.Debug("Using bridge netmode") return nil - } else if netMode.IsContainer() { - logrus.Debug("Using container netmode") + } else if netCtr := netMode.Container(); netCtr != "" { + logrus.Debugf("using container %s netmode", netCtr) return nil } else if IsNS(string(netMode)) { logrus.Debug("Using ns netmode") @@ -606,6 +616,9 @@ func addUTSNS(config *CreateConfig, g *generate.Generator) error { if utsMode.IsHost() { return g.RemoveLinuxNamespace(string(spec.UTSNamespace)) } + if utsCtr := utsMode.Container(); utsCtr != "" { + logrus.Debugf("using container %s utsmode", utsCtr) + } return nil } @@ -617,8 +630,8 @@ func addIpcNS(config *CreateConfig, g *generate.Generator) error { if ipcMode.IsHost() { return g.RemoveLinuxNamespace(string(spec.IPCNamespace)) } - if ipcMode.IsContainer() { - logrus.Debug("Using container ipcmode") + if ipcCtr := ipcMode.Container(); ipcCtr != "" { + logrus.Debugf("Using container %s ipcmode", ipcCtr) } return nil @@ -635,8 +648,8 @@ func addCgroupNS(config *CreateConfig, g *generate.Generator) error { if cgroupMode.IsPrivate() { return g.AddOrReplaceLinuxNamespace(string(spec.CgroupNamespace), "") } - if cgroupMode.IsContainer() { - logrus.Debug("Using container cgroup mode") + if cgCtr := cgroupMode.Container(); cgCtr != "" { + logrus.Debugf("Using container %s cgroup mode", cgCtr) } return nil } diff --git a/pkg/spec/storage.go b/pkg/spec/storage.go index ac7a2c30f..e0bb48a9c 100644 --- a/pkg/spec/storage.go +++ b/pkg/spec/storage.go @@ -410,13 +410,42 @@ func getBindMount(args []string) (spec.Mount, error) { setSource := false setDest := false + setRORW := false for _, val := range args { kv := strings.Split(val, "=") switch kv[0] { case "bind-nonrecursive": newMount.Options = append(newMount.Options, "bind") - case "ro", "nosuid", "nodev", "noexec": + case "ro", "rw": + if setRORW { + return newMount, errors.Wrapf(optionArgError, "cannot pass 'ro' or 'rw' options more than once") + } + setRORW = true + // Can be formatted as one of: + // ro + // ro=[true|false] + // rw + // rw=[true|false] + if len(kv) == 1 { + newMount.Options = append(newMount.Options, kv[0]) + } else if len(kv) == 2 { + switch strings.ToLower(kv[1]) { + case "true": + newMount.Options = append(newMount.Options, kv[0]) + case "false": + // Set the opposite only for rw + // ro's opposite is the default + if kv[0] == "rw" { + newMount.Options = append(newMount.Options, "ro") + } + default: + return newMount, errors.Wrapf(optionArgError, "%s must be set to true or false, instead received %q", kv[0], kv[1]) + } + } else { + return newMount, errors.Wrapf(optionArgError, "badly formatted option %q", val) + } + case "nosuid", "nodev", "noexec": // TODO: detect duplication of these options. // (Is this necessary?) newMount.Options = append(newMount.Options, kv[0]) |