mirror of
https://github.com/containers/podman.git
synced 2025-10-19 20:23:08 +08:00
podman: handle namespaces specified on the CLI
and handle differently the user namespace as it supports additional options. Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
This commit is contained in:
@ -49,8 +49,9 @@ func GetCreateFlags(cf *ContainerCLIOpts) *pflag.FlagSet {
|
|||||||
"cap-drop", []string{},
|
"cap-drop", []string{},
|
||||||
"Drop capabilities from the container",
|
"Drop capabilities from the container",
|
||||||
)
|
)
|
||||||
|
cgroupNS := ""
|
||||||
createFlags.StringVar(
|
createFlags.StringVar(
|
||||||
&cf.CGroupsNS,
|
&cgroupNS,
|
||||||
"cgroupns", containerConfig.CgroupNS(),
|
"cgroupns", containerConfig.CgroupNS(),
|
||||||
"cgroup namespace to use",
|
"cgroup namespace to use",
|
||||||
)
|
)
|
||||||
@ -247,8 +248,9 @@ func GetCreateFlags(cf *ContainerCLIOpts) *pflag.FlagSet {
|
|||||||
"interactive", "i", false,
|
"interactive", "i", false,
|
||||||
"Keep STDIN open even if not attached",
|
"Keep STDIN open even if not attached",
|
||||||
)
|
)
|
||||||
|
ipcNS := ""
|
||||||
createFlags.StringVar(
|
createFlags.StringVar(
|
||||||
&cf.IPC,
|
&ipcNS,
|
||||||
"ipc", containerConfig.IPCNS(),
|
"ipc", containerConfig.IPCNS(),
|
||||||
"IPC namespace to use",
|
"IPC namespace to use",
|
||||||
)
|
)
|
||||||
@ -329,8 +331,9 @@ func GetCreateFlags(cf *ContainerCLIOpts) *pflag.FlagSet {
|
|||||||
"use `OS` instead of the running OS for choosing images",
|
"use `OS` instead of the running OS for choosing images",
|
||||||
)
|
)
|
||||||
// markFlagHidden(createFlags, "override-os")
|
// markFlagHidden(createFlags, "override-os")
|
||||||
|
pid := ""
|
||||||
createFlags.StringVar(
|
createFlags.StringVar(
|
||||||
&cf.PID,
|
&pid,
|
||||||
"pid", containerConfig.PidNS(),
|
"pid", containerConfig.PidNS(),
|
||||||
"PID namespace to use",
|
"PID namespace to use",
|
||||||
)
|
)
|
||||||
@ -461,13 +464,15 @@ func GetCreateFlags(cf *ContainerCLIOpts) *pflag.FlagSet {
|
|||||||
"user", "u", "",
|
"user", "u", "",
|
||||||
"Username or UID (format: <name|uid>[:<group|gid>])",
|
"Username or UID (format: <name|uid>[:<group|gid>])",
|
||||||
)
|
)
|
||||||
|
userNS := ""
|
||||||
createFlags.StringVar(
|
createFlags.StringVar(
|
||||||
&cf.UserNS,
|
&userNS,
|
||||||
"userns", containerConfig.Containers.UserNS,
|
"userns", containerConfig.Containers.UserNS,
|
||||||
"User namespace to use",
|
"User namespace to use",
|
||||||
)
|
)
|
||||||
|
utsNS := ""
|
||||||
createFlags.StringVar(
|
createFlags.StringVar(
|
||||||
&cf.UTS,
|
&utsNS,
|
||||||
"uts", containerConfig.Containers.UTSNS,
|
"uts", containerConfig.Containers.UTSNS,
|
||||||
"UTS namespace to use",
|
"UTS namespace to use",
|
||||||
)
|
)
|
||||||
|
@ -222,55 +222,28 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string
|
|||||||
s.PortMappings = ep
|
s.PortMappings = ep
|
||||||
s.Pod = c.Pod
|
s.Pod = c.Pod
|
||||||
|
|
||||||
//s.CgroupNS = specgen.Namespace{
|
for k, v := range map[string]*specgen.Namespace{
|
||||||
// NSMode: ,
|
c.IPC: &s.IpcNS,
|
||||||
// Value: "",
|
c.PID: &s.PidNS,
|
||||||
//}
|
c.UTS: &s.UtsNS,
|
||||||
|
c.CGroupsNS: &s.CgroupNS,
|
||||||
//s.UserNS = specgen.Namespace{}
|
} {
|
||||||
|
if k != "" {
|
||||||
// Kernel Namespaces
|
*v, err = specgen.ParseNamespace(k)
|
||||||
// TODO Fix handling of namespace from pod
|
if err != nil {
|
||||||
// Instead of integrating here, should be done in libpod
|
return err
|
||||||
// However, that also involves setting up security opts
|
}
|
||||||
// when the pod's namespace is integrated
|
}
|
||||||
//namespaces = map[string]string{
|
}
|
||||||
// "cgroup": c.CGroupsNS,
|
// userns must be treated differently
|
||||||
// "pid": c.PID,
|
if c.UserNS != "" {
|
||||||
// //"net": c.Net.Network.Value, // TODO need help here
|
s.UserNS, err = specgen.ParseUserNamespace(c.UserNS)
|
||||||
// "ipc": c.IPC,
|
if err != nil {
|
||||||
// "user": c.User,
|
return err
|
||||||
// "uts": c.UTS,
|
}
|
||||||
//}
|
}
|
||||||
//
|
if c.Net != nil {
|
||||||
//if len(c.PID) > 0 {
|
s.NetNS = c.Net.Network
|
||||||
// split := strings.SplitN(c.PID, ":", 2)
|
|
||||||
// // need a way to do thsi
|
|
||||||
// specgen.Namespace{
|
|
||||||
// NSMode: split[0],
|
|
||||||
// }
|
|
||||||
// //Value: split1 if len allows
|
|
||||||
//}
|
|
||||||
// TODO this is going to have be done after things like pod creation are done because
|
|
||||||
// pod creation changes these values.
|
|
||||||
//pidMode := ns.PidMode(namespaces["pid"])
|
|
||||||
//usernsMode := ns.UsernsMode(namespaces["user"])
|
|
||||||
//utsMode := ns.UTSMode(namespaces["uts"])
|
|
||||||
//cgroupMode := ns.CgroupMode(namespaces["cgroup"])
|
|
||||||
//ipcMode := ns.IpcMode(namespaces["ipc"])
|
|
||||||
//// Make sure if network is set to container namespace, port binding is not also being asked for
|
|
||||||
//netMode := ns.NetworkMode(namespaces["net"])
|
|
||||||
//if netMode.IsContainer() {
|
|
||||||
// if len(portBindings) > 0 {
|
|
||||||
// return nil, errors.Errorf("cannot set port bindings on an existing container network namespace")
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
// TODO Remove when done with namespaces for realz
|
|
||||||
// Setting a default for IPC to get this working
|
|
||||||
s.IpcNS = specgen.Namespace{
|
|
||||||
NSMode: specgen.Private,
|
|
||||||
Value: "",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO this is going to have to be done the libpod/server end of things
|
// TODO this is going to have to be done the libpod/server end of things
|
||||||
|
@ -149,6 +149,21 @@ func createInit(c *cobra.Command) error {
|
|||||||
if c.Flag("no-hosts").Changed && c.Flag("add-host").Changed {
|
if c.Flag("no-hosts").Changed && c.Flag("add-host").Changed {
|
||||||
return errors.Errorf("--no-hosts and --add-host cannot be set together")
|
return errors.Errorf("--no-hosts and --add-host cannot be set together")
|
||||||
}
|
}
|
||||||
|
if c.Flag("userns").Changed {
|
||||||
|
cliVals.UserNS = c.Flag("userns").Value.String()
|
||||||
|
}
|
||||||
|
if c.Flag("ipc").Changed {
|
||||||
|
cliVals.IPC = c.Flag("ipc").Value.String()
|
||||||
|
}
|
||||||
|
if c.Flag("uts").Changed {
|
||||||
|
cliVals.UTS = c.Flag("uts").Value.String()
|
||||||
|
}
|
||||||
|
if c.Flag("pid").Changed {
|
||||||
|
cliVals.PID = c.Flag("pid").Value.String()
|
||||||
|
}
|
||||||
|
if c.Flag("cgroupns").Changed {
|
||||||
|
cliVals.CGroupsNS = c.Flag("cgroupns").Value.String()
|
||||||
|
}
|
||||||
|
|
||||||
// Docker-compatibility: the "-h" flag for run/create is reserved for
|
// Docker-compatibility: the "-h" flag for run/create is reserved for
|
||||||
// the hostname (see https://github.com/containers/libpod/issues/1367).
|
// the hostname (see https://github.com/containers/libpod/issues/1367).
|
||||||
|
@ -129,7 +129,7 @@ func (s *SpecGenerator) Validate() error {
|
|||||||
if err := s.CgroupNS.validate(); err != nil {
|
if err := s.CgroupNS.validate(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := s.UserNS.validate(); err != nil {
|
if err := validateUserNS(&s.UserNS); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,8 +58,7 @@ func GetDefaultNamespaceMode(nsType string, cfg *config.Config, pod *libpod.Pod)
|
|||||||
case "uts":
|
case "uts":
|
||||||
return specgen.ParseNamespace(cfg.Containers.UTSNS)
|
return specgen.ParseNamespace(cfg.Containers.UTSNS)
|
||||||
case "user":
|
case "user":
|
||||||
// TODO: This may not work for --userns=auto
|
return specgen.ParseUserNamespace(cfg.Containers.UserNS)
|
||||||
return specgen.ParseNamespace(cfg.Containers.UserNS)
|
|
||||||
case "net":
|
case "net":
|
||||||
ns, _, err := specgen.ParseNetworkNamespace(cfg.Containers.NetNS)
|
ns, _, err := specgen.ParseNetworkNamespace(cfg.Containers.NetNS)
|
||||||
return ns, err
|
return ns, err
|
||||||
|
@ -33,6 +33,11 @@ const (
|
|||||||
// Slirp indicates that a slirp4netns network stack should
|
// Slirp indicates that a slirp4netns network stack should
|
||||||
// be used
|
// be used
|
||||||
Slirp NamespaceMode = "slirp4netns"
|
Slirp NamespaceMode = "slirp4netns"
|
||||||
|
// KeepId indicates a user namespace to keep the owner uid inside
|
||||||
|
// of the namespace itself
|
||||||
|
KeepID NamespaceMode = "keep-id"
|
||||||
|
// KeepId indicates to automatically create a user namespace
|
||||||
|
Auto NamespaceMode = "auto"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Namespace describes the namespace
|
// Namespace describes the namespace
|
||||||
@ -71,6 +76,16 @@ func (n *Namespace) IsPod() bool {
|
|||||||
func (n *Namespace) IsPrivate() bool {
|
func (n *Namespace) IsPrivate() bool {
|
||||||
return n.NSMode == Private
|
return n.NSMode == Private
|
||||||
}
|
}
|
||||||
|
func validateUserNS(n *Namespace) error {
|
||||||
|
if n == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
switch n.NSMode {
|
||||||
|
case Auto, KeepID:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return n.validate()
|
||||||
|
}
|
||||||
|
|
||||||
func validateNetNS(n *Namespace) error {
|
func validateNetNS(n *Namespace) error {
|
||||||
if n == nil {
|
if n == nil {
|
||||||
@ -158,6 +173,30 @@ func ParseNamespace(ns string) (Namespace, error) {
|
|||||||
return toReturn, nil
|
return toReturn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParseUserNamespace parses a user namespace specification in string
|
||||||
|
// form.
|
||||||
|
func ParseUserNamespace(ns string) (Namespace, error) {
|
||||||
|
toReturn := Namespace{}
|
||||||
|
switch {
|
||||||
|
case ns == "auto":
|
||||||
|
toReturn.NSMode = Auto
|
||||||
|
return toReturn, nil
|
||||||
|
case strings.HasPrefix(ns, "auto:"):
|
||||||
|
split := strings.SplitN(ns, ":", 2)
|
||||||
|
if len(split) != 2 {
|
||||||
|
return toReturn, errors.Errorf("invalid setting for auto: mode")
|
||||||
|
}
|
||||||
|
toReturn.NSMode = KeepID
|
||||||
|
toReturn.Value = split[1]
|
||||||
|
return toReturn, nil
|
||||||
|
case ns == "keep-id":
|
||||||
|
toReturn.NSMode = KeepID
|
||||||
|
toReturn.NSMode = FromContainer
|
||||||
|
return toReturn, nil
|
||||||
|
}
|
||||||
|
return ParseNamespace(ns)
|
||||||
|
}
|
||||||
|
|
||||||
// ParseNetworkNamespace parses a network namespace specification in string
|
// ParseNetworkNamespace parses a network namespace specification in string
|
||||||
// form.
|
// form.
|
||||||
// Returns a namespace and (optionally) a list of CNI networks to join.
|
// Returns a namespace and (optionally) a list of CNI networks to join.
|
||||||
|
Reference in New Issue
Block a user