From c4dd7c5813078acbe871aae37644bfff3163d160 Mon Sep 17 00:00:00 2001
From: baude <bbaude@redhat.com>
Date: Wed, 24 Apr 2019 15:57:37 -0500
Subject: enable podman remote top

add the ability for the remote client to display a container's running
processes.

Signed-off-by: baude <bbaude@redhat.com>
---
 cmd/podman/commands.go               |  2 --
 cmd/podman/container.go              |  1 +
 cmd/podman/main.go                   |  1 +
 cmd/podman/top.go                    | 28 +++-------------------------
 cmd/podman/varlink/io.podman.varlink |  2 ++
 libpod/container_top_linux.go        | 14 ++++++++++++++
 pkg/adapter/containers.go            | 20 ++++++++++++++++++++
 pkg/adapter/containers_remote.go     | 20 ++++++++++++++++++++
 pkg/varlinkapi/containers.go         | 13 +++++++++++++
 9 files changed, 74 insertions(+), 27 deletions(-)

diff --git a/cmd/podman/commands.go b/cmd/podman/commands.go
index 7680d6df2..c43ecec5c 100644
--- a/cmd/podman/commands.go
+++ b/cmd/podman/commands.go
@@ -21,7 +21,6 @@ func getMainCommands() []*cobra.Command {
 		_refreshCommand,
 		_searchCommand,
 		_statsCommand,
-		_topCommand,
 	}
 
 	if len(_varlinkCommand.Use) > 0 {
@@ -53,7 +52,6 @@ func getContainerSubCommands() []*cobra.Command {
 		_runlabelCommand,
 		_statsCommand,
 		_stopCommand,
-		_topCommand,
 		_umountCommand,
 	}
 }
diff --git a/cmd/podman/container.go b/cmd/podman/container.go
index 28e0f0e4a..52152d50e 100644
--- a/cmd/podman/container.go
+++ b/cmd/podman/container.go
@@ -64,6 +64,7 @@ var (
 		_runCommand,
 		_rmCommand,
 		_startCommand,
+		_topCommand,
 		_unpauseCommand,
 		_waitCommand,
 	}
