summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore37
-rw-r--r--cmd/podman/common/specgen.go21
-rw-r--r--cmd/podman/containers/start.go4
-rw-r--r--cmd/podman/pods/ps.go99
-rw-r--r--go.mod2
-rw-r--r--go.sum4
-rw-r--r--libpod/pod.go21
-rw-r--r--pkg/api/handlers/swagger/swagger.go2
-rw-r--r--pkg/domain/infra/abi/containers.go8
-rw-r--r--pkg/domain/infra/abi/pods.go18
-rw-r--r--pkg/namespaces/namespaces.go7
-rw-r--r--pkg/specgen/generate/namespaces.go20
-rw-r--r--pkg/specgen/namespaces.go14
-rw-r--r--pkg/util/utils.go101
-rw-r--r--test/e2e/commit_test.go1
-rw-r--r--test/e2e/common_test.go5
-rw-r--r--test/e2e/container_inspect_test.go1
-rw-r--r--test/e2e/init_test.go1
-rw-r--r--test/e2e/pause_test.go1
-rw-r--r--test/e2e/pod_inspect_test.go6
-rw-r--r--test/e2e/pod_kill_test.go1
-rw-r--r--test/e2e/pod_prune_test.go1
-rw-r--r--test/e2e/pod_ps_test.go18
-rw-r--r--test/e2e/pod_top_test.go1
-rw-r--r--test/e2e/run_dns_test.go1
-rw-r--r--test/e2e/run_ns_test.go1
-rw-r--r--test/e2e/run_passwd_test.go1
-rw-r--r--test/e2e/run_restart_test.go1
-rw-r--r--test/e2e/run_signal_test.go1
-rw-r--r--test/e2e/run_userns_test.go1
-rw-r--r--vendor/github.com/rootless-containers/rootlesskit/pkg/port/builtin/parent/parent.go39
-rw-r--r--vendor/modules.txt2
32 files changed, 287 insertions, 154 deletions
diff --git a/.gitignore b/.gitignore
index d5d1206b5..e60b8c03a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,32 +1,33 @@
/.artifacts/
-/_output/
+/bin/
/brew
+/build/
+/cmd/podman/varlink/iopodman.go
+/cmd/podman/varlink/ioprojectatomicpodman.go
/conmon/
+contrib/spec/podman.spec
+*.coverprofile
/docs/*.[158]
/docs/*.[158].gz
-/docs/remote
/docs/build/
+/docs/remote
+.gopathok
+.idea*
+.nfs*
*.o
*.orig
+/_output/
/pause/pause.o
-/bin/
+pkg/api/swagger.yaml
+/pkg/varlink/iopodman.go
+podman-remote*.zip
+podman*.tar.gz
+__pycache__
+release.txt
+.ropeproject
+*.rpm
/test/bin2img/bin2img
/test/checkseccomp/checkseccomp
/test/copyimg/copyimg
/test/goecho/goecho
-/build/
-.nfs*
-.ropeproject
-__pycache__
-/cmd/podman/varlink/ioprojectatomicpodman.go
-/cmd/podman/varlink/iopodman.go
-/pkg/varlink/iopodman.go
-.gopathok
-release.txt
-podman-remote*.zip
-podman*.tar.gz
-.idea*
.vscode*
-contrib/spec/podman.spec
-*.rpm
-*.coverprofile
diff --git a/cmd/podman/common/specgen.go b/cmd/podman/common/specgen.go
index abec1213c..488843f41 100644
--- a/cmd/podman/common/specgen.go
+++ b/cmd/podman/common/specgen.go
@@ -209,10 +209,15 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string
}
}
- 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)
@@ -246,20 +251,6 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string
s.NetNS = c.Net.Network
}
- // 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
- // }
- //}
-
// STOP SIGNAL
signalString := "TERM"
if sig := c.StopSignal; len(sig) > 0 {
diff --git a/cmd/podman/containers/start.go b/cmd/podman/containers/start.go
index 73f37e51f..381bf8e26 100644
--- a/cmd/podman/containers/start.go
+++ b/cmd/podman/containers/start.go
@@ -20,7 +20,6 @@ var (
Short: "Start one or more containers",
Long: startDescription,
RunE: start,
- Args: cobra.MinimumNArgs(1),
Example: `podman start --latest
podman start 860a4b231279 5421ab43b45
podman start --interactive --attach imageID`,
@@ -72,6 +71,9 @@ func init() {
func start(cmd *cobra.Command, args []string) error {
var errs utils.OutputErrors
+ if len(args) == 0 && !startOptions.Latest {
+ return errors.New("start requires at least one argument")
+ }
if len(args) > 1 && startOptions.Attach {
return errors.Errorf("you cannot start and attach multiple containers at once")
}
diff --git a/cmd/podman/pods/ps.go b/cmd/podman/pods/ps.go
index 808980eff..6d0d9cf7f 100644
--- a/cmd/podman/pods/ps.go
+++ b/cmd/podman/pods/ps.go
@@ -5,6 +5,7 @@ import (
"fmt"
"io"
"os"
+ "sort"
"strings"
"text/tabwriter"
"text/template"
@@ -32,7 +33,7 @@ var (
var (
defaultHeaders string = "POD ID\tNAME\tSTATUS\tCREATED"
- inputFilters string
+ inputFilters []string
noTrunc bool
psInput entities.PodPSOptions
)
@@ -48,7 +49,7 @@ func init() {
flags.BoolVar(&psInput.CtrIds, "ctr-ids", false, "Display the container UUIDs. If no-trunc is not set they will be truncated")
flags.BoolVar(&psInput.CtrStatus, "ctr-status", false, "Display the container status")
// TODO should we make this a [] ?
- flags.StringVarP(&inputFilters, "filter", "f", "", "Filter output based on conditions given")
+ flags.StringSliceVarP(&inputFilters, "filter", "f", []string{}, "Filter output based on conditions given")
flags.StringVar(&psInput.Format, "format", "", "Pretty-print pods to JSON or using a Go template")
flags.BoolVarP(&psInput.Latest, "latest", "l", false, "Act on the latest pod podman is aware of")
flags.BoolVar(&psInput.Namespace, "namespace", false, "Display namespace information of the pod")
@@ -67,8 +68,13 @@ func pods(cmd *cobra.Command, args []string) error {
row string
lpr []ListPodReporter
)
+
+ if psInput.Quiet && len(psInput.Format) > 0 {
+ return errors.New("quiet and format cannot be used together")
+ }
if cmd.Flag("filter").Changed {
- for _, f := range strings.Split(inputFilters, ",") {
+ psInput.Filters = make(map[string][]string)
+ for _, f := range inputFilters {
split := strings.Split(f, "=")
if len(split) < 2 {
return errors.Errorf("filter input must be in the form of filter=value: %s is invalid", f)
@@ -81,6 +87,10 @@ func pods(cmd *cobra.Command, args []string) error {
return err
}
+ if err := sortPodPsOutput(psInput.Sort, responses); err != nil {
+ return err
+ }
+
if psInput.Format == "json" {
b, err := json.MarshalIndent(responses, "", " ")
if err != nil {
@@ -95,11 +105,7 @@ func pods(cmd *cobra.Command, args []string) error {
}
headers, row := createPodPsOut()
if psInput.Quiet {
- if noTrunc {
- row = "{{.Id}}\n"
- } else {
- row = "{{slice .Id 0 12}}\n"
- }
+ row = "{{.Id}}\n"
}
if cmd.Flag("format").Changed {
row = psInput.Format
@@ -130,11 +136,7 @@ func pods(cmd *cobra.Command, args []string) error {
func createPodPsOut() (string, string) {
var row string
headers := defaultHeaders
- if noTrunc {
- row += "{{.Id}}"
- } else {
- row += "{{slice .Id 0 12}}"
- }
+ row += "{{.Id}}"
row += "\t{{.Name}}\t{{.Status}}\t{{.Created}}"
@@ -160,11 +162,7 @@ func createPodPsOut() (string, string) {
}
headers += "\tINFRA ID\n"
- if noTrunc {
- row += "\t{{.InfraId}}\n"
- } else {
- row += "\t{{slice .InfraId 0 12}}\n"
- }
+ row += "\t{{.InfraId}}\n"
return headers, row
}
@@ -184,6 +182,19 @@ func (l ListPodReporter) NumberOfContainers() int {
return len(l.Containers)
}
+// ID is a wrapper to Id for compat, typos
+func (l ListPodReporter) ID() string {
+ return l.Id()
+}
+
+// Id returns the Pod id
+func (l ListPodReporter) Id() string {
+ if noTrunc {
+ return l.ListPodsReport.Id
+ }
+ return l.ListPodsReport.Id[0:12]
+}
+
// Added for backwards compatibility with podmanv1
func (l ListPodReporter) InfraID() string {
return l.InfraId()
@@ -192,6 +203,9 @@ func (l ListPodReporter) InfraID() string {
// InfraId returns the infra container id for the pod
// depending on trunc
func (l ListPodReporter) InfraId() string {
+ if len(l.ListPodsReport.InfraId) == 0 {
+ return ""
+ }
if noTrunc {
return l.ListPodsReport.InfraId
}
@@ -225,3 +239,52 @@ func (l ListPodReporter) ContainerStatuses() string {
}
return strings.Join(statuses, ",")
}
+
+func sortPodPsOutput(sortBy string, lprs []*entities.ListPodsReport) error {
+ switch sortBy {
+ case "created":
+ sort.Sort(podPsSortedCreated{lprs})
+ case "id":
+ sort.Sort(podPsSortedId{lprs})
+ case "name":
+ sort.Sort(podPsSortedName{lprs})
+ case "number":
+ sort.Sort(podPsSortedNumber{lprs})
+ case "status":
+ sort.Sort(podPsSortedStatus{lprs})
+ default:
+ return errors.Errorf("invalid option for --sort, options are: id, names, or number")
+ }
+ return nil
+}
+
+type lprSort []*entities.ListPodsReport
+
+func (a lprSort) Len() int { return len(a) }
+func (a lprSort) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
+
+type podPsSortedCreated struct{ lprSort }
+
+func (a podPsSortedCreated) Less(i, j int) bool {
+ return a.lprSort[i].Created.After(a.lprSort[j].Created)
+}
+
+type podPsSortedId struct{ lprSort }
+
+func (a podPsSortedId) Less(i, j int) bool { return a.lprSort[i].Id < a.lprSort[j].Id }
+
+type podPsSortedNumber struct{ lprSort }
+
+func (a podPsSortedNumber) Less(i, j int) bool {
+ return len(a.lprSort[i].Containers) < len(a.lprSort[j].Containers)
+}
+
+type podPsSortedName struct{ lprSort }
+
+func (a podPsSortedName) Less(i, j int) bool { return a.lprSort[i].Name < a.lprSort[j].Name }
+
+type podPsSortedStatus struct{ lprSort }
+
+func (a podPsSortedStatus) Less(i, j int) bool {
+ return a.lprSort[i].Status < a.lprSort[j].Status
+}
diff --git a/go.mod b/go.mod
index 09077188c..576166df0 100644
--- a/go.mod
+++ b/go.mod
@@ -45,7 +45,7 @@ require (
github.com/opentracing/opentracing-go v1.1.0
github.com/pkg/errors v0.9.1
github.com/pmezard/go-difflib v1.0.0
- github.com/rootless-containers/rootlesskit v0.9.3
+ github.com/rootless-containers/rootlesskit v0.9.4
github.com/seccomp/containers-golang v0.0.0-20190312124753-8ca8945ccf5f
github.com/sirupsen/logrus v1.5.0
github.com/spf13/cobra v0.0.7
diff --git a/go.sum b/go.sum
index 92ea6f545..167d52e0a 100644
--- a/go.sum
+++ b/go.sum
@@ -373,8 +373,8 @@ github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDa
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
-github.com/rootless-containers/rootlesskit v0.9.3 h1:hrkZzBZT5vEnhAso6H1jHAcc4DT8h6/hp2z4yL0xu/8=
-github.com/rootless-containers/rootlesskit v0.9.3/go.mod h1:fx5DhInDgnR0Upj+2cOVacKuZJYSNKV5P/bCwGa+quQ=
+github.com/rootless-containers/rootlesskit v0.9.4 h1:6ogX7l3r3nlS7eTB8ePbLSQ6TZR1aVQzRjTy2SIBOzk=
+github.com/rootless-containers/rootlesskit v0.9.4/go.mod h1:fx5DhInDgnR0Upj+2cOVacKuZJYSNKV5P/bCwGa+quQ=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8 h1:2c1EFnZHIPCW8qKWgHMH/fX2PkSabFc5mrVzfUNdg5U=
github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4=
diff --git a/libpod/pod.go b/libpod/pod.go
index 4cdeb1033..b5a14c165 100644
--- a/libpod/pod.go
+++ b/libpod/pod.go
@@ -76,27 +76,6 @@ type podState struct {
InfraContainerID string
}
-// PodInspect represents the data we want to display for
-// podman pod inspect
-type PodInspect struct {
- Config *PodConfig
- State *PodInspectState
- Containers []PodContainerInfo
-}
-
-// PodInspectState contains inspect data on the pod's state
-type PodInspectState struct {
- CgroupPath string `json:"cgroupPath"`
- InfraContainerID string `json:"infraContainerID"`
- Status string `json:"status"`
-}
-
-// PodContainerInfo keeps information on a container in a pod
-type PodContainerInfo struct {
- ID string `json:"id"`
- State string `json:"state"`
-}
-
// InfraContainerConfig is the configuration for the pod's infra container
type InfraContainerConfig struct {
HasInfraContainer bool `json:"makeInfraContainer"`
diff --git a/pkg/api/handlers/swagger/swagger.go b/pkg/api/handlers/swagger/swagger.go
index 87891d4a8..7d8932f56 100644
--- a/pkg/api/handlers/swagger/swagger.go
+++ b/pkg/api/handlers/swagger/swagger.go
@@ -143,7 +143,7 @@ type swagListPodsResponse struct {
type swagInspectPodResponse struct {
// in:body
Body struct {
- libpod.PodInspect
+ define.InspectPodData
}
}
diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go
index a77b18ce1..9844d1d96 100644
--- a/pkg/domain/infra/abi/containers.go
+++ b/pkg/domain/infra/abi/containers.go
@@ -837,7 +837,13 @@ func (ic *ContainerEngine) ContainerInit(ctx context.Context, namesOrIds []strin
}
for _, ctr := range ctrs {
report := entities.ContainerInitReport{Id: ctr.ID()}
- report.Err = ctr.Init(ctx)
+ err := ctr.Init(ctx)
+
+ // If we're initializing all containers, ignore invalid state errors
+ if options.All && errors.Cause(err) == define.ErrCtrStateInvalid {
+ err = nil
+ }
+ report.Err = err
reports = append(reports, &report)
}
return reports, nil
diff --git a/pkg/domain/infra/abi/pods.go b/pkg/domain/infra/abi/pods.go
index c4ae9efbf..7732d5aa3 100644
--- a/pkg/domain/infra/abi/pods.go
+++ b/pkg/domain/infra/abi/pods.go
@@ -292,9 +292,12 @@ func (ic *ContainerEngine) PodTop(ctx context.Context, options entities.PodTopOp
func (ic *ContainerEngine) PodPs(ctx context.Context, options entities.PodPSOptions) ([]*entities.ListPodsReport, error) {
var (
+ err error
filters []libpod.PodFilter
+ pds []*libpod.Pod
reports []*entities.ListPodsReport
)
+
for k, v := range options.Filters {
for _, filter := range v {
f, err := lpfilters.GeneratePodFilterFunc(k, filter)
@@ -305,10 +308,19 @@ func (ic *ContainerEngine) PodPs(ctx context.Context, options entities.PodPSOpti
}
}
- pds, err := ic.Libpod.Pods(filters...)
- if err != nil {
- return nil, err
+ if options.Latest {
+ pod, err := ic.Libpod.GetLatestPod()
+ if err != nil {
+ return nil, err
+ }
+ pds = append(pds, pod)
+ } else {
+ pds, err = ic.Libpod.Pods(filters...)
+ if err != nil {
+ return nil, err
+ }
}
+
for _, p := range pds {
var lpcs []*entities.ListPodContainer
status, err := p.GetPodStatus()
diff --git a/pkg/namespaces/namespaces.go b/pkg/namespaces/namespaces.go
index 2cb3c3f20..2ffbde977 100644
--- a/pkg/namespaces/namespaces.go
+++ b/pkg/namespaces/namespaces.go
@@ -31,7 +31,7 @@ func (n CgroupMode) IsHost() bool {
// IsDefaultValue indicates whether the cgroup namespace has the default value.
func (n CgroupMode) IsDefaultValue() bool {
- return n == ""
+ return n == "" || n == defaultType
}
// IsNS indicates a cgroup namespace passed in by path (ns:<path>)
@@ -102,6 +102,11 @@ func (n UsernsMode) IsAuto() bool {
return parts[0] == "auto"
}
+// IsDefaultValue indicates whether the user namespace has the default value.
+func (n UsernsMode) IsDefaultValue() bool {
+ return n == "" || n == defaultType
+}
+
// GetAutoOptions returns a AutoUserNsOptions with the settings to setup automatically
// a user namespace.
func (n UsernsMode) GetAutoOptions() (*storage.AutoUserNsOptions, error) {
diff --git a/pkg/specgen/generate/namespaces.go b/pkg/specgen/generate/namespaces.go
index 2e0e088bf..a8b74b504 100644
--- a/pkg/specgen/generate/namespaces.go
+++ b/pkg/specgen/generate/namespaces.go
@@ -10,6 +10,7 @@ import (
"github.com/containers/libpod/pkg/cgroups"
"github.com/containers/libpod/pkg/rootless"
"github.com/containers/libpod/pkg/specgen"
+ "github.com/containers/libpod/pkg/util"
spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/runtime-tools/generate"
"github.com/pkg/errors"
@@ -175,6 +176,13 @@ func GenerateNamespaceOptions(s *specgen.SpecGenerator, rt *libpod.Runtime, pod
// User
switch s.UserNS.NSMode {
+ case specgen.KeepID:
+ if rootless.IsRootless() {
+ s.User = ""
+ } else {
+ // keep-id as root doesn't need a user namespace
+ s.UserNS.NSMode = specgen.Host
+ }
case specgen.FromPod:
if pod == nil || infraCtr == nil {
return nil, errNoInfra
@@ -378,6 +386,18 @@ func specConfigureNamespaces(s *specgen.SpecGenerator, g *generate.Generator, rt
if err := g.RemoveLinuxNamespace(string(spec.UserNamespace)); err != nil {
return err
}
+ case specgen.KeepID:
+ var (
+ err error
+ uid, gid int
+ )
+ s.IDMappings, uid, gid, err = util.GetKeepIDMapping()
+ if err != nil {
+ return err
+ }
+ g.SetProcessUID(uint32(uid))
+ g.SetProcessGID(uint32(gid))
+ fallthrough
case specgen.Private:
if err := g.AddOrReplaceLinuxNamespace(string(spec.UserNamespace), ""); err != nil {
return err
diff --git a/pkg/specgen/namespaces.go b/pkg/specgen/namespaces.go
index fffbd6d9e..cee49ff51 100644
--- a/pkg/specgen/namespaces.go
+++ b/pkg/specgen/namespaces.go
@@ -76,6 +76,17 @@ func (n *Namespace) IsPod() bool {
func (n *Namespace) IsPrivate() bool {
return n.NSMode == Private
}
+
+// IsAuto indicates the namespace is auto
+func (n *Namespace) IsAuto() bool {
+ return n.NSMode == Auto
+}
+
+// IsKeepID indicates the namespace is KeepID
+func (n *Namespace) IsKeepID() bool {
+ return n.NSMode == KeepID
+}
+
func validateUserNS(n *Namespace) error {
if n == nil {
return nil
@@ -186,12 +197,11 @@ func ParseUserNamespace(ns string) (Namespace, error) {
if len(split) != 2 {
return toReturn, errors.Errorf("invalid setting for auto: mode")
}
- toReturn.NSMode = KeepID
+ toReturn.NSMode = Auto
toReturn.Value = split[1]
return toReturn, nil
case ns == "keep-id":
toReturn.NSMode = KeepID
- toReturn.NSMode = FromContainer
return toReturn, nil
}
return ParseNamespace(ns)
diff --git a/pkg/util/utils.go b/pkg/util/utils.go
index 64331cf66..917f57742 100644
--- a/pkg/util/utils.go
+++ b/pkg/util/utils.go
@@ -330,6 +330,58 @@ func ParseSignal(rawSignal string) (syscall.Signal, error) {
return sig, nil
}
+// GetKeepIDMapping returns the mappings and the user to use when keep-id is used
+func GetKeepIDMapping() (*storage.IDMappingOptions, int, int, error) {
+ options := storage.IDMappingOptions{
+ HostUIDMapping: true,
+ HostGIDMapping: true,
+ }
+ uid, gid := 0, 0
+ if rootless.IsRootless() {
+ min := func(a, b int) int {
+ if a < b {
+ return a
+ }
+ return b
+ }
+
+ uid = rootless.GetRootlessUID()
+ gid = rootless.GetRootlessGID()
+
+ uids, gids, err := rootless.GetConfiguredMappings()
+ if err != nil {
+ return nil, -1, -1, errors.Wrapf(err, "cannot read mappings")
+ }
+ maxUID, maxGID := 0, 0
+ for _, u := range uids {
+ maxUID += u.Size
+ }
+ for _, g := range gids {
+ maxGID += g.Size
+ }
+
+ options.UIDMap, options.GIDMap = nil, nil
+
+ options.UIDMap = append(options.UIDMap, idtools.IDMap{ContainerID: 0, HostID: 1, Size: min(uid, maxUID)})
+ options.UIDMap = append(options.UIDMap, idtools.IDMap{ContainerID: uid, HostID: 0, Size: 1})
+ if maxUID > uid {
+ options.UIDMap = append(options.UIDMap, idtools.IDMap{ContainerID: uid + 1, HostID: uid + 1, Size: maxUID - uid})
+ }
+
+ options.GIDMap = append(options.GIDMap, idtools.IDMap{ContainerID: 0, HostID: 1, Size: min(gid, maxGID)})
+ options.GIDMap = append(options.GIDMap, idtools.IDMap{ContainerID: gid, HostID: 0, Size: 1})
+ if maxGID > gid {
+ options.GIDMap = append(options.GIDMap, idtools.IDMap{ContainerID: gid + 1, HostID: gid + 1, Size: maxGID - gid})
+ }
+
+ options.HostUIDMapping = false
+ options.HostGIDMapping = false
+
+ }
+ // Simply ignore the setting and do not setup an inner namespace for root as it is a no-op
+ return &options, uid, gid, nil
+}
+
// ParseIDMapping takes idmappings and subuid and subgid maps and returns a storage mapping
func ParseIDMapping(mode namespaces.UsernsMode, uidMapSlice, gidMapSlice []string, subUIDMap, subGIDMap string) (*storage.IDMappingOptions, error) {
options := storage.IDMappingOptions{
@@ -350,53 +402,8 @@ func ParseIDMapping(mode namespaces.UsernsMode, uidMapSlice, gidMapSlice []strin
return &options, nil
}
if mode.IsKeepID() {
- if len(uidMapSlice) > 0 || len(gidMapSlice) > 0 {
- return nil, errors.New("cannot specify custom mappings with --userns=keep-id")
- }
- if len(subUIDMap) > 0 || len(subGIDMap) > 0 {
- return nil, errors.New("cannot specify subuidmap or subgidmap with --userns=keep-id")
- }
- if rootless.IsRootless() {
- min := func(a, b int) int {
- if a < b {
- return a
- }
- return b
- }
-
- uid := rootless.GetRootlessUID()
- gid := rootless.GetRootlessGID()
-
- uids, gids, err := rootless.GetConfiguredMappings()
- if err != nil {
- return nil, errors.Wrapf(err, "cannot read mappings")
- }
- maxUID, maxGID := 0, 0
- for _, u := range uids {
- maxUID += u.Size
- }
- for _, g := range gids {
- maxGID += g.Size
- }
-
- options.UIDMap, options.GIDMap = nil, nil
-
- options.UIDMap = append(options.UIDMap, idtools.IDMap{ContainerID: 0, HostID: 1, Size: min(uid, maxUID)})
- options.UIDMap = append(options.UIDMap, idtools.IDMap{ContainerID: uid, HostID: 0, Size: 1})
- if maxUID > uid {
- options.UIDMap = append(options.UIDMap, idtools.IDMap{ContainerID: uid + 1, HostID: uid + 1, Size: maxUID - uid})
- }
-
- options.GIDMap = append(options.GIDMap, idtools.IDMap{ContainerID: 0, HostID: 1, Size: min(gid, maxGID)})
- options.GIDMap = append(options.GIDMap, idtools.IDMap{ContainerID: gid, HostID: 0, Size: 1})
- if maxGID > gid {
- options.GIDMap = append(options.GIDMap, idtools.IDMap{ContainerID: gid + 1, HostID: gid + 1, Size: maxGID - gid})
- }
-
- options.HostUIDMapping = false
- options.HostGIDMapping = false
- }
- // Simply ignore the setting and do not setup an inner namespace for root as it is a no-op
+ options.HostUIDMapping = false
+ options.HostGIDMapping = false
return &options, nil
}
diff --git a/test/e2e/commit_test.go b/test/e2e/commit_test.go
index ceb656a01..72387ed8c 100644
--- a/test/e2e/commit_test.go
+++ b/test/e2e/commit_test.go
@@ -18,7 +18,6 @@ var _ = Describe("Podman commit", func() {
)
BeforeEach(func() {
- Skip(v2fail)
tempdir, err = CreateTempDirInTempDir()
if err != nil {
os.Exit(1)
diff --git a/test/e2e/common_test.go b/test/e2e/common_test.go
index d93ee8d3a..160af1bd5 100644
--- a/test/e2e/common_test.go
+++ b/test/e2e/common_test.go
@@ -14,7 +14,6 @@ import (
"testing"
"time"
- "github.com/containers/libpod/libpod"
"github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/pkg/inspect"
"github.com/containers/libpod/pkg/rootless"
@@ -501,8 +500,8 @@ func (s *PodmanSessionIntegration) InspectContainerToJSON() []define.InspectCont
}
// InspectPodToJSON takes the sessions output from a pod inspect and returns json
-func (s *PodmanSessionIntegration) InspectPodToJSON() libpod.PodInspect {
- var i libpod.PodInspect
+func (s *PodmanSessionIntegration) InspectPodToJSON() define.InspectPodData {
+ var i define.InspectPodData
err := json.Unmarshal(s.Out.Contents(), &i)
Expect(err).To(BeNil())
return i
diff --git a/test/e2e/container_inspect_test.go b/test/e2e/container_inspect_test.go
index cc986f1a8..91c025197 100644
--- a/test/e2e/container_inspect_test.go
+++ b/test/e2e/container_inspect_test.go
@@ -17,7 +17,6 @@ var _ = Describe("Podman container inspect", func() {
)
BeforeEach(func() {
- Skip(v2fail)
tempdir, err = CreateTempDirInTempDir()
if err != nil {
os.Exit(1)
diff --git a/test/e2e/init_test.go b/test/e2e/init_test.go
index 6241f813f..919fe4abf 100644
--- a/test/e2e/init_test.go
+++ b/test/e2e/init_test.go
@@ -16,7 +16,6 @@ var _ = Describe("Podman init", func() {
)
BeforeEach(func() {
- Skip(v2fail)
tempdir, err = CreateTempDirInTempDir()
if err != nil {
os.Exit(1)
diff --git a/test/e2e/pause_test.go b/test/e2e/pause_test.go
index 66b888803..39e08e2e8 100644
--- a/test/e2e/pause_test.go
+++ b/test/e2e/pause_test.go
@@ -21,7 +21,6 @@ var _ = Describe("Podman pause", func() {
createdState := "Created"
BeforeEach(func() {
- Skip(v2fail)
SkipIfRootless()
tempdir, err = CreateTempDirInTempDir()
if err != nil {
diff --git a/test/e2e/pod_inspect_test.go b/test/e2e/pod_inspect_test.go
index 06f36c751..f87bbe047 100644
--- a/test/e2e/pod_inspect_test.go
+++ b/test/e2e/pod_inspect_test.go
@@ -16,7 +16,6 @@ var _ = Describe("Podman pod inspect", func() {
)
BeforeEach(func() {
- Skip(v2fail)
tempdir, err = CreateTempDirInTempDir()
if err != nil {
os.Exit(1)
@@ -55,8 +54,7 @@ var _ = Describe("Podman pod inspect", func() {
inspect.WaitWithDefaultTimeout()
Expect(inspect.ExitCode()).To(Equal(0))
Expect(inspect.IsJSONOutputValid()).To(BeTrue())
- // FIXME sujil, disabled for now
- //podData := inspect.InspectPodToJSON()
- //Expect(podData.Config.ID).To(Equal(podid))
+ podData := inspect.InspectPodToJSON()
+ Expect(podData.ID).To(Equal(podid))
})
})
diff --git a/test/e2e/pod_kill_test.go b/test/e2e/pod_kill_test.go
index 29d7664df..a3efec46c 100644
--- a/test/e2e/pod_kill_test.go
+++ b/test/e2e/pod_kill_test.go
@@ -17,7 +17,6 @@ var _ = Describe("Podman pod kill", func() {
)
BeforeEach(func() {
- Skip(v2fail)
tempdir, err = CreateTempDirInTempDir()
if err != nil {
os.Exit(1)
diff --git a/test/e2e/pod_prune_test.go b/test/e2e/pod_prune_test.go
index d0725883c..d98383331 100644
--- a/test/e2e/pod_prune_test.go
+++ b/test/e2e/pod_prune_test.go
@@ -16,7 +16,6 @@ var _ = Describe("Podman pod prune", func() {
)
BeforeEach(func() {
- Skip(v2fail)
tempdir, err = CreateTempDirInTempDir()
if err != nil {
os.Exit(1)
diff --git a/test/e2e/pod_ps_test.go b/test/e2e/pod_ps_test.go
index ea9118f37..5f8712a7a 100644
--- a/test/e2e/pod_ps_test.go
+++ b/test/e2e/pod_ps_test.go
@@ -18,7 +18,6 @@ var _ = Describe("Podman ps", func() {
)
BeforeEach(func() {
- Skip(v2fail)
tempdir, err = CreateTempDirInTempDir()
if err != nil {
os.Exit(1)
@@ -96,6 +95,7 @@ var _ = Describe("Podman ps", func() {
Expect(result.OutputToString()).To(ContainSubstring(podid2))
Expect(result.OutputToString()).To(Not(ContainSubstring(podid1)))
})
+
It("podman pod ps id filter flag", func() {
_, ec, podid := podmanTest.CreatePod("")
Expect(ec).To(Equal(0))
@@ -143,7 +143,7 @@ var _ = Describe("Podman ps", func() {
_, ec, _ = podmanTest.RunLsContainerInPod("test2", podid)
Expect(ec).To(Equal(0))
- session = podmanTest.Podman([]string{"pod", "ps", "--format={{.ContainerInfo}}", "--ctr-names"})
+ session = podmanTest.Podman([]string{"pod", "ps", "--format={{.ContainerNames}}", "--ctr-names"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
Expect(session.OutputToString()).To(ContainSubstring("test1"))
@@ -228,4 +228,18 @@ var _ = Describe("Podman ps", func() {
Expect(session.OutputToString()).To(ContainSubstring(podid2))
Expect(session.OutputToString()).To(Not(ContainSubstring(podid3)))
})
+
+ It("pod no infra should ps", func() {
+ session := podmanTest.Podman([]string{"pod", "create", "--infra=false"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ ps := podmanTest.Podman([]string{"pod", "ps"})
+ ps.WaitWithDefaultTimeout()
+ Expect(ps.ExitCode()).To(Equal(0))
+
+ infra := podmanTest.Podman([]string{"pod", "ps", "--format", "{{.InfraId}}"})
+ infra.WaitWithDefaultTimeout()
+ Expect(len(infra.OutputToString())).To(BeZero())
+ })
})
diff --git a/test/e2e/pod_top_test.go b/test/e2e/pod_top_test.go
index 2f75aaf30..c313b0675 100644
--- a/test/e2e/pod_top_test.go
+++ b/test/e2e/pod_top_test.go
@@ -20,7 +20,6 @@ var _ = Describe("Podman top", func() {
)
BeforeEach(func() {
- Skip(v2fail)
tempdir, err = CreateTempDirInTempDir()
if err != nil {
os.Exit(1)
diff --git a/test/e2e/run_dns_test.go b/test/e2e/run_dns_test.go
index 749047b76..02b9ff8d1 100644
--- a/test/e2e/run_dns_test.go
+++ b/test/e2e/run_dns_test.go
@@ -18,7 +18,6 @@ var _ = Describe("Podman run dns", func() {
)
BeforeEach(func() {
- Skip(v2fail)
tempdir, err = CreateTempDirInTempDir()
if err != nil {
os.Exit(1)
diff --git a/test/e2e/run_ns_test.go b/test/e2e/run_ns_test.go
index 9c914188a..c8ba68efc 100644
--- a/test/e2e/run_ns_test.go
+++ b/test/e2e/run_ns_test.go
@@ -19,7 +19,6 @@ var _ = Describe("Podman run ns", func() {
)
BeforeEach(func() {
- Skip(v2fail)
tempdir, err = CreateTempDirInTempDir()
if err != nil {
os.Exit(1)
diff --git a/test/e2e/run_passwd_test.go b/test/e2e/run_passwd_test.go
index 0868bce4f..bd6a0e036 100644
--- a/test/e2e/run_passwd_test.go
+++ b/test/e2e/run_passwd_test.go
@@ -18,7 +18,6 @@ var _ = Describe("Podman run passwd", func() {
)
BeforeEach(func() {
- Skip(v2fail)
tempdir, err = CreateTempDirInTempDir()
if err != nil {
os.Exit(1)
diff --git a/test/e2e/run_restart_test.go b/test/e2e/run_restart_test.go
index 28ab23ab0..8bbdf2056 100644
--- a/test/e2e/run_restart_test.go
+++ b/test/e2e/run_restart_test.go
@@ -18,7 +18,6 @@ var _ = Describe("Podman run restart containers", func() {
)
BeforeEach(func() {
- Skip(v2fail)
tempdir, err = CreateTempDirInTempDir()
if err != nil {
os.Exit(1)
diff --git a/test/e2e/run_signal_test.go b/test/e2e/run_signal_test.go
index 58dde62da..fbdd3acec 100644
--- a/test/e2e/run_signal_test.go
+++ b/test/e2e/run_signal_test.go
@@ -29,7 +29,6 @@ var _ = Describe("Podman run with --sig-proxy", func() {
)
BeforeEach(func() {
- Skip(v2fail)
tmpdir, err = CreateTempDirInTempDir()
if err != nil {
os.Exit(1)
diff --git a/test/e2e/run_userns_test.go b/test/e2e/run_userns_test.go
index a4e99ab71..25f12ec2e 100644
--- a/test/e2e/run_userns_test.go
+++ b/test/e2e/run_userns_test.go
@@ -22,7 +22,6 @@ var _ = Describe("Podman UserNS support", func() {
)
BeforeEach(func() {
- Skip(v2fail)
if os.Getenv("SKIP_USERNS") != "" {
Skip("Skip userns tests.")
}
diff --git a/vendor/github.com/rootless-containers/rootlesskit/pkg/port/builtin/parent/parent.go b/vendor/github.com/rootless-containers/rootlesskit/pkg/port/builtin/parent/parent.go
index 893bf1da9..8ffadd859 100644
--- a/vendor/github.com/rootless-containers/rootlesskit/pkg/port/builtin/parent/parent.go
+++ b/vendor/github.com/rootless-containers/rootlesskit/pkg/port/builtin/parent/parent.go
@@ -2,11 +2,14 @@ package parent
import (
"context"
+ "fmt"
"io"
"io/ioutil"
"net"
"os"
"path/filepath"
+ "strconv"
+ "strings"
"sync"
"syscall"
@@ -84,6 +87,39 @@ func (d *driver) RunParentDriver(initComplete chan struct{}, quit <-chan struct{
return nil
}
+func isEPERM(err error) bool {
+ k := "permission denied"
+ // As of Go 1.14, errors.Is(err, syscall.EPERM) does not seem to work for
+ // "listen tcp 0.0.0.0:80: bind: permission denied" error from net.ListenTCP().
+ return errors.Is(err, syscall.EPERM) || strings.Contains(err.Error(), k)
+}
+
+// annotateEPERM annotates origErr for human-readability
+func annotateEPERM(origErr error, spec port.Spec) error {
+ // Read "net.ipv4.ip_unprivileged_port_start" value (typically 1024)
+ // TODO: what for IPv6?
+ // NOTE: sync.Once should not be used here
+ b, e := ioutil.ReadFile("/proc/sys/net/ipv4/ip_unprivileged_port_start")
+ if e != nil {
+ return origErr
+ }
+ start, e := strconv.Atoi(strings.TrimSpace(string(b)))
+ if e != nil {
+ return origErr
+ }
+ if spec.ParentPort >= start {
+ // origErr is unrelated to ip_unprivileged_port_start
+ return origErr
+ }
+ text := fmt.Sprintf("cannot expose privileged port %d, you might need to add \"net.ipv4.ip_unprivileged_port_start=0\" (currently %d) to /etc/sysctl.conf", spec.ParentPort, start)
+ if filepath.Base(os.Args[0]) == "rootlesskit" {
+ // NOTE: The following sentence is appended only if Args[0] == "rootlesskit", because it does not apply to Podman (as of Podman v1.9).
+ // Podman launches the parent driver in the child user namespace (but in the parent network namespace), which disables the file capability.
+ text += ", or set CAP_NET_BIND_SERVICE on rootlesskit binary"
+ }
+ return errors.Wrap(origErr, text)
+}
+
func (d *driver) AddPort(ctx context.Context, spec port.Spec) (*port.Status, error) {
d.mu.Lock()
err := portutil.ValidatePortSpec(spec, d.ports)
@@ -106,6 +142,9 @@ func (d *driver) AddPort(ctx context.Context, spec port.Spec) (*port.Status, err
return nil, errors.New("spec was not validated?")
}
if err != nil {
+ if isEPERM(err) {
+ err = annotateEPERM(err, spec)
+ }
return nil, err
}
d.mu.Lock()
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 782a905a1..0a6d8ccd5 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -454,7 +454,7 @@ github.com/prometheus/common/model
github.com/prometheus/procfs
github.com/prometheus/procfs/internal/fs
github.com/prometheus/procfs/internal/util
-# github.com/rootless-containers/rootlesskit v0.9.3
+# github.com/rootless-containers/rootlesskit v0.9.4
github.com/rootless-containers/rootlesskit/pkg/msgutil
github.com/rootless-containers/rootlesskit/pkg/port
github.com/rootless-containers/rootlesskit/pkg/port/builtin