diff options
Diffstat (limited to 'cmd/podman/common')
-rw-r--r-- | cmd/podman/common/create.go | 18 | ||||
-rw-r--r-- | cmd/podman/common/ports.go | 112 | ||||
-rw-r--r-- | cmd/podman/common/specgen.go | 176 |
3 files changed, 106 insertions, 200 deletions
diff --git a/cmd/podman/common/create.go b/cmd/podman/common/create.go index bdf762ed7..a0aed984c 100644 --- a/cmd/podman/common/create.go +++ b/cmd/podman/common/create.go @@ -49,8 +49,9 @@ func GetCreateFlags(cf *ContainerCLIOpts) *pflag.FlagSet { "cap-drop", []string{}, "Drop capabilities from the container", ) + cgroupNS := "" createFlags.StringVar( - &cf.CGroupsNS, + &cgroupNS, "cgroupns", containerConfig.CgroupNS(), "cgroup namespace to use", ) @@ -247,8 +248,9 @@ func GetCreateFlags(cf *ContainerCLIOpts) *pflag.FlagSet { "interactive", "i", false, "Keep STDIN open even if not attached", ) + ipcNS := "" createFlags.StringVar( - &cf.IPC, + &ipcNS, "ipc", containerConfig.IPCNS(), "IPC namespace to use", ) @@ -329,8 +331,9 @@ func GetCreateFlags(cf *ContainerCLIOpts) *pflag.FlagSet { "use `OS` instead of the running OS for choosing images", ) // markFlagHidden(createFlags, "override-os") + pid := "" createFlags.StringVar( - &cf.PID, + &pid, "pid", containerConfig.PidNS(), "PID namespace to use", ) @@ -394,8 +397,9 @@ func GetCreateFlags(cf *ContainerCLIOpts) *pflag.FlagSet { "security-opt", containerConfig.SecurityOptions(), "Security Options", ) + shmSize := "" createFlags.StringVar( - &cf.ShmSize, + &shmSize, "shm-size", containerConfig.ShmSize(), "Size of /dev/shm "+sizeWithUnitFormat, ) @@ -460,13 +464,15 @@ func GetCreateFlags(cf *ContainerCLIOpts) *pflag.FlagSet { "user", "u", "", "Username or UID (format: <name|uid>[:<group|gid>])", ) + userNS := "" createFlags.StringVar( - &cf.UserNS, + &userNS, "userns", containerConfig.Containers.UserNS, "User namespace to use", ) + utsNS := "" createFlags.StringVar( - &cf.UTS, + &utsNS, "uts", containerConfig.Containers.UTSNS, "UTS namespace to use", ) diff --git a/cmd/podman/common/ports.go b/cmd/podman/common/ports.go index 7e2b1e79d..a96bafabd 100644 --- a/cmd/podman/common/ports.go +++ b/cmd/podman/common/ports.go @@ -1,28 +1,11 @@ package common import ( - "fmt" - "net" - "strconv" - - "github.com/cri-o/ocicni/pkg/ocicni" "github.com/docker/go-connections/nat" "github.com/pkg/errors" - "github.com/sirupsen/logrus" ) -// ExposedPorts parses user and image ports and returns binding information -func ExposedPorts(expose []string, publish []ocicni.PortMapping, publishAll bool, imageExposedPorts map[string]struct{}) ([]ocicni.PortMapping, error) { - containerPorts := make(map[string]string) - - // TODO this needs to be added into a something that - // has access to an imageengine - // add expose ports from the image itself - //for expose := range imageExposedPorts { - // _, port := nat.SplitProtoPort(expose) - // containerPorts[port] = "" - //} - +func verifyExpose(expose []string) error { // add the expose ports from the user (--expose) // can be single or a range for _, expose := range expose { @@ -30,97 +13,10 @@ func ExposedPorts(expose []string, publish []ocicni.PortMapping, publishAll bool _, port := nat.SplitProtoPort(expose) //parse the start and end port and create a sequence of ports to expose //if expose a port, the start and end port are the same - start, end, err := nat.ParsePortRange(port) + _, _, err := nat.ParsePortRange(port) if err != nil { - return nil, fmt.Errorf("invalid range format for --expose: %s, error: %s", expose, err) - } - for i := start; i <= end; i++ { - containerPorts[strconv.Itoa(int(i))] = "" - } - } - - // TODO/FIXME this is hell reencarnated - // parse user inputted port bindings - pbPorts, portBindings, err := nat.ParsePortSpecs([]string{}) - if err != nil { - return nil, err - } - - // delete exposed container ports if being used by -p - for i := range pbPorts { - delete(containerPorts, i.Port()) - } - - // iterate container ports and make port bindings from them - if publishAll { - for e := range containerPorts { - //support two formats for expose, original format <portnum>/[<proto>] or <startport-endport>/[<proto>] - //proto, port := nat.SplitProtoPort(e) - p, err := nat.NewPort("tcp", e) - if err != nil { - return nil, err - } - rp, err := getRandomPort() - if err != nil { - return nil, err - } - logrus.Debug(fmt.Sprintf("Using random host port %d with container port %d", rp, p.Int())) - portBindings[p] = CreatePortBinding(rp, "") - } - } - - // We need to see if any host ports are not populated and if so, we need to assign a - // random port to them. - for k, pb := range portBindings { - if pb[0].HostPort == "" { - hostPort, err := getRandomPort() - if err != nil { - return nil, err - } - logrus.Debug(fmt.Sprintf("Using random host port %d with container port %s", hostPort, k.Port())) - pb[0].HostPort = strconv.Itoa(hostPort) - } - } - var pms []ocicni.PortMapping - for k, v := range portBindings { - for _, pb := range v { - hp, err := strconv.Atoi(pb.HostPort) - if err != nil { - return nil, err - } - pms = append(pms, ocicni.PortMapping{ - HostPort: int32(hp), - ContainerPort: int32(k.Int()), - //Protocol: "", - HostIP: pb.HostIP, - }) + return errors.Wrapf(err, "invalid range format for --expose: %s", expose) } } - return pms, nil -} - -func getRandomPort() (int, error) { - l, err := net.Listen("tcp", ":0") - if err != nil { - return 0, errors.Wrapf(err, "unable to get free port") - } - defer l.Close() - _, randomPort, err := net.SplitHostPort(l.Addr().String()) - if err != nil { - return 0, errors.Wrapf(err, "unable to determine free port") - } - rp, err := strconv.Atoi(randomPort) - if err != nil { - return 0, errors.Wrapf(err, "unable to convert random port to int") - } - return rp, nil -} - -//CreatePortBinding takes port (int) and IP (string) and creates an array of portbinding structs -func CreatePortBinding(hostPort int, hostIP string) []nat.PortBinding { - pb := nat.PortBinding{ - HostPort: strconv.Itoa(hostPort), - } - pb.HostIP = hostIP - return []nat.PortBinding{pb} + return nil } diff --git a/cmd/podman/common/specgen.go b/cmd/podman/common/specgen.go index 10ae0bb2d..5d5816ea4 100644 --- a/cmd/podman/common/specgen.go +++ b/cmd/podman/common/specgen.go @@ -119,13 +119,13 @@ func getIOLimits(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string) ( func getPidsLimits(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string) (*specs.LinuxPids, error) { pids := &specs.LinuxPids{} hasLimits := false + if c.CGroupsMode == "disabled" && c.PIDsLimit > 0 { + return nil, nil + } if c.PIDsLimit > 0 { pids.Limit = c.PIDsLimit hasLimits = true } - if c.CGroupsMode == "disabled" && c.PIDsLimit > 0 { - s.ResourceLimits.Pids.Limit = -1 - } if !hasLimits { return nil, nil } @@ -203,89 +203,63 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string s.User = c.User inputCommand := args[1:] if len(c.HealthCmd) > 0 { + if c.NoHealthCheck { + return errors.New("Cannot specify both --no-healthcheck and --health-cmd") + } s.HealthConfig, err = makeHealthCheckFromCli(c.HealthCmd, c.HealthInterval, c.HealthRetries, c.HealthTimeout, c.HealthStartPeriod) if err != nil { return err } + } else if c.NoHealthCheck { + s.HealthConfig = &manifest.Schema2HealthConfig{ + Test: []string{"NONE"}, + } } - s.IDMappings, err = util.ParseIDMapping(ns.UsernsMode(c.UserNS), c.UIDMap, c.GIDMap, c.SubUIDName, c.SubGIDName) + userNS := ns.UsernsMode(c.UserNS) + s.IDMappings, err = util.ParseIDMapping(userNS, c.UIDMap, c.GIDMap, c.SubUIDName, c.SubGIDName) if err != nil { return err } + // If some mappings are specified, assume a private user namespace + if userNS.IsDefaultValue() && (!s.IDMappings.HostUIDMapping || !s.IDMappings.HostGIDMapping) { + s.UserNS.NSMode = specgen.Private + } s.Terminal = c.TTY - ep, err := ExposedPorts(c.Expose, c.Net.PublishPorts, c.PublishAll, nil) - if err != nil { + + if err := verifyExpose(c.Expose); err != nil { return err } - s.PortMappings = ep + // We are not handling the Expose flag yet. + // s.PortsExpose = c.Expose + s.PortMappings = c.Net.PublishPorts + s.PublishImagePorts = c.PublishAll s.Pod = c.Pod - //s.CgroupNS = specgen.Namespace{ - // NSMode: , - // Value: "", - //} - - //s.UserNS = specgen.Namespace{} - - // Kernel Namespaces - // TODO Fix handling of namespace from pod - // Instead of integrating here, should be done in libpod - // However, that also involves setting up security opts - // when the pod's namespace is integrated - //namespaces = map[string]string{ - // "cgroup": c.CGroupsNS, - // "pid": c.PID, - // //"net": c.Net.Network.Value, // TODO need help here - // "ipc": c.IPC, - // "user": c.User, - // "uts": c.UTS, - //} - // - //if len(c.PID) > 0 { - // 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 - // USER - //user := c.String("user") - //if user == "" { - // switch { - // case usernsMode.IsKeepID(): - // user = fmt.Sprintf("%d:%d", rootless.GetRootlessUID(), rootless.GetRootlessGID()) - // case data == nil: - // user = "0" - // default: - // user = data.Config.User - // } - //} + for k, v := range map[string]*specgen.Namespace{ + c.IPC: &s.IpcNS, + c.PID: &s.PidNS, + c.UTS: &s.UtsNS, + c.CGroupsNS: &s.CgroupNS, + } { + if k != "" { + *v, err = specgen.ParseNamespace(k) + if err != nil { + return err + } + } + } + // userns must be treated differently + if c.UserNS != "" { + s.UserNS, err = specgen.ParseUserNamespace(c.UserNS) + if err != nil { + return err + } + } + if c.Net != nil { + s.NetNS = c.Net.Network + } // STOP SIGNAL signalString := "TERM" @@ -315,7 +289,23 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string if c.EnvHost { env = envLib.Join(env, osEnv) + } else if c.HTTPProxy { + for _, envSpec := range []string{ + "http_proxy", + "HTTP_PROXY", + "https_proxy", + "HTTPS_PROXY", + "ftp_proxy", + "FTP_PROXY", + "no_proxy", + "NO_PROXY", + } { + if v, ok := osEnv[envSpec]; ok { + env[envSpec] = v + } + } } + // env-file overrides any previous variables for _, f := range c.EnvFile { fileEnv, err := envLib.ParseFile(f) @@ -403,11 +393,13 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string } // SHM Size - shmSize, err := units.FromHumanSize(c.ShmSize) - if err != nil { - return errors.Wrapf(err, "unable to translate --shm-size") + if c.ShmSize != "" { + shmSize, err := units.FromHumanSize(c.ShmSize) + if err != nil { + return errors.Wrapf(err, "unable to translate --shm-size") + } + s.ShmSize = &shmSize } - s.ShmSize = &shmSize s.HostAdd = c.Net.AddHosts s.UseImageResolvConf = c.Net.UseImageResolvConf s.DNSServers = c.Net.DNSServers @@ -415,14 +407,13 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string s.DNSOptions = c.Net.DNSOptions s.StaticIP = c.Net.StaticIP s.StaticMAC = c.Net.StaticMAC - - // deferred, must be added on libpod side - //var ImageVolumes map[string]struct{} - //if data != nil && c.String("image-volume") != "ignore" { - // ImageVolumes = data.Config.Volumes - //} + s.UseImageHosts = c.Net.NoHosts s.ImageVolumeMode = c.ImageVolume + if s.ImageVolumeMode == "bind" { + s.ImageVolumeMode = "anonymous" + } + systemd := c.SystemdD == "always" if !systemd && command != nil { x, err := strconv.ParseBool(c.SystemdD) @@ -474,6 +465,7 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string } s.CgroupParent = c.CGroupParent s.CgroupsMode = c.CGroupsMode + s.Groups = c.GroupAdd // TODO WTF //cgroup := &cc.CgroupConfig{ // Cgroupns: c.String("cgroupns"), @@ -610,7 +602,14 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string if len(split) < 2 { return errors.Errorf("invalid log option %q", o) } - logOpts[split[0]] = split[1] + switch { + case split[0] == "driver": + s.LogConfiguration.Driver = split[1] + case split[0] == "path": + s.LogConfiguration.Path = split[1] + default: + logOpts[split[0]] = split[1] + } } s.LogConfiguration.Options = logOpts s.Name = c.Name @@ -633,10 +632,15 @@ func makeHealthCheckFromCli(inCmd, interval string, retries uint, timeout, start // first try to parse option value as JSON array of strings... cmd := []string{} - err := json.Unmarshal([]byte(inCmd), &cmd) - if err != nil { - // ...otherwise pass it to "/bin/sh -c" inside the container - cmd = []string{"CMD-SHELL", inCmd} + + if inCmd == "none" { + cmd = []string{"NONE"} + } else { + err := json.Unmarshal([]byte(inCmd), &cmd) + if err != nil { + // ...otherwise pass it to "/bin/sh -c" inside the container + cmd = []string{"CMD-SHELL", inCmd} + } } hc := manifest.Schema2HealthConfig{ Test: cmd, |