diff options
-rw-r--r-- | cmd/podman/stats.go | 6 | ||||
-rw-r--r-- | docs/podman-stats.1.md | 20 | ||||
-rw-r--r-- | libpod/container_api.go | 5 | ||||
-rw-r--r-- | libpod/runtime_pod_linux.go | 6 | ||||
-rw-r--r-- | pkg/cgroups/cgroups.go | 8 | ||||
-rw-r--r-- | test/e2e/exec_test.go | 19 |
6 files changed, 51 insertions, 13 deletions
diff --git a/cmd/podman/stats.go b/cmd/podman/stats.go index 2f696445e..25514ec75 100644 --- a/cmd/podman/stats.go +++ b/cmd/podman/stats.go @@ -134,9 +134,13 @@ func statsCmd(c *cliconfig.StatsValues) error { initialStats, err := ctr.GetContainerStats(&libpod.ContainerStats{}) if err != nil { // when doing "all", dont worry about containers that are not running - if c.All && errors.Cause(err) == define.ErrCtrRemoved || errors.Cause(err) == define.ErrNoSuchCtr || errors.Cause(err) == define.ErrCtrStateInvalid { + cause := errors.Cause(err) + if c.All && (cause == define.ErrCtrRemoved || cause == define.ErrNoSuchCtr || cause == define.ErrCtrStateInvalid) { continue } + if cause == cgroups.ErrCgroupV1Rootless { + err = cause + } return err } containerStats[ctr.ID()] = initialStats diff --git a/docs/podman-stats.1.md b/docs/podman-stats.1.md index c1a87f210..2f604644f 100644 --- a/docs/podman-stats.1.md +++ b/docs/podman-stats.1.md @@ -9,6 +9,10 @@ podman\-stats - Display a live stream of 1 or more containers' resource usage st ## DESCRIPTION Display a live stream of one or more containers' resource usage statistics +Note: Podman stats will not work in rootless environments that use CGroups V1. +Podman stats relies on CGroup information for statistics, and CGroup v1 is not +supported for rootless use cases. + ## OPTIONS **--all**, **-a** @@ -69,14 +73,14 @@ a9f807ffaacd frosty_hodgkin -- 3.092MB / 16.7GB 0.02% -- / -- -- # podman stats --no-stream --format=json a9f80 [ { - "id": "a9f807ffaacd", - "name": "frosty_hodgkin", - "cpu_percent": "--", - "mem_usage": "3.092MB / 16.7GB", - "mem_percent": "0.02%", - "netio": "-- / --", - "blocki": "-- / --", - "pids": "2" + "id": "a9f807ffaacd", + "name": "frosty_hodgkin", + "cpu_percent": "--", + "mem_usage": "3.092MB / 16.7GB", + "mem_percent": "0.02%", + "netio": "-- / --", + "blocki": "-- / --", + "pids": "2" } ] ``` diff --git a/libpod/container_api.go b/libpod/container_api.go index abcfcb271..9e59104cc 100644 --- a/libpod/container_api.go +++ b/libpod/container_api.go @@ -274,6 +274,11 @@ func (c *Container) Exec(tty, privileged bool, env, cmd []string, user, workDir } }() + // if the user is empty, we should inherit the user that the container is currently running with + if user == "" { + user = c.config.User + } + pid, attachChan, err := c.ociRuntime.execContainer(c, cmd, capList, env, tty, workDir, user, sessionID, streams, preserveFDs, resize, detachKeys) if err != nil { ec := define.ExecErrorCodeGeneric diff --git a/libpod/runtime_pod_linux.go b/libpod/runtime_pod_linux.go index 073c5054d..05866d05a 100644 --- a/libpod/runtime_pod_linux.go +++ b/libpod/runtime_pod_linux.go @@ -204,7 +204,7 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool) // Get the conmon CGroup conmonCgroupPath := filepath.Join(p.state.CgroupPath, "conmon") conmonCgroup, err := cgroups.Load(conmonCgroupPath) - if err != nil && err != cgroups.ErrCgroupDeleted { + if err != nil && err != cgroups.ErrCgroupDeleted && err != cgroups.ErrCgroupV1Rootless { removalErr = errors.Wrapf(err, "error retrieving pod %s conmon cgroup %s", p.ID(), conmonCgroupPath) } @@ -266,7 +266,7 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool) // hard - instead, just log errors. conmonCgroupPath := filepath.Join(p.state.CgroupPath, "conmon") conmonCgroup, err := cgroups.Load(conmonCgroupPath) - if err != nil && err != cgroups.ErrCgroupDeleted { + if err != nil && err != cgroups.ErrCgroupDeleted && err != cgroups.ErrCgroupV1Rootless { if removalErr == nil { removalErr = errors.Wrapf(err, "error retrieving pod %s conmon cgroup", p.ID()) } else { @@ -283,7 +283,7 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool) } } cgroup, err := cgroups.Load(p.state.CgroupPath) - if err != nil && err != cgroups.ErrCgroupDeleted { + if err != nil && err != cgroups.ErrCgroupDeleted && err != cgroups.ErrCgroupV1Rootless { if removalErr == nil { removalErr = errors.Wrapf(err, "error retrieving pod %s cgroup", p.ID()) } else { diff --git a/pkg/cgroups/cgroups.go b/pkg/cgroups/cgroups.go index 085718855..9711e8120 100644 --- a/pkg/cgroups/cgroups.go +++ b/pkg/cgroups/cgroups.go @@ -10,6 +10,7 @@ import ( "strconv" "strings" + "github.com/containers/libpod/pkg/rootless" systemdDbus "github.com/coreos/go-systemd/dbus" "github.com/godbus/dbus" spec "github.com/opencontainers/runtime-spec/specs-go" @@ -19,7 +20,9 @@ import ( var ( // ErrCgroupDeleted means the cgroup was deleted - ErrCgroupDeleted = errors.New("cgroups: cgroup deleted") + ErrCgroupDeleted = errors.New("cgroup deleted") + // ErrCgroupV1Rootless means the cgroup v1 were attempted to be used in rootless environmen + ErrCgroupV1Rootless = errors.New("no support for CGroups V1 in rootless environments") ) // CgroupControl controls a cgroup hierarchy @@ -339,6 +342,9 @@ func Load(path string) (*CgroupControl, error) { p := control.getCgroupv1Path(name) if _, err := os.Stat(p); err != nil { if os.IsNotExist(err) { + if rootless.IsRootless() { + return nil, ErrCgroupV1Rootless + } // compatible with the error code // used by containerd/cgroups return nil, ErrCgroupDeleted diff --git a/test/e2e/exec_test.go b/test/e2e/exec_test.go index ac727f9bc..f3190978c 100644 --- a/test/e2e/exec_test.go +++ b/test/e2e/exec_test.go @@ -146,6 +146,25 @@ var _ = Describe("Podman exec", func() { Expect(session2.OutputToString()).To(Equal(testUser)) }) + It("podman exec with user from run", func() { + testUser := "guest" + setup := podmanTest.Podman([]string{"run", "--user", testUser, "-d", ALPINE, "top"}) + setup.WaitWithDefaultTimeout() + Expect(setup.ExitCode()).To(Equal(0)) + ctrID := setup.OutputToString() + + session := podmanTest.Podman([]string{"exec", ctrID, "whoami"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(session.OutputToString()).To(ContainSubstring(testUser)) + + overrideUser := "root" + session = podmanTest.Podman([]string{"exec", "--user", overrideUser, ctrID, "whoami"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(session.OutputToString()).To(ContainSubstring(overrideUser)) + }) + It("podman exec simple working directory test", func() { setup := podmanTest.RunTopContainer("test1") setup.WaitWithDefaultTimeout() |