diff --git a/cmd/podman/main.go b/cmd/podman/main.go
index 392dfe542..a0f1cf401 100644
--- a/cmd/podman/main.go
+++ b/cmd/podman/main.go
@@ -57,6 +57,7 @@ var mainCommands = []*cobra.Command{
 	_saveCommand,
 	_stopCommand,
 	_tagCommand,
+	_topCommand,
 	_umountCommand,
 	_unpauseCommand,
 	_versionCommand,
diff --git a/cmd/podman/top.go b/cmd/podman/top.go
index 0b7da64a8..f1f594ebf 100644
--- a/cmd/podman/top.go
+++ b/cmd/podman/top.go
@@ -7,8 +7,8 @@ import (
 	"text/tabwriter"
 
 	"github.com/containers/libpod/cmd/podman/cliconfig"
-	"github.com/containers/libpod/cmd/podman/libpodruntime"
 	"github.com/containers/libpod/libpod"
+	"github.com/containers/libpod/pkg/adapter"
 	"github.com/pkg/errors"
 	"github.com/spf13/cobra"
 )
@@ -60,7 +60,6 @@ func init() {
 }
 
 func topCmd(c *cliconfig.TopValues) error {
-	var container *libpod.Container
 	var err error
 	args := c.InputArgs
 
@@ -77,37 +76,16 @@ func topCmd(c *cliconfig.TopValues) error {
 		return errors.Errorf("you must provide the name or id of a running container")
 	}
 
-	runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
+	runtime, err := adapter.GetRuntime(&c.PodmanCommand)
 	if err != nil {
 		return errors.Wrapf(err, "error creating libpod runtime")
 	}
 	defer runtime.Shutdown(false)
 
-	var descriptors []string
-	if c.Latest {
-		descriptors = args
-		container, err = runtime.GetLatestContainer()
-	} else {
-		descriptors = args[1:]
-		container, err = runtime.LookupContainer(args[0])
-	}
-
-	if err != nil {
-		return errors.Wrapf(err, "unable to lookup requested container")
-	}
-
-	conStat, err := container.State()
-	if err != nil {
-		return errors.Wrapf(err, "unable to look up state for %s", args[0])
-	}
-	if conStat != libpod.ContainerStateRunning {
-		return errors.Errorf("top can only be used on running containers")
-	}
-	psOutput, err := container.GetContainerPidInformation(descriptors)
+	psOutput, err := runtime.Top(c)
 	if err != nil {
 		return err
 	}
-
 	w := tabwriter.NewWriter(os.Stdout, 5, 1, 3, ' ', 0)
 	for _, proc := range psOutput {
 		fmt.Fprintln(w, proc)
diff --git a/cmd/podman/varlink/io.podman.varlink b/cmd/podman/varlink/io.podman.varlink
index 1fde72164..17179d665 100644
--- a/cmd/podman/varlink/io.podman.varlink
+++ b/cmd/podman/varlink/io.podman.varlink
@@ -524,6 +524,8 @@ method Ps(opts: PsOpts) -> (containers: []PsContainer)
 
 method GetContainersByStatus(status: []string) -> (containerS: []Container)
 
+method Top (nameOrID: string, descriptors: []string) -> (top: []string)
+
 # GetContainer returns information about a single container.  If a container
 # with the given id doesn't exist, a [ContainerNotFound](#ContainerNotFound)
 # error will be returned.  See also [ListContainers](ListContainers) and
diff --git a/libpod/container_top_linux.go b/libpod/container_top_linux.go
index 9b0f156b5..b370495fe 100644
--- a/libpod/container_top_linux.go
+++ b/libpod/container_top_linux.go
@@ -7,8 +7,22 @@ import (
 	"strings"
 
 	"github.com/containers/psgo"
+	"github.com/pkg/errors"
 )
 
+// Top gathers statistics about the running processes in a container. It returns a
+// []string for output
+func (c *Container) Top(descriptors []string) ([]string, error) {
+	conStat, err := c.State()
+	if err != nil {
+		return nil, errors.Wrapf(err, "unable to look up state for %s", c.ID())
+	}
+	if conStat != ContainerStateRunning {
+		return nil, errors.Errorf("top can only be used on running containers")
+	}
+	return c.GetContainerPidInformation(descriptors)
+}
+
 // GetContainerPidInformation returns process-related data of all processes in
 // the container.  The output data can be controlled via the `descriptors`
 // argument which expects format descriptors and supports all AIXformat
diff --git a/pkg/adapter/containers.go b/pkg/adapter/containers.go
index 8481a0cec..9f5fc7e65 100644
--- a/pkg/adapter/containers.go
+++ b/pkg/adapter/containers.go
@@ -766,3 +766,23 @@ func (r *LocalRuntime) Restart(ctx context.Context, c *cliconfig.RestartValues)
 	}
 	return pool.Run()
 }
+
+// Top display the running processes of a container
+func (r *LocalRuntime) Top(cli *cliconfig.TopValues) ([]string, error) {
+	var (
+		descriptors []string
+		container   *libpod.Container
+		err         error
+	)
+	if cli.Latest {
+		descriptors = cli.InputArgs
+		container, err = r.Runtime.GetLatestContainer()
+	} else {
+		descriptors = cli.InputArgs[1:]
+		container, err = r.Runtime.LookupContainer(cli.InputArgs[0])
+	}
+	if err != nil {
+		return nil, errors.Wrapf(err, "unable to lookup requested container")
+	}
+	return container.Top(descriptors)
+}
diff --git a/pkg/adapter/containers_remote.go b/pkg/adapter/containers_remote.go
index e8f221eaf..ef6d0efe1 100644
--- a/pkg/adapter/containers_remote.go
+++ b/pkg/adapter/containers_remote.go
@@ -832,3 +832,23 @@ func (r *LocalRuntime) Restart(ctx context.Context, c *cliconfig.RestartValues)
 	}
 	return ok, failures, nil
 }
+
+// Top display the running processes of a container
+func (r *LocalRuntime) Top(cli *cliconfig.TopValues) ([]string, error) {
+	var (
+		ctr         *Container
+		err         error
+		descriptors []string
+	)
+	if cli.Latest {
+		ctr, err = r.GetLatestContainer()
+		descriptors = cli.InputArgs
+	} else {
+		ctr, err = r.LookupContainer(cli.InputArgs[0])
+		descriptors = cli.InputArgs[1:]
+	}
+	if err != nil {
+		return nil, err
+	}
+	return iopodman.Top().Call(r.Conn, ctr.ID(), descriptors)
+}
diff --git a/pkg/varlinkapi/containers.go b/pkg/varlinkapi/containers.go
index 237407050..872c7bc26 100644
--- a/pkg/varlinkapi/containers.go
+++ b/pkg/varlinkapi/containers.go
@@ -733,3 +733,16 @@ func newPodmanLogLine(line *libpod.LogLine) iopodman.LogLine {
 		Cid:          line.CID,
 	}
 }
+
+// Top displays information about a container's running processes
+func (i *LibpodAPI) Top(call iopodman.VarlinkCall, nameOrID string, descriptors []string) error {
+	ctr, err := i.Runtime.LookupContainer(nameOrID)
+	if err != nil {
+		return call.ReplyContainerNotFound(ctr.ID(), err.Error())
+	}
+	topInfo, err := ctr.Top(descriptors)
+	if err != nil {
+		return call.ReplyErrorOccurred(err.Error())
+	}
+	return call.ReplyTop(topInfo)
+}
-- 
cgit v1.2.3-54-g00ecf