From e04668c8ca5056e8704fa110fd79ae19e4ef7adb Mon Sep 17 00:00:00 2001 From: Matt Heon Date: Tue, 17 Sep 2024 11:34:22 -0400 Subject: [PATCH] Match output of Compat Top API to Docker We were only splitting on tabs, not spaces, so we returned just a single line most of the time, not an array of the fields in the output of `ps`. Unfortunately, some of these fields are allowed to contain spaces themselves, which makes things complicated, but we got lucky in that Docker took the simplest possible solution and just assumed that only one field would contain spaces and it would always be the last one, which is easy enough to duplicate on our end. Fixes #23981 Signed-off-by: Matt Heon --- pkg/api/handlers/compat/containers_top.go | 19 +++++++++++++++---- test/apiv2/20-containers.at | 8 ++++++++ 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/pkg/api/handlers/compat/containers_top.go b/pkg/api/handlers/compat/containers_top.go index 9653906277..8befc6b944 100644 --- a/pkg/api/handlers/compat/containers_top.go +++ b/pkg/api/handlers/compat/containers_top.go @@ -88,11 +88,22 @@ loop: // break out of for/select infinite` loop } for _, line := range output[1:] { - process := strings.Split(line, "\t") - for i := range process { - process[i] = strings.TrimSpace(process[i]) + process := strings.FieldsFunc(line, func(r rune) bool { + return r == ' ' || r == '\t' + }) + if len(process) > len(body.Titles) { + // Docker assumes the last entry is *always* command + // Which can include spaces. + // All other descriptors are assumed to NOT include extra spaces. + // So combine any extras. + cmd := strings.Join(process[len(body.Titles)-1:], " ") + var finalProc []string + finalProc = append(finalProc, process[:len(body.Titles)-1]...) + finalProc = append(finalProc, cmd) + body.Processes = append(body.Processes, finalProc) + } else { + body.Processes = append(body.Processes, process) } - body.Processes = append(body.Processes, process) } if err := encoder.Encode(body); err != nil { diff --git a/test/apiv2/20-containers.at b/test/apiv2/20-containers.at index 7aca66797f..011c8f289b 100644 --- a/test/apiv2/20-containers.at +++ b/test/apiv2/20-containers.at @@ -144,6 +144,14 @@ if root; then podman rm -f $CTRNAME fi +# Verify that compat top endpoint combines multi-entry COMMAND lines +CTRNAME=testtopproc +podman run --name $CTRNAME -d $IMAGE sleep 25 +t GET containers/$CTRNAME/top?stream=false 200 \ + .Processes.[0].[6]="00:00:00" \ + .Processes.[0].[7]="sleep 25" +podman rm -f -t0 $CTRNAME + CTRNAME=test123 podman run --name $CTRNAME -d $IMAGE top t GET libpod/containers/$CTRNAME/top?ps_args=--invalid 500 \