From 1fa4e45a950338b92cacc60abaafa909155d7a73 Mon Sep 17 00:00:00 2001 From: Daniel J Walsh Date: Mon, 10 Apr 2023 13:50:10 -0400 Subject: [PATCH] Return title fields as a list Podman is attempting to split the headers returned by the ps command into a list of headers. Problem is that some headers are multi-word, and headers are not guaranteed to be split via a tab. This PR splits the headers bases on white space, and for the select group of CAPS headers which are multi-word, combines them back together. Fixes: https://github.com/containers/podman/issues/17524 Signed-off-by: Daniel J Walsh --- pkg/api/handlers/compat/containers_top.go | 5 +++-- pkg/api/handlers/libpod/pods.go | 2 +- pkg/api/handlers/utils/containers.go | 21 +++++++++++++++++++++ test/apiv2/20-containers.at | 8 ++++++++ 4 files changed, 33 insertions(+), 3 deletions(-) diff --git a/pkg/api/handlers/compat/containers_top.go b/pkg/api/handlers/compat/containers_top.go index 9f598cd732..69e4160430 100644 --- a/pkg/api/handlers/compat/containers_top.go +++ b/pkg/api/handlers/compat/containers_top.go @@ -63,7 +63,7 @@ loop: // break out of for/select infinite` loop case <-r.Context().Done(): break loop default: - output, err := c.Top([]string{query.PsArgs}) + output, err := c.Top(strings.Split(query.PsArgs, ",")) if err != nil { logrus.Infof("Error from %s %q : %v", r.Method, r.URL, err) break loop @@ -71,7 +71,8 @@ loop: // break out of for/select infinite` loop if len(output) > 0 { body := handlers.ContainerTopOKBody{} - body.Titles = strings.Split(output[0], "\t") + body.Titles = utils.PSTitles(output[0]) + for i := range body.Titles { body.Titles[i] = strings.TrimSpace(body.Titles[i]) } diff --git a/pkg/api/handlers/libpod/pods.go b/pkg/api/handlers/libpod/pods.go index c39b9ee2ff..43acebb6cb 100644 --- a/pkg/api/handlers/libpod/pods.go +++ b/pkg/api/handlers/libpod/pods.go @@ -413,7 +413,7 @@ loop: // break out of for/select infinite` loop if len(output) > 0 { body := handlers.PodTopOKBody{} - body.Titles = strings.Split(output[0], "\t") + body.Titles = utils.PSTitles(output[0]) for i := range body.Titles { body.Titles[i] = strings.TrimSpace(body.Titles[i]) } diff --git a/pkg/api/handlers/utils/containers.go b/pkg/api/handlers/utils/containers.go index 3df7218ad2..798dd8ff65 100644 --- a/pkg/api/handlers/utils/containers.go +++ b/pkg/api/handlers/utils/containers.go @@ -6,6 +6,7 @@ import ( "fmt" "net/http" "strconv" + "strings" "time" "github.com/containers/podman/v4/libpod/events" @@ -238,3 +239,23 @@ func containerExists(ctx context.Context, name string) (bool, error) { } return ctrExistRep.Value, nil } + +// PSTitles merges CAPS headers from ps output. All PS headers are single words, except for +// CAPS. Function compines CAP Headers into single field separated by a space. +func PSTitles(output string) []string { + var titles []string + + for _, title := range strings.Fields(output) { + switch title { + case "AMBIENT", "INHERITED", "PERMITTED", "EFFECTIVE", "BOUNDING": + { + titles = append(titles, title+" CAPS") + } + case "CAPS": + continue + default: + titles = append(titles, title) + } + } + return titles +} diff --git a/test/apiv2/20-containers.at b/test/apiv2/20-containers.at index 650c67cfd1..7cfe161de4 100644 --- a/test/apiv2/20-containers.at +++ b/test/apiv2/20-containers.at @@ -121,6 +121,14 @@ if root; then .memory_stats.limit=536870912 \ .id~[0-9a-f]\\{64\\} + t GET containers/$CTRNAME/top?stream=false 200 \ + .Titles='[ + "PID", + "USER", + "TIME", + "COMMAND" +]' + podman rm -f $CTRNAME fi