summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/podman/attach.go2
-rw-r--r--cmd/podman/build.go2
-rw-r--r--cmd/podman/commands.go57
-rw-r--r--cmd/podman/commands_remoteclient.go19
-rw-r--r--cmd/podman/commit.go1
-rw-r--r--cmd/podman/container.go6
-rw-r--r--cmd/podman/create.go1
-rw-r--r--cmd/podman/diff.go3
-rw-r--r--cmd/podman/exec.go1
-rw-r--r--cmd/podman/export.go1
-rw-r--r--cmd/podman/generate.go1
-rw-r--r--cmd/podman/history.go3
-rw-r--r--cmd/podman/image.go6
-rw-r--r--cmd/podman/images.go2
-rw-r--r--cmd/podman/import.go1
-rw-r--r--cmd/podman/info.go1
-rw-r--r--cmd/podman/inspect.go1
-rw-r--r--cmd/podman/kill.go1
-rw-r--r--cmd/podman/load.go1
-rw-r--r--cmd/podman/login.go1
-rw-r--r--cmd/podman/logout.go1
-rw-r--r--cmd/podman/logs.go1
-rw-r--r--cmd/podman/main.go20
-rw-r--r--cmd/podman/mount.go1
-rw-r--r--cmd/podman/pause.go1
-rw-r--r--cmd/podman/play.go1
-rw-r--r--cmd/podman/pod.go1
-rw-r--r--cmd/podman/pod_stats.go130
-rw-r--r--cmd/podman/port.go1
-rw-r--r--cmd/podman/ps.go3
-rw-r--r--cmd/podman/pull.go1
-rw-r--r--cmd/podman/push.go1
-rw-r--r--cmd/podman/refresh.go1
-rw-r--r--cmd/podman/restart.go1
-rw-r--r--cmd/podman/restore.go1
-rw-r--r--cmd/podman/rm.go12
-rw-r--r--cmd/podman/rmi.go2
-rw-r--r--cmd/podman/run.go2
-rw-r--r--cmd/podman/save.go2
-rw-r--r--cmd/podman/search.go2
-rw-r--r--cmd/podman/sign.go2
-rw-r--r--cmd/podman/start.go2
-rw-r--r--cmd/podman/stats.go2
-rw-r--r--cmd/podman/stop.go2
-rw-r--r--cmd/podman/system.go6
-rw-r--r--cmd/podman/tag.go2
-rw-r--r--cmd/podman/top.go2
-rw-r--r--cmd/podman/umount.go2
-rw-r--r--cmd/podman/unpause.go2
-rw-r--r--cmd/podman/varlink.go4
-rw-r--r--cmd/podman/version.go1
-rw-r--r--cmd/podman/volume.go1
-rw-r--r--cmd/podman/wait.go2
-rw-r--r--docs/podman-rm.1.md4
-rw-r--r--docs/podman-stats.1.md9
-rw-r--r--libpod/errors.go11
-rw-r--r--libpod/kube.go10
-rw-r--r--libpod/runtime_ctr.go15
-rw-r--r--test/e2e/pod_stats_test.go23
59 files changed, 286 insertions, 112 deletions
diff --git a/cmd/podman/attach.go b/cmd/podman/attach.go
index 8b0fd7ffd..ecba91a90 100644
--- a/cmd/podman/attach.go
+++ b/cmd/podman/attach.go
@@ -34,8 +34,6 @@ func init() {
flags.BoolVar(&attachCommand.SigProxy, "sig-proxy", true, "Proxy received signals to the process (default true)")
flags.BoolVarP(&attachCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
-
- rootCmd.AddCommand(attachCommand.Command)
}
func attachCmd(c *cliconfig.AttachValues) error {
diff --git a/cmd/podman/build.go b/cmd/podman/build.go
index 20f621e84..cebca18f1 100644
--- a/cmd/podman/build.go
+++ b/cmd/podman/build.go
@@ -58,8 +58,6 @@ func init() {
flags.AddFlagSet(&budFlags)
flags.AddFlagSet(&fromAndBugFlags)
-
- rootCmd.AddCommand(buildCommand.Command)
}
func getDockerfiles(files []string) []string {
diff --git a/cmd/podman/commands.go b/cmd/podman/commands.go
index e1eba1f31..fd438e2fc 100644
--- a/cmd/podman/commands.go
+++ b/cmd/podman/commands.go
@@ -6,24 +6,66 @@ import (
"github.com/spf13/cobra"
)
+// Commands that the local client implements
+func getMainCommands() []*cobra.Command {
+ rootCommands := []*cobra.Command{
+ _attachCommand,
+ _buildCommand,
+ _commitCommand,
+ _createCommand,
+ _diffCommand,
+ _execCommand,
+ _killCommand,
+ generateCommand.Command,
+ podCommand.Command,
+ _containerKubeCommand,
+ _psCommand,
+ _loadCommand,
+ _loginCommand,
+ _logoutCommand,
+ _logsCommand,
+ _mountCommand,
+ _pauseCommand,
+ _portCommand,
+ _pushCommand,
+ _refreshCommand,
+ _restartCommand,
+ _restoreCommand,
+ _rmCommand,
+ _runCommmand,
+ _saveCommand,
+ _searchCommand,
+ _signCommand,
+ _startCommand,
+ _statsCommand,
+ _stopCommand,
+ _topCommand,
+ _umountCommand,
+ _unpauseCommand,
+ _varlinkCommand,
+ volumeCommand.Command,
+ _waitCommand,
+ }
+ return rootCommands
+}
+
+// Commands that the local client implements
func getImageSubCommands() []*cobra.Command {
return []*cobra.Command{
_buildCommand,
- _importCommand,
_loadCommand,
- _pullCommand,
- _rmiCommand,
+ _pushCommand,
_saveCommand,
_signCommand,
}
}
+// Commands that the local client implements
func getContainerSubCommands() []*cobra.Command {
return []*cobra.Command{
_attachCommand,
_checkpointCommand,
_cleanupCommand,
- _containerExistsCommand,
_commitCommand,
_createCommand,
_diffCommand,
@@ -52,6 +94,7 @@ func getContainerSubCommands() []*cobra.Command {
}
}
+// Commands that the local client implements
func getPodSubCommands() []*cobra.Command {
return []*cobra.Command{
_podCreateCommand,
@@ -70,6 +113,7 @@ func getPodSubCommands() []*cobra.Command {
}
}
+// Commands that the local client implements
func getVolumeSubCommands() []*cobra.Command {
return []*cobra.Command{
_volumeCreateCommand,
@@ -80,18 +124,21 @@ func getVolumeSubCommands() []*cobra.Command {
}
}
+// Commands that the local client implements
func getGenerateSubCommands() []*cobra.Command {
return []*cobra.Command{
_containerKubeCommand,
}
}
+// Commands that the local client implements
func getPlaySubCommands() []*cobra.Command {
return []*cobra.Command{
_playKubeCommand,
}
}
+// Commands that the local client implements
func getTrustSubCommands() []*cobra.Command {
return []*cobra.Command{
_setTrustCommand,
@@ -99,9 +146,9 @@ func getTrustSubCommands() []*cobra.Command {
}
}
+// Commands that the local client implements
func getSystemSubCommands() []*cobra.Command {
return []*cobra.Command{
- _infoCommand,
_pruneSystemCommand,
}
}
diff --git a/cmd/podman/commands_remoteclient.go b/cmd/podman/commands_remoteclient.go
index 993137fde..e1f68405e 100644
--- a/cmd/podman/commands_remoteclient.go
+++ b/cmd/podman/commands_remoteclient.go
@@ -6,45 +6,54 @@ import (
"github.com/spf13/cobra"
)
-//import "github.com/urfave/cli"
-//
+// commands that only the remoteclient implements
+func getMainCommands() []*cobra.Command {
+ return []*cobra.Command{}
+}
+
+// commands that only the remoteclient implements
func getAppCommands() []*cobra.Command {
return []*cobra.Command{}
}
+// commands that only the remoteclient implements
func getImageSubCommands() []*cobra.Command {
return []*cobra.Command{}
}
+// commands that only the remoteclient implements
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 getVolumeSubCommands() []*cobra.Command {
return []*cobra.Command{
_volumeCreateCommand,
}
}
+// commands that only the remoteclient implements
func getGenerateSubCommands() []*cobra.Command {
return []*cobra.Command{}
}
+// commands that only the remoteclient implements
func getPlaySubCommands() []*cobra.Command {
return []*cobra.Command{}
}
+// commands that only the remoteclient implements
func getTrustSubCommands() []*cobra.Command {
return []*cobra.Command{}
}
-//func getMainAppFlags() []cli.Flag {
-// return []cli.Flag{}
-//}
+// commands that only the remoteclient implements
func getSystemSubCommands() []*cobra.Command {
return []*cobra.Command{}
}
diff --git a/cmd/podman/commit.go b/cmd/podman/commit.go
index 6fd6b9761..e77903c36 100644
--- a/cmd/podman/commit.go
+++ b/cmd/podman/commit.go
@@ -47,7 +47,6 @@ func init() {
flags.BoolVarP(&commitCommand.Pause, "pause", "p", false, "Pause container during commit")
flags.BoolVarP(&commitCommand.Quiet, "quiet", "q", false, "Suppress output")
- rootCmd.AddCommand(commitCommand.Command)
}
func commitCmd(c *cliconfig.CommitValues) error {
diff --git a/cmd/podman/container.go b/cmd/podman/container.go
index 969cb2dc8..6d9231482 100644
--- a/cmd/podman/container.go
+++ b/cmd/podman/container.go
@@ -15,7 +15,13 @@ var containerCommand = cliconfig.PodmanCommand{
},
}
+// Commands that are universally implemented.
+var containerCommands = []*cobra.Command{
+ _containerExistsCommand,
+}
+
func init() {
+ containerCommand.AddCommand(containerCommands...)
containerCommand.AddCommand(getContainerSubCommands()...)
rootCmd.AddCommand(containerCommand.Command)
}
diff --git a/cmd/podman/create.go b/cmd/podman/create.go
index 2f8742052..7aa371147 100644
--- a/cmd/podman/create.go
+++ b/cmd/podman/create.go
@@ -65,7 +65,6 @@ func init() {
flags := createCommand.Flags()
flags.SetInterspersed(true)
- rootCmd.AddCommand(createCommand.Command)
}
func createCmd(c *cliconfig.CreateValues) error {
diff --git a/cmd/podman/diff.go b/cmd/podman/diff.go
index 04a659ab6..1bcedbd1e 100644
--- a/cmd/podman/diff.go
+++ b/cmd/podman/diff.go
@@ -59,9 +59,8 @@ func init() {
flags.MarkHidden("archive")
- rootCmd.AddCommand(diffCommand.Command)
-
}
+
func formatJSON(output []diffOutputParams) (diffJSONOutput, error) {
jsonStruct := diffJSONOutput{}
for _, output := range output {
diff --git a/cmd/podman/exec.go b/cmd/podman/exec.go
index b4f66bc03..fa6e4af03 100644
--- a/cmd/podman/exec.go
+++ b/cmd/podman/exec.go
@@ -46,7 +46,6 @@ func init() {
flags.StringVarP(&execCommand.Workdir, "workdir", "w", "", "Working directory inside the container")
- rootCmd.AddCommand(execCommand.Command)
}
func execCmd(c *cliconfig.ExecValues) error {
diff --git a/cmd/podman/export.go b/cmd/podman/export.go
index bd9e38b0c..18fcc679c 100644
--- a/cmd/podman/export.go
+++ b/cmd/podman/export.go
@@ -33,7 +33,6 @@ func init() {
exportCommand.Command = _exportCommand
flags := exportCommand.Flags()
flags.StringVarP(&exportCommand.Output, "output", "o", "/dev/stdout", "Write to a file, default is STDOUT")
- rootCmd.AddCommand(exportCommand.Command)
}
// exportCmd saves a container to a tarball on disk
diff --git a/cmd/podman/generate.go b/cmd/podman/generate.go
index a5e15fdd6..d258c5194 100644
--- a/cmd/podman/generate.go
+++ b/cmd/podman/generate.go
@@ -17,5 +17,4 @@ var generateCommand = cliconfig.PodmanCommand{
func init() {
generateCommand.AddCommand(getGenerateSubCommands()...)
- rootCmd.AddCommand(generateCommand.Command)
}
diff --git a/cmd/podman/history.go b/cmd/podman/history.go
index 97e501947..953c94b69 100644
--- a/cmd/podman/history.go
+++ b/cmd/podman/history.go
@@ -60,9 +60,8 @@ func init() {
flags.BoolVar(&historyCommand.NoTrunc, "no-trunc", false, "Do not truncate the output")
flags.BoolVarP(&historyCommand.Quiet, "quiet", "q", false, "Display the numeric IDs only")
- rootCmd.AddCommand(historyCommand.Command)
-
}
+
func historyCmd(c *cliconfig.HistoryValues) error {
runtime, err := adapter.GetRuntime(&c.PodmanCommand)
if err != nil {
diff --git a/cmd/podman/image.go b/cmd/podman/image.go
index ac7ff4944..e93c63267 100644
--- a/cmd/podman/image.go
+++ b/cmd/podman/image.go
@@ -20,10 +20,11 @@ var (
var imageSubCommands = []*cobra.Command{
_historyCommand,
_imageExistsCommand,
- _inspectCommand,
_imagesCommand,
+ _importCommand,
+ _inspectCommand,
_pruneImagesCommand,
- _pushCommand,
+ _pullCommand,
_rmiCommand,
_tagCommand,
}
@@ -31,5 +32,4 @@ var imageSubCommands = []*cobra.Command{
func init() {
imageCommand.AddCommand(imageSubCommands...)
imageCommand.AddCommand(getImageSubCommands()...)
- rootCmd.AddCommand(imageCommand.Command)
}
diff --git a/cmd/podman/images.go b/cmd/podman/images.go
index 6f5a3e9f1..329b8e8d9 100644
--- a/cmd/podman/images.go
+++ b/cmd/podman/images.go
@@ -114,8 +114,6 @@ func init() {
flags.BoolVarP(&imagesCommand.Quiet, "quiet", "q", false, "Display only image IDs")
flags.StringVar(&imagesCommand.Sort, "sort", "created", "Sort by created, id, repository, size, or tag")
- rootCmd.AddCommand(imagesCommand.Command)
-
}
func imagesCmd(c *cliconfig.ImagesValues) error {
diff --git a/cmd/podman/import.go b/cmd/podman/import.go
index 52d144eb3..15b33f818 100644
--- a/cmd/podman/import.go
+++ b/cmd/podman/import.go
@@ -36,7 +36,6 @@ func init() {
flags.StringVarP(&importCommand.Message, "message", "m", "", "Set commit message for imported image")
flags.BoolVarP(&importCommand.Quiet, "quiet", "q", false, "Suppress output")
- rootCmd.AddCommand(importCommand.Command)
}
func importCmd(c *cliconfig.ImportValues) error {
diff --git a/cmd/podman/info.go b/cmd/podman/info.go
index 0896e16a4..177878e5a 100644
--- a/cmd/podman/info.go
+++ b/cmd/podman/info.go
@@ -37,7 +37,6 @@ func init() {
flags.BoolVarP(&infoCommand.Debug, "debug", "D", false, "Display additional debug information")
flags.StringVarP(&infoCommand.Format, "format", "f", "", "Change the output format to JSON or a Go template")
- rootCmd.AddCommand(infoCommand.Command)
}
func infoCmd(c *cliconfig.InfoValues) error {
diff --git a/cmd/podman/inspect.go b/cmd/podman/inspect.go
index b2979c6ae..21ad067cd 100644
--- a/cmd/podman/inspect.go
+++ b/cmd/podman/inspect.go
@@ -46,7 +46,6 @@ func init() {
flags.BoolVarP(&inspectCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of if the type is a container")
flags.BoolVarP(&inspectCommand.Size, "size", "s", false, "Display total file size if the type is container")
- rootCmd.AddCommand(inspectCommand.Command)
}
func inspectCmd(c *cliconfig.InspectValues) error {
diff --git a/cmd/podman/kill.go b/cmd/podman/kill.go
index 04c0fd531..75ebbb6b0 100644
--- a/cmd/podman/kill.go
+++ b/cmd/podman/kill.go
@@ -40,7 +40,6 @@ func init() {
flags.StringVarP(&killCommand.Signal, "signal", "s", "KILL", "Signal to send to the container")
flags.BoolVarP(&killCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
- rootCmd.AddCommand(killCommand.Command)
}
// killCmd kills one or more containers with a signal
diff --git a/cmd/podman/load.go b/cmd/podman/load.go
index 90268ca8f..c50cd1608 100644
--- a/cmd/podman/load.go
+++ b/cmd/podman/load.go
@@ -39,7 +39,6 @@ func init() {
flags.BoolVarP(&loadCommand.Quiet, "quiet", "q", false, "Suppress the output")
flags.StringVar(&loadCommand.SignaturePolicy, "signature-policy", "", "Pathname of signature policy file (not usually used)")
- rootCmd.AddCommand(loadCommand.Command)
}
// loadCmd gets the image/file to be loaded from the command line
diff --git a/cmd/podman/login.go b/cmd/podman/login.go
index 5ab0713e5..92102e940 100644
--- a/cmd/podman/login.go
+++ b/cmd/podman/login.go
@@ -44,7 +44,6 @@ func init() {
flags.BoolVar(&loginCommand.TlsVerify, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries (default: true)")
flags.StringVarP(&loginCommand.Username, "username", "u", "", "Username for registry")
- rootCmd.AddCommand(loginCommand.Command)
}
// loginCmd uses the authentication package to store a user's authenticated credentials
diff --git a/cmd/podman/logout.go b/cmd/podman/logout.go
index 02bde7857..4d0f156e4 100644
--- a/cmd/podman/logout.go
+++ b/cmd/podman/logout.go
@@ -32,7 +32,6 @@ func init() {
flags.BoolVarP(&logoutCommand.All, "all", "a", false, "Remove the cached credentials for all registries in the auth file")
flags.StringVar(&logoutCommand.Authfile, "authfile", "", "Path of the authentication file. Default is ${XDG_RUNTIME_DIR}/containers/auth.json. Use REGISTRY_AUTH_FILE environment variable to override")
- rootCmd.AddCommand(logoutCommand.Command)
}
// logoutCmd uses the authentication package to remove the authenticated of a registry
diff --git a/cmd/podman/logs.go b/cmd/podman/logs.go
index 83f900e63..77c0b17f3 100644
--- a/cmd/podman/logs.go
+++ b/cmd/podman/logs.go
@@ -43,7 +43,6 @@ func init() {
flags.SetInterspersed(false)
- rootCmd.AddCommand(logsCommand.Command)
}
func logsCmd(c *cliconfig.LogsValues) error {
diff --git a/cmd/podman/main.go b/cmd/podman/main.go
index 32ecaede7..49acde1f9 100644
--- a/cmd/podman/main.go
+++ b/cmd/podman/main.go
@@ -27,6 +27,24 @@ var (
exitCode = 125
)
+// Commands that the remote and local client have
+// implemented.
+var mainCommands = []*cobra.Command{
+ _exportCommand,
+ _historyCommand,
+ _imagesCommand,
+ _importCommand,
+ _infoCommand,
+ _inspectCommand,
+ _killCommand,
+ _pullCommand,
+ _rmiCommand,
+ _tagCommand,
+ _versionCommand,
+ imageCommand.Command,
+ systemCommand.Command,
+}
+
var cmdsNotRequiringRootless = map[*cobra.Command]bool{
_versionCommand: true,
_createCommand: true,
@@ -92,6 +110,8 @@ func init() {
rootCmd.PersistentFlags().BoolVar(&MainGlobalOpts.Syslog, "syslog", false, "Output logging information to syslog as well as the console")
rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.TmpDir, "tmpdir", "", "Path to the tmp directory")
+ rootCmd.AddCommand(mainCommands...)
+ rootCmd.AddCommand(getMainCommands()...)
}
func initConfig() {
diff --git a/cmd/podman/mount.go b/cmd/podman/mount.go
index 36ca8bcfb..d16b17108 100644
--- a/cmd/podman/mount.go
+++ b/cmd/podman/mount.go
@@ -45,7 +45,6 @@ func init() {
flags.BoolVarP(&mountCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
flags.BoolVar(&mountCommand.NoTrunc, "notruncate", false, "Do not truncate output")
- rootCmd.AddCommand(mountCommand.Command)
}
// jsonMountPoint stores info about each container
diff --git a/cmd/podman/pause.go b/cmd/podman/pause.go
index 466a3b136..8d8501ff7 100644
--- a/cmd/podman/pause.go
+++ b/cmd/podman/pause.go
@@ -37,7 +37,6 @@ func init() {
flags := pauseCommand.Flags()
flags.BoolVarP(&pauseCommand.All, "all", "a", false, "Pause all running containers")
- rootCmd.AddCommand(pauseCommand.Command)
}
func pauseCmd(c *cliconfig.PauseValues) error {
diff --git a/cmd/podman/play.go b/cmd/podman/play.go
index ff8320a6b..f083c9ff1 100644
--- a/cmd/podman/play.go
+++ b/cmd/podman/play.go
@@ -19,5 +19,4 @@ func init() {
func init() {
playCommand.AddCommand(getPlaySubCommands()...)
- rootCmd.AddCommand(playCommand.Command)
}
diff --git a/cmd/podman/pod.go b/cmd/podman/pod.go
index 4104c39c7..4de824703 100644
--- a/cmd/podman/pod.go
+++ b/cmd/podman/pod.go
@@ -20,5 +20,4 @@ var podCommand = cliconfig.PodmanCommand{
func init() {
podCommand.AddCommand(getPodSubCommands()...)
- rootCmd.AddCommand(podCommand.Command)
}
diff --git a/cmd/podman/pod_stats.go b/cmd/podman/pod_stats.go
index ccbcf9f7c..02dee68ac 100644
--- a/cmd/podman/pod_stats.go
+++ b/cmd/podman/pod_stats.go
@@ -2,7 +2,11 @@ package main
import (
"fmt"
+ "html/template"
+ "os"
+ "reflect"
"strings"
+ "text/tabwriter"
"time"
"encoding/json"
@@ -136,6 +140,25 @@ func podStatsCmd(c *cliconfig.PodStatsValues) error {
step = 0
}
+ headerNames := make(map[string]string)
+ if c.Format != "" {
+ // Make a map of the field names for the headers
+ v := reflect.ValueOf(podStatOut{})
+ t := v.Type()
+ for i := 0; i < t.NumField(); i++ {
+ value := strings.ToUpper(splitCamelCase(t.Field(i).Name))
+ switch value {
+ case "CPU":
+ value = value + " %"
+ case "MEM":
+ value = value + " %"
+ case "MEM USAGE":
+ value = "MEM USAGE / LIMIT"
+ }
+ headerNames[t.Field(i).Name] = value
+ }
+ }
+
for i := 0; i < times; i += step {
var newStats []*libpod.PodContainerStats
for _, p := range pods {
@@ -163,7 +186,14 @@ func podStatsCmd(c *cliconfig.PodStatsValues) error {
outputJson(newStats)
} else {
- outputToStdOut(newStats)
+ results := podContainerStatsToPodStatOut(newStats)
+ if len(format) == 0 {
+ outputToStdOut(results)
+ } else {
+ if err := printPSFormat(c.Format, results, headerNames); err != nil {
+ return err
+ }
+ }
}
time.Sleep(time.Second)
previousPodStats := new([]*libpod.PodContainerStats)
@@ -177,28 +207,88 @@ func podStatsCmd(c *cliconfig.PodStatsValues) error {
return nil
}
-func outputToStdOut(stats []*libpod.PodContainerStats) {
- outFormat := ("%-14s %-14s %-12s %-6s %-19s %-6s %-19s %-19s %-4s\n")
- fmt.Printf(outFormat, "POD", "CID", "NAME", "CPU %", "MEM USAGE/ LIMIT", "MEM %", "NET IO", "BLOCK IO", "PIDS")
- for _, i := range stats {
- if len(i.ContainerStats) == 0 {
- fmt.Printf(outFormat, i.Pod.ID()[:12], "--", "--", "--", "--", "--", "--", "--", "--")
- }
- for _, c := range i.ContainerStats {
- cpu := floatToPercentString(c.CPU)
- memUsage := combineHumanValues(c.MemUsage, c.MemLimit)
- memPerc := floatToPercentString(c.MemPerc)
- netIO := combineHumanValues(c.NetInput, c.NetOutput)
- blockIO := combineHumanValues(c.BlockInput, c.BlockOutput)
- pids := pidsToString(c.PIDs)
- containerName := c.Name
- if len(c.Name) > 10 {
- containerName = containerName[:10]
+func podContainerStatsToPodStatOut(stats []*libpod.PodContainerStats) []*podStatOut {
+ var out []*podStatOut
+ for _, p := range stats {
+ for _, c := range p.ContainerStats {
+ o := podStatOut{
+ CPU: floatToPercentString(c.CPU),
+ MemUsage: combineHumanValues(c.MemUsage, c.MemLimit),
+ Mem: floatToPercentString(c.MemPerc),
+ NetIO: combineHumanValues(c.NetInput, c.NetOutput),
+ BlockIO: combineHumanValues(c.BlockInput, c.BlockOutput),
+ PIDS: pidsToString(c.PIDs),
+ CID: c.ContainerID[:12],
+ Name: c.Name,
+ Pod: p.Pod.ID()[:12],
}
- fmt.Printf(outFormat, i.Pod.ID()[:12], c.ContainerID[:12], containerName, cpu, memUsage, memPerc, netIO, blockIO, pids)
+ out = append(out, &o)
+ }
+ }
+ return out
+}
+
+type podStatOut struct {
+ CPU string
+ MemUsage string
+ Mem string
+ NetIO string
+ BlockIO string
+ PIDS string
+ Pod string
+ CID string
+ Name string
+}
+
+func printPSFormat(format string, stats []*podStatOut, headerNames map[string]string) error {
+ if len(stats) == 0 {
+ return nil
+ }
+
+ // Use a tabwriter to align column format
+ w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0)
+ // Spit out the header if "table" is present in the format
+ if strings.HasPrefix(format, "table") {
+ hformat := strings.Replace(strings.TrimSpace(format[5:]), " ", "\t", -1)
+ format = hformat
+ headerTmpl, err := template.New("header").Parse(hformat)
+ if err != nil {
+ return err
+ }
+ if err := headerTmpl.Execute(w, headerNames); err != nil {
+ return err
+ }
+ fmt.Fprintln(w, "")
+ }
+
+ // Spit out the data rows now
+ dataTmpl, err := template.New("data").Parse(format)
+ if err != nil {
+ return err
+ }
+ for _, container := range stats {
+ if err := dataTmpl.Execute(w, container); err != nil {
+ return err
+ }
+ fmt.Fprintln(w, "")
+ }
+ // Flush the writer
+ return w.Flush()
+
+}
+
+func outputToStdOut(stats []*podStatOut) {
+ w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
+ outFormat := ("%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n")
+ fmt.Fprintf(w, outFormat, "POD", "CID", "NAME", "CPU %", "MEM USAGE/ LIMIT", "MEM %", "NET IO", "BLOCK IO", "PIDS")
+ for _, i := range stats {
+ if len(stats) == 0 {
+ fmt.Fprintf(w, outFormat, i.Pod, "--", "--", "--", "--", "--", "--", "--", "--")
+ } else {
+ fmt.Fprintf(w, outFormat, i.Pod, i.CID, i.Name, i.CPU, i.MemUsage, i.Mem, i.NetIO, i.BlockIO, i.PIDS)
}
}
- fmt.Println()
+ w.Flush()
}
func getPreviousPodContainerStats(podID string, prev []*libpod.PodContainerStats) map[string]*libpod.ContainerStats {
diff --git a/cmd/podman/port.go b/cmd/podman/port.go
index 488ef2ffe..6b458c3c8 100644
--- a/cmd/podman/port.go
+++ b/cmd/podman/port.go
@@ -39,7 +39,6 @@ func init() {
flags.BoolVarP(&portCommand.All, "all", "a", false, "Display port information for all containers")
flags.BoolVarP(&portCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
- rootCmd.AddCommand(portCommand.Command)
}
func portCmd(c *cliconfig.PortValues) error {
diff --git a/cmd/podman/ps.go b/cmd/podman/ps.go
index 002975b87..dd5bf0ff2 100644
--- a/cmd/podman/ps.go
+++ b/cmd/podman/ps.go
@@ -187,9 +187,8 @@ func init() {
flags.StringVar(&psCommand.Sort, "sort", "created", "Sort output by command, created, id, image, names, runningfor, size, or status")
flags.BoolVar(&psCommand.Sync, "sync", false, "Sync container state with OCI runtime")
- rootCmd.AddCommand(psCommand.Command)
-
}
+
func psCmd(c *cliconfig.PsValues) error {
var (
filterFuncs []libpod.ContainerFilter
diff --git a/cmd/podman/pull.go b/cmd/podman/pull.go
index d70719164..ad1469403 100644
--- a/cmd/podman/pull.go
+++ b/cmd/podman/pull.go
@@ -48,7 +48,6 @@ func init() {
flags.StringVar(&pullCommand.SignaturePolicy, "signature-policy", "", "`Pathname` of signature policy file (not usually used)")
flags.BoolVar(&pullCommand.TlsVerify, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries (default: true)")
- rootCmd.AddCommand(pullCommand.Command)
}
// pullCmd gets the data from the command line and calls pullImage
diff --git a/cmd/podman/push.go b/cmd/podman/push.go
index a1ee00a65..49786e86f 100644
--- a/cmd/podman/push.go
+++ b/cmd/podman/push.go
@@ -52,7 +52,6 @@ func init() {
flags.StringVar(&pushCommand.SignaturePolicy, "signature-policy", "", "`Pathname` of signature policy file (not usually used)")
flags.StringVar(&pushCommand.SignBy, "sign-by", "", "Add a signature at the destination using the specified key")
flags.BoolVar(&pushCommand.TlsVerify, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries (default: true)")
- rootCmd.AddCommand(pushCommand.Command)
}
func pushCmd(c *cliconfig.PushValues) error {
diff --git a/cmd/podman/refresh.go b/cmd/podman/refresh.go
index 3890188b4..32b274169 100644
--- a/cmd/podman/refresh.go
+++ b/cmd/podman/refresh.go
@@ -27,7 +27,6 @@ var (
func init() {
refreshCommand.Command = _refreshCommand
- rootCmd.AddCommand(refreshCommand.Command)
}
func refreshCmd(c *cliconfig.RefreshValues) error {
diff --git a/cmd/podman/restart.go b/cmd/podman/restart.go
index f94e745ed..a305b364a 100644
--- a/cmd/podman/restart.go
+++ b/cmd/podman/restart.go
@@ -39,7 +39,6 @@ func init() {
flags.UintVarP(&restartCommand.Timeout, "timeout", "t", libpod.CtrRemoveTimeout, "Seconds to wait for stop before killing the container")
flags.UintVar(&restartCommand.Timeout, "time", libpod.CtrRemoveTimeout, "Seconds to wait for stop before killing the container")
- rootCmd.AddCommand(restartCommand.Command)
}
func restartCmd(c *cliconfig.RestartValues) error {
diff --git a/cmd/podman/restore.go b/cmd/podman/restore.go
index daee635f0..5f28c3087 100644
--- a/cmd/podman/restore.go
+++ b/cmd/podman/restore.go
@@ -42,7 +42,6 @@ func init() {
// TODO: add ContainerStateCheckpointed
flags.BoolVar(&restoreCommand.TcpEstablished, "tcp-established", false, "Checkpoint a container with established TCP connections")
- rootCmd.AddCommand(restoreCommand.Command)
}
func restoreCmd(c *cliconfig.RestoreValues) error {
diff --git a/cmd/podman/rm.go b/cmd/podman/rm.go
index bb9a913c9..f8aef6461 100644
--- a/cmd/podman/rm.go
+++ b/cmd/podman/rm.go
@@ -6,6 +6,7 @@ import (
"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/sirupsen/logrus"
"github.com/spf13/cobra"
@@ -39,7 +40,6 @@ func init() {
flags.BoolVarP(&rmCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
flags.BoolVarP(&rmCommand.Volumes, "volumes", "v", false, "Remove the volumes associated with the container (Not implemented yet)")
- rootCmd.AddCommand(rmCommand.Command)
}
// saveCmd saves the image to either docker-archive or oci
@@ -61,10 +61,18 @@ func rmCmd(c *cliconfig.RmValues) error {
delContainers, err := getAllOrLatestContainers(&c.PodmanCommand, runtime, -1, "all")
if err != nil {
+ if c.Force && len(c.InputArgs) > 0 {
+ if errors.Cause(err) == libpod.ErrNoSuchCtr {
+ err = nil
+ }
+ runtime.RemoveContainersFromStorage(c.InputArgs)
+ }
if len(delContainers) == 0 {
return err
}
- fmt.Println(err.Error())
+ if err != nil {
+ fmt.Println(err.Error())
+ }
}
for _, container := range delContainers {
diff --git a/cmd/podman/rmi.go b/cmd/podman/rmi.go
index 70f58e844..4572fd530 100644
--- a/cmd/podman/rmi.go
+++ b/cmd/podman/rmi.go
@@ -32,8 +32,6 @@ func init() {
flags := rmiCommand.Flags()
flags.BoolVarP(&rmiCommand.All, "all", "a", false, "Remove all images")
flags.BoolVarP(&rmiCommand.Force, "force", "f", false, "Force Removal of the image")
-
- rootCmd.AddCommand(rmiCommand.Command)
}
func rmiCmd(c *cliconfig.RmiValues) error {
diff --git a/cmd/podman/run.go b/cmd/podman/run.go
index 76b29cb84..897e2d1b3 100644
--- a/cmd/podman/run.go
+++ b/cmd/podman/run.go
@@ -40,8 +40,6 @@ func init() {
flags.SetInterspersed(false)
flags.Bool("sig-proxy", true, "Proxy received signals to the process (default true)")
getCreateFlags(&runCommmand.PodmanCommand)
-
- rootCmd.AddCommand(runCommmand.Command)
}
func runCmd(c *cliconfig.RunValues) error {
diff --git a/cmd/podman/save.go b/cmd/podman/save.go
index 766561f1a..62b891358 100644
--- a/cmd/podman/save.go
+++ b/cmd/podman/save.go
@@ -52,8 +52,6 @@ func init() {
flags.StringVar(&saveCommand.Format, "format", "", "Save image to oci-archive, oci-dir (directory with oci manifest type), docker-dir (directory with v2s2 manifest type)")
flags.StringVarP(&saveCommand.Output, "output", "o", "/dev/stdout", "Write to a file, default is STDOUT")
flags.BoolVarP(&saveCommand.Quiet, "quiet", "q", false, "Suppress the output")
-
- rootCmd.AddCommand(saveCommand.Command)
}
// saveCmd saves the image to either docker-archive or oci
diff --git a/cmd/podman/search.go b/cmd/podman/search.go
index b15da1f6d..10c29c918 100644
--- a/cmd/podman/search.go
+++ b/cmd/podman/search.go
@@ -50,8 +50,6 @@ func init() {
flags.IntVar(&searchCommand.Limit, "limit", 0, "Limit the number of results")
flags.BoolVar(&searchCommand.NoTrunc, "no-trunc", false, "Do not truncate the output")
flags.BoolVar(&searchCommand.TlsVerify, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries (default: true)")
-
- rootCmd.AddCommand(searchCommand.Command)
}
type searchParams struct {
diff --git a/cmd/podman/sign.go b/cmd/podman/sign.go
index a87c12556..2c3f6c09f 100644
--- a/cmd/podman/sign.go
+++ b/cmd/podman/sign.go
@@ -42,8 +42,6 @@ func init() {
flags.StringVarP(&signCommand.Directory, "directory", "d", "", "Define an alternate directory to store signatures")
flags.StringVar(&signCommand.SignBy, "sign-by", "", "Name of the signing key")
- rootCmd.AddCommand(signCommand.Command)
-
}
// SignatureStoreDir defines default directory to store signatures
diff --git a/cmd/podman/start.go b/cmd/podman/start.go
index 483ab4081..3a03db47a 100644
--- a/cmd/podman/start.go
+++ b/cmd/podman/start.go
@@ -42,8 +42,6 @@ func init() {
flags.BoolVarP(&startCommand.Interactive, "interactive", "i", false, "Keep STDIN open even if not attached")
flags.BoolVarP(&startCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
flags.BoolVar(&startCommand.SigProxy, "sig-proxy", true, "Proxy received signals to the process (default true if attaching, false otherwise)")
-
- rootCmd.AddCommand(startCommand.Command)
}
func startCmd(c *cliconfig.StartValues) error {
diff --git a/cmd/podman/stats.go b/cmd/podman/stats.go
index 8c79ed290..2af7fb9ea 100644
--- a/cmd/podman/stats.go
+++ b/cmd/podman/stats.go
@@ -53,8 +53,6 @@ func init() {
flags.BoolVarP(&statsCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
flags.BoolVar(&statsCommand.NoReset, "no-reset", false, "Disable resetting the screen between intervals")
flags.BoolVar(&statsCommand.NoStream, "no-stream", false, "Disable streaming stats and only pull the first result, default setting is false")
-
- rootCmd.AddCommand(statsCommand.Command)
}
func statsCmd(c *cliconfig.StatsValues) error {
diff --git a/cmd/podman/stop.go b/cmd/podman/stop.go
index e2c16fe20..4700b2dde 100644
--- a/cmd/podman/stop.go
+++ b/cmd/podman/stop.go
@@ -42,8 +42,6 @@ func init() {
flags.BoolVarP(&stopCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
flags.UintVar(&stopCommand.Timeout, "time", libpod.CtrRemoveTimeout, "Seconds to wait for stop before killing the container")
flags.UintVarP(&stopCommand.Timeout, "timeout", "t", libpod.CtrRemoveTimeout, "Seconds to wait for stop before killing the container")
-
- rootCmd.AddCommand(stopCommand.Command)
}
func stopCmd(c *cliconfig.StopValues) error {
diff --git a/cmd/podman/system.go b/cmd/podman/system.go
index f6b28fee1..b6bc1bfef 100644
--- a/cmd/podman/system.go
+++ b/cmd/podman/system.go
@@ -17,7 +17,11 @@ var (
}
)
+var systemCommands = []*cobra.Command{
+ _infoCommand,
+}
+
func init() {
+ systemCommand.AddCommand(systemCommands...)
systemCommand.AddCommand(getSystemSubCommands()...)
- rootCmd.AddCommand(systemCommand.Command)
}
diff --git a/cmd/podman/tag.go b/cmd/podman/tag.go
index 2c7cf4abb..fdd29fc83 100644
--- a/cmd/podman/tag.go
+++ b/cmd/podman/tag.go
@@ -26,8 +26,6 @@ var (
func init() {
tagCommand.Command = _tagCommand
- rootCmd.AddCommand(tagCommand.Command)
-
}
func tagCmd(c *cliconfig.TagValues) error {
diff --git a/cmd/podman/top.go b/cmd/podman/top.go
index a03830ee5..8555f701e 100644
--- a/cmd/podman/top.go
+++ b/cmd/podman/top.go
@@ -52,8 +52,6 @@ func init() {
flags.BoolVar(&topCommand.ListDescriptors, "list-descriptors", false, "")
flags.MarkHidden("list-descriptors")
flags.BoolVarP(&topCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
-
- rootCmd.AddCommand(topCommand.Command)
}
func topCmd(c *cliconfig.TopValues) error {
diff --git a/cmd/podman/umount.go b/cmd/podman/umount.go
index 4622e8276..453560641 100644
--- a/cmd/podman/umount.go
+++ b/cmd/podman/umount.go
@@ -41,8 +41,6 @@ func init() {
flags.BoolVarP(&umountCommand.All, "all", "a", false, "Umount all of the currently mounted containers")
flags.BoolVarP(&umountCommand.Force, "force", "f", false, "Force the complete umount all of the currently mounted containers")
flags.BoolVarP(&umountCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
-
- rootCmd.AddCommand(umountCommand.Command)
}
func umountCmd(c *cliconfig.UmountValues) error {
diff --git a/cmd/podman/unpause.go b/cmd/podman/unpause.go
index fb3a7b57a..de4e71ad9 100644
--- a/cmd/podman/unpause.go
+++ b/cmd/podman/unpause.go
@@ -37,8 +37,6 @@ func init() {
unpauseCommand.Command = _unpauseCommand
flags := unpauseCommand.Flags()
flags.BoolVarP(&unpauseCommand.All, "all", "a", false, "Unpause all paused containers")
-
- rootCmd.AddCommand(unpauseCommand.Command)
}
func unpauseCmd(c *cliconfig.UnpauseValues) error {
diff --git a/cmd/podman/varlink.go b/cmd/podman/varlink.go
index 2b76e034e..73ffcdb3f 100644
--- a/cmd/podman/varlink.go
+++ b/cmd/podman/varlink.go
@@ -1,4 +1,4 @@
-// +build varlink
+// +build varlink,!remoteclient
package main
@@ -40,8 +40,6 @@ func init() {
varlinkCommand.Command = _varlinkCommand
flags := varlinkCommand.Flags()
flags.Int64VarP(&varlinkCommand.Timeout, "timeout", "t", 1000, "Time until the varlink session expires in milliseconds. Use 0 to disable the timeout")
-
- rootCmd.AddCommand(varlinkCommand.Command)
}
func varlinkCmd(c *cliconfig.VarlinkValues) error {
diff --git a/cmd/podman/version.go b/cmd/podman/version.go
index 0e7cd43d5..766dfdc0b 100644
--- a/cmd/podman/version.go
+++ b/cmd/podman/version.go
@@ -30,7 +30,6 @@ func init() {
versionCommand.Command = _versionCommand
flags := versionCommand.Flags()
flags.StringVarP(&versionCommand.Format, "format", "f", "", "Change the output format to JSON or a Go template")
- rootCmd.AddCommand(versionCommand.Command)
}
// versionCmd gets and prints version info for version command
diff --git a/cmd/podman/volume.go b/cmd/podman/volume.go
index bae778e52..d63db82e4 100644
--- a/cmd/podman/volume.go
+++ b/cmd/podman/volume.go
@@ -19,5 +19,4 @@ var volumeCommand = cliconfig.PodmanCommand{
func init() {
volumeCommand.AddCommand(getVolumeSubCommands()...)
- rootCmd.AddCommand(volumeCommand.Command)
}
diff --git a/cmd/podman/wait.go b/cmd/podman/wait.go
index fa195b7ce..9d2441b8f 100644
--- a/cmd/podman/wait.go
+++ b/cmd/podman/wait.go
@@ -37,8 +37,6 @@ func init() {
flags := waitCommand.Flags()
flags.UintVarP(&waitCommand.Interval, "interval", "i", 250, "Milliseconds to wait before polling for completion")
flags.BoolVarP(&waitCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
-
- rootCmd.AddCommand(waitCommand.Command)
}
func waitCmd(c *cliconfig.WaitValues) error {
diff --git a/docs/podman-rm.1.md b/docs/podman-rm.1.md
index 4fcb0b6c5..f4513c2be 100644
--- a/docs/podman-rm.1.md
+++ b/docs/podman-rm.1.md
@@ -17,7 +17,9 @@ Remove all containers. Can be used in conjunction with -f as well.
**--force, f**
-Force the removal of a running and paused containers
+Force the removal of running and paused containers. Forcing a containers removal also
+removes containers from container storage even if the container is not known to podman.
+Containers could have been created by a different container engine.
**--latest, -l**
diff --git a/docs/podman-stats.1.md b/docs/podman-stats.1.md
index 8fc765326..d0b56b2e6 100644
--- a/docs/podman-stats.1.md
+++ b/docs/podman-stats.1.md
@@ -36,16 +36,17 @@ Valid placeholders for the Go template are listed below:
| **Placeholder** | **Description** |
| --------------- | --------------- |
-| .ID | Container ID |
+| .Pod | Pod ID |
+| .CID | Container ID |
| .Name | Container Name |
-| .CPUPerc | CPU percentage |
+| .CPU | CPU percentage |
| .MemUsage | Memory usage |
-| .MemPerc | Memory percentage |
+| .Mem | Memory percentage |
| .NetIO | Network IO |
| .BlockIO | Block IO |
| .PIDS | Number of PIDs |
-
+When using a GO template, you may preceed the format with `table` to print headers.
## EXAMPLE
```
diff --git a/libpod/errors.go b/libpod/errors.go
index d6614141c..30a19d30f 100644
--- a/libpod/errors.go
+++ b/libpod/errors.go
@@ -2,15 +2,20 @@ package libpod
import (
"errors"
+
+ "github.com/containers/libpod/libpod/image"
)
var (
// ErrNoSuchCtr indicates the requested container does not exist
- ErrNoSuchCtr = errors.New("no such container")
+ ErrNoSuchCtr = image.ErrNoSuchCtr
+
// ErrNoSuchPod indicates the requested pod does not exist
- ErrNoSuchPod = errors.New("no such pod")
+ ErrNoSuchPod = image.ErrNoSuchPod
+
// ErrNoSuchImage indicates the requested image does not exist
- ErrNoSuchImage = errors.New("no such image")
+ ErrNoSuchImage = image.ErrNoSuchImage
+
// ErrNoSuchVolume indicates the requested volume does not exist
ErrNoSuchVolume = errors.New("no such volume")
diff --git a/libpod/kube.go b/libpod/kube.go
index f34805e39..16cebf99b 100644
--- a/libpod/kube.go
+++ b/libpod/kube.go
@@ -401,7 +401,7 @@ func capAddDrop(caps *specs.LinuxCapabilities) (*v1.Capabilities, error) {
func generateKubeSecurityContext(c *Container) (*v1.SecurityContext, error) {
priv := c.Privileged()
ro := c.IsReadOnly()
- allowPrivEscalation := !c.Spec().Process.NoNewPrivileges
+ allowPrivEscalation := !c.config.Spec.Process.NoNewPrivileges
newCaps, err := capAddDrop(c.config.Spec.Process.Capabilities)
if err != nil {
@@ -421,7 +421,13 @@ func generateKubeSecurityContext(c *Container) (*v1.SecurityContext, error) {
}
if c.User() != "" {
- // It is *possible* that
+ if !c.batched {
+ c.lock.Lock()
+ defer c.lock.Unlock()
+ }
+ if err := c.syncContainer(); err != nil {
+ return nil, errors.Wrapf(err, "unable to sync container during YAML generation")
+ }
logrus.Debugf("Looking in container for user: %s", c.User())
u, err := lookup.GetUser(c.state.Mountpoint, c.User())
if err != nil {
diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go
index 9afdef7b6..4f8192198 100644
--- a/libpod/runtime_ctr.go
+++ b/libpod/runtime_ctr.go
@@ -10,7 +10,9 @@ import (
"strings"
"time"
+ "github.com/containers/libpod/libpod/image"
"github.com/containers/libpod/pkg/rootless"
+ "github.com/containers/storage"
"github.com/containers/storage/pkg/stringid"
spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
@@ -564,3 +566,16 @@ func (r *Runtime) Export(name string, path string) error {
return ctr.Export(path)
}
+
+// RemoveContainersFromStorage attempt to remove containers from storage that do not exist in libpod database
+func (r *Runtime) RemoveContainersFromStorage(ctrs []string) {
+ for _, i := range ctrs {
+ // if the container does not exist in database, attempt to remove it from storage
+ if _, err := r.LookupContainer(i); err != nil && errors.Cause(err) == image.ErrNoSuchCtr {
+ r.storageService.UnmountContainerImage(i, true)
+ if err := r.storageService.DeleteContainer(i); err != nil && errors.Cause(err) != storage.ErrContainerUnknown {
+ logrus.Errorf("Failed to remove container %q from storage: %s", i, err)
+ }
+ }
+ }
+}
diff --git a/test/e2e/pod_stats_test.go b/test/e2e/pod_stats_test.go
index 43d089a24..e330c3a39 100644
--- a/test/e2e/pod_stats_test.go
+++ b/test/e2e/pod_stats_test.go
@@ -147,5 +147,28 @@ var _ = Describe("Podman pod stats", func() {
Expect(stats.ExitCode()).To(Equal(0))
Expect(stats.IsJSONOutputValid()).To(BeTrue())
})
+ It("podman stats with GO template", func() {
+ _, ec, podid := podmanTest.CreatePod("")
+ Expect(ec).To(Equal(0))
+
+ session := podmanTest.RunTopContainerInPod("", podid)
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ stats := podmanTest.Podman([]string{"pod", "stats", "-a", "--no-reset", "--no-stream", "--format", "\"table {{.CID}} {{.Pod}} {{.Mem}} {{.MemUsage}} {{.CPU}} {{.NetIO}} {{.BlockIO}} {{.PIDS}} {{.Pod}}\""})
+ stats.WaitWithDefaultTimeout()
+ Expect(stats.ExitCode()).To(Equal(0))
+ })
+
+ It("podman stats with invalid GO template", func() {
+ _, ec, podid := podmanTest.CreatePod("")
+ Expect(ec).To(Equal(0))
+
+ session := podmanTest.RunTopContainerInPod("", podid)
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ stats := podmanTest.Podman([]string{"pod", "stats", "-a", "--no-reset", "--no-stream", "--format", "\"table {{.ID}} \""})
+ stats.WaitWithDefaultTimeout()
+ Expect(stats.ExitCode()).ToNot(Equal(0))
+ })
})