mirror of
https://github.com/containers/podman.git
synced 2025-06-03 03:07:56 +08:00
podman-remote pod top|stats
this is the final enablement for the pod subcommand. it includes the ability to run podman-remote pod top and stats. Signed-off-by: baude <bbaude@redhat.com>
This commit is contained in:
@ -85,14 +85,6 @@ func getContainerSubCommands() []*cobra.Command {
|
||||
}
|
||||
}
|
||||
|
||||
// Commands that the local client implements
|
||||
func getPodSubCommands() []*cobra.Command {
|
||||
return []*cobra.Command{
|
||||
_podStatsCommand,
|
||||
_podTopCommand,
|
||||
}
|
||||
}
|
||||
|
||||
func getGenerateSubCommands() []*cobra.Command {
|
||||
return []*cobra.Command{
|
||||
_containerKubeCommand,
|
||||
|
@ -28,11 +28,6 @@ func getContainerSubCommands() []*cobra.Command {
|
||||
return []*cobra.Command{}
|
||||
}
|
||||
|
||||
// commands that only the remoteclient implements
|
||||
func getPodSubCommands() []*cobra.Command {
|
||||
return []*cobra.Command{}
|
||||
}
|
||||
|
||||
// commands that only the remoteclient implements
|
||||
func getGenerateSubCommands() []*cobra.Command {
|
||||
return []*cobra.Command{}
|
||||
|
@ -29,12 +29,13 @@ var podSubCommands = []*cobra.Command{
|
||||
_podRestartCommand,
|
||||
_podRmCommand,
|
||||
_podStartCommand,
|
||||
_podStatsCommand,
|
||||
_podStopCommand,
|
||||
_podTopCommand,
|
||||
_podUnpauseCommand,
|
||||
}
|
||||
|
||||
func init() {
|
||||
podCommand.AddCommand(podSubCommands...)
|
||||
podCommand.AddCommand(getPodSubCommands()...)
|
||||
podCommand.SetUsageTemplate(UsageTemplate())
|
||||
}
|
||||
|
@ -13,8 +13,8 @@ import (
|
||||
tm "github.com/buger/goterm"
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/formats"
|
||||
"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"
|
||||
"github.com/ulule/deepcopier"
|
||||
@ -51,10 +51,6 @@ func init() {
|
||||
}
|
||||
|
||||
func podStatsCmd(c *cliconfig.PodStatsValues) error {
|
||||
var (
|
||||
podFunc func() ([]*libpod.Pod, error)
|
||||
)
|
||||
|
||||
format := c.Format
|
||||
all := c.All
|
||||
latest := c.Latest
|
||||
@ -76,7 +72,7 @@ func podStatsCmd(c *cliconfig.PodStatsValues) error {
|
||||
all = true
|
||||
}
|
||||
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
runtime, err := adapter.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get runtime")
|
||||
}
|
||||
@ -87,29 +83,12 @@ func podStatsCmd(c *cliconfig.PodStatsValues) error {
|
||||
times = 1
|
||||
}
|
||||
|
||||
if len(c.InputArgs) > 0 {
|
||||
podFunc = func() ([]*libpod.Pod, error) { return getPodsByList(c.InputArgs, runtime) }
|
||||
} else if latest {
|
||||
podFunc = func() ([]*libpod.Pod, error) {
|
||||
latestPod, err := runtime.GetLatestPod()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return []*libpod.Pod{latestPod}, err
|
||||
}
|
||||
} else if all {
|
||||
podFunc = runtime.GetAllPods
|
||||
} else {
|
||||
podFunc = runtime.GetRunningPods
|
||||
}
|
||||
|
||||
pods, err := podFunc()
|
||||
pods, err := runtime.GetStatPods(c)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "unable to get a list of pods")
|
||||
}
|
||||
|
||||
// First we need to get an initial pass of pod/ctr stats (these are not printed)
|
||||
var podStats []*libpod.PodContainerStats
|
||||
var podStats []*adapter.PodContainerStats
|
||||
for _, p := range pods {
|
||||
cons, err := p.AllContainersByID()
|
||||
if err != nil {
|
||||
@ -120,7 +99,7 @@ func podStatsCmd(c *cliconfig.PodStatsValues) error {
|
||||
for _, c := range cons {
|
||||
emptyStats[c] = &libpod.ContainerStats{}
|
||||
}
|
||||
ps := libpod.PodContainerStats{
|
||||
ps := adapter.PodContainerStats{
|
||||
Pod: p,
|
||||
ContainerStats: emptyStats,
|
||||
}
|
||||
@ -128,10 +107,10 @@ func podStatsCmd(c *cliconfig.PodStatsValues) error {
|
||||
}
|
||||
|
||||
// Create empty container stat results for our first pass
|
||||
var previousPodStats []*libpod.PodContainerStats
|
||||
var previousPodStats []*adapter.PodContainerStats
|
||||
for _, p := range pods {
|
||||
cs := make(map[string]*libpod.ContainerStats)
|
||||
pcs := libpod.PodContainerStats{
|
||||
pcs := adapter.PodContainerStats{
|
||||
Pod: p,
|
||||
ContainerStats: cs,
|
||||
}
|
||||
@ -164,7 +143,7 @@ func podStatsCmd(c *cliconfig.PodStatsValues) error {
|
||||
}
|
||||
|
||||
for i := 0; i < times; i += step {
|
||||
var newStats []*libpod.PodContainerStats
|
||||
var newStats []*adapter.PodContainerStats
|
||||
for _, p := range pods {
|
||||
prevStat := getPreviousPodContainerStats(p.ID(), previousPodStats)
|
||||
newPodStats, err := p.GetPodStats(prevStat)
|
||||
@ -174,7 +153,7 @@ func podStatsCmd(c *cliconfig.PodStatsValues) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
newPod := libpod.PodContainerStats{
|
||||
newPod := adapter.PodContainerStats{
|
||||
Pod: p,
|
||||
ContainerStats: newPodStats,
|
||||
}
|
||||
@ -202,7 +181,7 @@ func podStatsCmd(c *cliconfig.PodStatsValues) error {
|
||||
time.Sleep(time.Second)
|
||||
previousPodStats := new([]*libpod.PodContainerStats)
|
||||
deepcopier.Copy(newStats).To(previousPodStats)
|
||||
pods, err = podFunc()
|
||||
pods, err = runtime.GetStatPods(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -211,7 +190,7 @@ func podStatsCmd(c *cliconfig.PodStatsValues) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func podContainerStatsToPodStatOut(stats []*libpod.PodContainerStats) []*podStatOut {
|
||||
func podContainerStatsToPodStatOut(stats []*adapter.PodContainerStats) []*podStatOut {
|
||||
var out []*podStatOut
|
||||
for _, p := range stats {
|
||||
for _, c := range p.ContainerStats {
|
||||
@ -295,7 +274,7 @@ func outputToStdOut(stats []*podStatOut) {
|
||||
w.Flush()
|
||||
}
|
||||
|
||||
func getPreviousPodContainerStats(podID string, prev []*libpod.PodContainerStats) map[string]*libpod.ContainerStats {
|
||||
func getPreviousPodContainerStats(podID string, prev []*adapter.PodContainerStats) map[string]*libpod.ContainerStats {
|
||||
for _, p := range prev {
|
||||
if podID == p.Pod.ID() {
|
||||
return p.ContainerStats
|
||||
@ -304,7 +283,7 @@ func getPreviousPodContainerStats(podID string, prev []*libpod.PodContainerStats
|
||||
return map[string]*libpod.ContainerStats{}
|
||||
}
|
||||
|
||||
func outputJson(stats []*libpod.PodContainerStats) error {
|
||||
func outputJson(stats []*adapter.PodContainerStats) error {
|
||||
b, err := json.MarshalIndent(&stats, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -2,13 +2,12 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/containers/libpod/pkg/adapter"
|
||||
"os"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/containers/libpod/cmd/podman/shared"
|
||||
"github.com/containers/libpod/libpod"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
@ -50,8 +49,9 @@ func init() {
|
||||
}
|
||||
|
||||
func podTopCmd(c *cliconfig.PodTopValues) error {
|
||||
var pod *libpod.Pod
|
||||
var err error
|
||||
var (
|
||||
descriptors []string
|
||||
)
|
||||
args := c.InputArgs
|
||||
|
||||
if c.ListDescriptors {
|
||||
@ -67,39 +67,22 @@ func podTopCmd(c *cliconfig.PodTopValues) error {
|
||||
return errors.Errorf("you must provide the name or id of a running pod")
|
||||
}
|
||||
|
||||
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
|
||||
pod, err = runtime.GetLatestPod()
|
||||
} else {
|
||||
descriptors = args[1:]
|
||||
pod, err = runtime.LookupPod(args[0])
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "unable to lookup requested container")
|
||||
}
|
||||
|
||||
podStatus, err := shared.GetPodStatus(pod)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if podStatus != "Running" {
|
||||
return errors.Errorf("pod top can only be used on pods with at least one running container")
|
||||
}
|
||||
|
||||
psOutput, err := pod.GetPodPidInformation(descriptors)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
w := tabwriter.NewWriter(os.Stdout, 5, 1, 3, ' ', 0)
|
||||
psOutput, err := runtime.PodTop(c, descriptors)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, proc := range psOutput {
|
||||
fmt.Fprintln(w, proc)
|
||||
}
|
||||
|
@ -549,6 +549,10 @@ method ExportContainer(name: string, path: string) -> (tarfile: string)
|
||||
# ~~~
|
||||
method GetContainerStats(name: string) -> (container: ContainerStats)
|
||||
|
||||
# GetContainerStatsWithHistory takes a previous set of container statistics and uses libpod functions
|
||||
# to calculate the containers statistics based on current and previous measurements.
|
||||
method GetContainerStatsWithHistory(previousStats: ContainerStats) -> (container: ContainerStats)
|
||||
|
||||
# This method has not be implemented yet.
|
||||
# method ResizeContainerTty() -> (notimplemented: NotImplemented)
|
||||
|
||||
@ -952,8 +956,7 @@ method RemovePod(name: string, force: bool) -> (pod: string)
|
||||
# This method has not be implemented yet.
|
||||
# method WaitPod() -> (notimplemented: NotImplemented)
|
||||
|
||||
# This method has not been implemented yet.
|
||||
# method TopPod() -> (notimplemented: NotImplemented)
|
||||
method TopPod(pod: string, latest: bool, descriptors: []string) -> (stats: []string)
|
||||
|
||||
# GetPodStats takes the name or ID of a pod and returns a pod name and slice of ContainerStats structure which
|
||||
# contains attributes like memory and cpu usage. If the pod cannot be found, a [PodNotFound](#PodNotFound)
|
||||
|
@ -4,6 +4,7 @@ package adapter
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/pkg/errors"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
@ -17,6 +18,13 @@ type Pod struct {
|
||||
*libpod.Pod
|
||||
}
|
||||
|
||||
// PodContainerStats is struct containing an adapter Pod and a libpod
|
||||
// ContainerStats and is used primarily for outputing pod stats.
|
||||
type PodContainerStats struct {
|
||||
Pod *Pod
|
||||
ContainerStats map[string]*libpod.ContainerStats
|
||||
}
|
||||
|
||||
// RemovePods ...
|
||||
func (r *LocalRuntime) RemovePods(ctx context.Context, cli *cliconfig.PodRmValues) ([]string, []error) {
|
||||
var (
|
||||
@ -321,3 +329,55 @@ func (r *LocalRuntime) RestartPods(ctx context.Context, c *cliconfig.PodRestartV
|
||||
return restartIDs, containerErrors, restartErrors
|
||||
|
||||
}
|
||||
|
||||
// PodTop is a wrapper function to call GetPodPidInformation in libpod and return its results
|
||||
// for output
|
||||
func (r *LocalRuntime) PodTop(c *cliconfig.PodTopValues, descriptors []string) ([]string, error) {
|
||||
var (
|
||||
pod *Pod
|
||||
err error
|
||||
)
|
||||
|
||||
if c.Latest {
|
||||
pod, err = r.GetLatestPod()
|
||||
} else {
|
||||
pod, err = r.LookupPod(c.InputArgs[0])
|
||||
}
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "unable to lookup requested container")
|
||||
}
|
||||
podStatus, err := pod.GetPodStatus()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "unable to get status for pod %s", pod.ID())
|
||||
}
|
||||
if podStatus != "Running" {
|
||||
return nil, errors.Errorf("pod top can only be used on pods with at least one running container")
|
||||
}
|
||||
return pod.GetPodPidInformation(descriptors)
|
||||
}
|
||||
|
||||
// GetStatPods returns pods for use in pod stats
|
||||
func (r *LocalRuntime) GetStatPods(c *cliconfig.PodStatsValues) ([]*Pod, error) {
|
||||
var (
|
||||
adapterPods []*Pod
|
||||
pods []*libpod.Pod
|
||||
err error
|
||||
)
|
||||
|
||||
if len(c.InputArgs) > 0 || c.Latest || c.All {
|
||||
pods, err = shortcuts.GetPodsByContext(c.All, c.Latest, c.InputArgs, r.Runtime)
|
||||
} else {
|
||||
pods, err = r.Runtime.GetRunningPods()
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// convert libpod pods to adapter pods
|
||||
for _, p := range pods {
|
||||
adapterPod := Pod{
|
||||
p,
|
||||
}
|
||||
adapterPods = append(adapterPods, &adapterPod)
|
||||
}
|
||||
return adapterPods, nil
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ import (
|
||||
"github.com/containers/libpod/cmd/podman/shared"
|
||||
"github.com/containers/libpod/cmd/podman/varlink"
|
||||
"github.com/containers/libpod/libpod"
|
||||
"github.com/containers/libpod/pkg/varlinkapi"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/ulule/deepcopier"
|
||||
)
|
||||
@ -21,6 +22,13 @@ type Pod struct {
|
||||
remotepod
|
||||
}
|
||||
|
||||
// PodContainerStats is struct containing an adapter Pod and a libpod
|
||||
// ContainerStats and is used primarily for outputing pod stats.
|
||||
type PodContainerStats struct {
|
||||
Pod *Pod
|
||||
ContainerStats map[string]*libpod.ContainerStats
|
||||
}
|
||||
|
||||
type remotepod struct {
|
||||
config *libpod.PodConfig
|
||||
state *libpod.PodInspectState
|
||||
@ -399,3 +407,103 @@ func (r *LocalRuntime) RestartPods(ctx context.Context, c *cliconfig.PodRestartV
|
||||
}
|
||||
return restartIDs, nil, restartErrors
|
||||
}
|
||||
|
||||
// PodTop gets top statistics for a pod
|
||||
func (r *LocalRuntime) PodTop(c *cliconfig.PodTopValues, descriptors []string) ([]string, error) {
|
||||
var (
|
||||
latest bool
|
||||
podName string
|
||||
)
|
||||
if c.Latest {
|
||||
latest = true
|
||||
} else {
|
||||
podName = c.InputArgs[0]
|
||||
}
|
||||
return iopodman.TopPod().Call(r.Conn, podName, latest, descriptors)
|
||||
}
|
||||
|
||||
// GetStatPods returns pods for use in pod stats
|
||||
func (r *LocalRuntime) GetStatPods(c *cliconfig.PodStatsValues) ([]*Pod, error) {
|
||||
var (
|
||||
pods []*Pod
|
||||
err error
|
||||
podIDs []string
|
||||
running bool
|
||||
)
|
||||
|
||||
if len(c.InputArgs) > 0 || c.Latest || c.All {
|
||||
podIDs, err = iopodman.GetPodsByContext().Call(r.Conn, c.All, c.Latest, c.InputArgs)
|
||||
} else {
|
||||
podIDs, err = iopodman.GetPodsByContext().Call(r.Conn, true, false, []string{})
|
||||
running = true
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, p := range podIDs {
|
||||
pod, err := r.Inspect(p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if running {
|
||||
status, err := pod.GetPodStatus()
|
||||
if err != nil {
|
||||
// if we cannot get the status of the pod, skip and move on
|
||||
continue
|
||||
}
|
||||
if strings.ToUpper(status) != "RUNNING" {
|
||||
// if the pod is not running, skip and move on as well
|
||||
continue
|
||||
}
|
||||
}
|
||||
pods = append(pods, pod)
|
||||
}
|
||||
return pods, nil
|
||||
}
|
||||
|
||||
// GetPodStats returns the stats for each of its containers
|
||||
func (p *Pod) GetPodStats(previousContainerStats map[string]*libpod.ContainerStats) (map[string]*libpod.ContainerStats, error) {
|
||||
var (
|
||||
ok bool
|
||||
prevStat *libpod.ContainerStats
|
||||
)
|
||||
newContainerStats := make(map[string]*libpod.ContainerStats)
|
||||
containers, err := p.AllContainers()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, c := range containers {
|
||||
if prevStat, ok = previousContainerStats[c.ID()]; !ok {
|
||||
prevStat = &libpod.ContainerStats{ContainerID: c.ID()}
|
||||
}
|
||||
cStats := iopodman.ContainerStats{
|
||||
Id: prevStat.ContainerID,
|
||||
Name: prevStat.Name,
|
||||
Cpu: prevStat.CPU,
|
||||
Cpu_nano: int64(prevStat.CPUNano),
|
||||
System_nano: int64(prevStat.SystemNano),
|
||||
Mem_usage: int64(prevStat.MemUsage),
|
||||
Mem_limit: int64(prevStat.MemLimit),
|
||||
Mem_perc: prevStat.MemPerc,
|
||||
Net_input: int64(prevStat.NetInput),
|
||||
Net_output: int64(prevStat.NetOutput),
|
||||
Block_input: int64(prevStat.BlockInput),
|
||||
Block_output: int64(prevStat.BlockOutput),
|
||||
Pids: int64(prevStat.PIDs),
|
||||
}
|
||||
stats, err := iopodman.GetContainerStatsWithHistory().Call(p.Runtime.Conn, cStats)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newStats := varlinkapi.ContainerStatsToLibpodContainerStats(stats)
|
||||
// If the container wasn't running, don't include it
|
||||
// but also suppress the error
|
||||
if err != nil && errors.Cause(err) != libpod.ErrCtrStateInvalid {
|
||||
return nil, err
|
||||
}
|
||||
if err == nil {
|
||||
newContainerStats[c.ID()] = &newStats
|
||||
}
|
||||
}
|
||||
return newContainerStats, nil
|
||||
}
|
||||
|
@ -552,3 +552,54 @@ func (i *LibpodAPI) ContainerStateData(call iopodman.VarlinkCall, name string) e
|
||||
}
|
||||
return call.ReplyContainerStateData(string(b))
|
||||
}
|
||||
|
||||
// GetContainerStatsWithHistory is a varlink endpoint that returns container stats based on current and
|
||||
// previous statistics
|
||||
func (i *LibpodAPI) GetContainerStatsWithHistory(call iopodman.VarlinkCall, prevStats iopodman.ContainerStats) error {
|
||||
con, err := i.Runtime.LookupContainer(prevStats.Id)
|
||||
if err != nil {
|
||||
return call.ReplyContainerNotFound(prevStats.Id, err.Error())
|
||||
}
|
||||
previousStats := ContainerStatsToLibpodContainerStats(prevStats)
|
||||
stats, err := con.GetContainerStats(&previousStats)
|
||||
if err != nil {
|
||||
return call.ReplyErrorOccurred(err.Error())
|
||||
}
|
||||
cStats := iopodman.ContainerStats{
|
||||
Id: stats.ContainerID,
|
||||
Name: stats.Name,
|
||||
Cpu: stats.CPU,
|
||||
Cpu_nano: int64(stats.CPUNano),
|
||||
System_nano: int64(stats.SystemNano),
|
||||
Mem_usage: int64(stats.MemUsage),
|
||||
Mem_limit: int64(stats.MemLimit),
|
||||
Mem_perc: stats.MemPerc,
|
||||
Net_input: int64(stats.NetInput),
|
||||
Net_output: int64(stats.NetOutput),
|
||||
Block_input: int64(stats.BlockInput),
|
||||
Block_output: int64(stats.BlockOutput),
|
||||
Pids: int64(stats.PIDs),
|
||||
}
|
||||
return call.ReplyGetContainerStatsWithHistory(cStats)
|
||||
}
|
||||
|
||||
// ContainerStatsToLibpodContainerStats converts the varlink containerstats to a libpod
|
||||
// container stats
|
||||
func ContainerStatsToLibpodContainerStats(stats iopodman.ContainerStats) libpod.ContainerStats {
|
||||
cstats := libpod.ContainerStats{
|
||||
ContainerID: stats.Id,
|
||||
Name: stats.Name,
|
||||
CPU: stats.Cpu,
|
||||
CPUNano: uint64(stats.Cpu_nano),
|
||||
SystemNano: uint64(stats.System_nano),
|
||||
MemUsage: uint64(stats.Mem_usage),
|
||||
MemLimit: uint64(stats.Mem_limit),
|
||||
MemPerc: stats.Mem_perc,
|
||||
NetInput: uint64(stats.Net_input),
|
||||
NetOutput: uint64(stats.Net_output),
|
||||
BlockInput: uint64(stats.Block_input),
|
||||
BlockOutput: uint64(stats.Block_output),
|
||||
PIDs: uint64(stats.Pids),
|
||||
}
|
||||
return cstats
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package varlinkapi
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/containers/libpod/pkg/adapter/shortcuts"
|
||||
"github.com/containers/libpod/pkg/rootless"
|
||||
"syscall"
|
||||
@ -299,3 +300,33 @@ func (i *LibpodAPI) PodStateData(call iopodman.VarlinkCall, name string) error {
|
||||
}
|
||||
return call.ReplyPodStateData(string(b))
|
||||
}
|
||||
|
||||
// TopPod provides the top stats for a given or latest pod
|
||||
func (i *LibpodAPI) TopPod(call iopodman.VarlinkCall, name string, latest bool, descriptors []string) error {
|
||||
var (
|
||||
pod *libpod.Pod
|
||||
err error
|
||||
)
|
||||
if latest {
|
||||
name = "latest"
|
||||
pod, err = i.Runtime.GetLatestPod()
|
||||
} else {
|
||||
pod, err = i.Runtime.LookupPod(name)
|
||||
}
|
||||
if err != nil {
|
||||
return call.ReplyPodNotFound(name, err.Error())
|
||||
}
|
||||
|
||||
podStatus, err := shared.GetPodStatus(pod)
|
||||
if err != nil {
|
||||
return call.ReplyErrorOccurred(fmt.Sprintf("unable to get status for pod %s", pod.ID()))
|
||||
}
|
||||
if podStatus != "Running" {
|
||||
return call.ReplyErrorOccurred("pod top can only be used on pods with at least one running container")
|
||||
}
|
||||
reply, err := pod.GetPodPidInformation(descriptors)
|
||||
if err != nil {
|
||||
return call.ReplyErrorOccurred(err.Error())
|
||||
}
|
||||
return call.ReplyTopPod(reply)
|
||||
}
|
||||
|
Reference in New Issue
Block a user