summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/podman/top.go4
-rw-r--r--libpod/container_top.go54
-rw-r--r--test/e2e/top_test.go16
3 files changed, 68 insertions, 6 deletions
diff --git a/cmd/podman/top.go b/cmd/podman/top.go
index 6aff25a71..5ff3b6643 100644
--- a/cmd/podman/top.go
+++ b/cmd/podman/top.go
@@ -70,11 +70,11 @@ func topCmd(c *cli.Context) error {
psArgs = append(psArgs, psOpts...)
- results, err := container.GetContainerPidInformation(psArgs)
+ psOutput, err := container.GetContainerPidInformation(psArgs)
if err != nil {
return err
}
- for _, line := range results {
+ for _, line := range psOutput {
fmt.Println(line)
}
return nil
diff --git a/libpod/container_top.go b/libpod/container_top.go
index 3eb484acd..241e3a3e7 100644
--- a/libpod/container_top.go
+++ b/libpod/container_top.go
@@ -38,7 +38,7 @@ func (c *Container) getContainerPids() ([]string, error) {
}
// GetContainerPidInformation calls ps with the appropriate options and returns
-// the results as a string
+// the results as a string and the container's PIDs as a []string
func (c *Container) GetContainerPidInformation(args []string) ([]string, error) {
if !c.locked {
c.lock.Lock()
@@ -57,5 +57,55 @@ func (c *Container) GetContainerPidInformation(args []string) ([]string, error)
if err != nil {
return []string{}, errors.Wrapf(err, "unable to obtain information about pids")
}
- return strings.Split(results, "\n"), nil
+
+ filteredOutput, err := filterPids(results, pids)
+ if err != nil {
+ return []string{}, err
+ }
+ return filteredOutput, nil
+}
+
+func filterPids(psOutput string, pids []string) ([]string, error) {
+ var output []string
+ results := strings.Split(psOutput, "\n")
+ // The headers are in the first line of the results
+ headers := fieldsASCII(results[0])
+ // We need to make sure PID in headers, so that we can filter
+ // Pids that don't belong.
+
+ // append the headers back in
+ output = append(output, results[0])
+
+ pidIndex := -1
+ for i, header := range headers {
+ if header == "PID" {
+ pidIndex = i
+ }
+ }
+ if pidIndex == -1 {
+ return []string{}, errors.Errorf("unable to find PID field in ps output. try a different set of ps arguments")
+ }
+ for _, l := range results[1:] {
+ if l == "" {
+ continue
+ }
+ cols := fieldsASCII(l)
+ pid := cols[pidIndex]
+ if StringInSlice(pid, pids) {
+ output = append(output, l)
+ }
+ }
+ return output, nil
+}
+
+// Detects ascii whitespaces
+func fieldsASCII(s string) []string {
+ fn := func(r rune) bool {
+ switch r {
+ case '\t', '\n', '\f', '\r', ' ':
+ return true
+ }
+ return false
+ }
+ return strings.FieldsFunc(s, fn)
}
diff --git a/test/e2e/top_test.go b/test/e2e/top_test.go
index d4438293b..410803353 100644
--- a/test/e2e/top_test.go
+++ b/test/e2e/top_test.go
@@ -59,14 +59,26 @@ var _ = Describe("Podman top", func() {
Expect(len(result.OutputToStringArray())).To(BeNumerically(">", 1))
})
- It("podman top on non-running container", func() {
+ It("podman top with options", func() {
session := podmanTest.Podman([]string{"run", "-d", ALPINE, "top", "-d", "2"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- result := podmanTest.Podman([]string{"top", session.OutputToString(), "-o", "fuser,f,comm,label"})
+ result := podmanTest.Podman([]string{"top", session.OutputToString(), "-o", "pid,fuser,f,comm,label"})
result.WaitWithDefaultTimeout()
Expect(result.ExitCode()).To(Equal(0))
Expect(len(result.OutputToStringArray())).To(BeNumerically(">", 1))
})
+
+ It("podman top on container invalid options", func() {
+ sleep := podmanTest.RunSleepContainer("")
+ sleep.WaitWithDefaultTimeout()
+ Expect(sleep.ExitCode()).To(Equal(0))
+ cid := sleep.OutputToString()
+
+ result := podmanTest.Podman([]string{"top", cid, "-o time"})
+ result.WaitWithDefaultTimeout()
+ Expect(result.ExitCode()).To(Equal(125))
+ })
+
})