mirror of
https://github.com/containers/podman.git
synced 2025-07-02 08:47:43 +08:00
Shortcut for most recent container
It is desirable to have a shortcut for the most recently created container. We can now use "**latest" to represent the most recent container instead of its container ID or name. For example: Signed-off-by: baude <bbaude@redhat.com> Closes: #179 Approved by: baude
This commit is contained in:
@ -19,6 +19,7 @@ var (
|
|||||||
Name: "no-stdin",
|
Name: "no-stdin",
|
||||||
Usage: "Do not attach STDIN. The default is false.",
|
Usage: "Do not attach STDIN. The default is false.",
|
||||||
},
|
},
|
||||||
|
LatestFlag,
|
||||||
}
|
}
|
||||||
attachDescription = "The podman attach command allows you to attach to a running container using the container's ID or name, either to view its ongoing output or to control it interactively."
|
attachDescription = "The podman attach command allows you to attach to a running container using the container's ID or name, either to view its ongoing output or to control it interactively."
|
||||||
attachCommand = cli.Command{
|
attachCommand = cli.Command{
|
||||||
@ -33,12 +34,12 @@ var (
|
|||||||
|
|
||||||
func attachCmd(c *cli.Context) error {
|
func attachCmd(c *cli.Context) error {
|
||||||
args := c.Args()
|
args := c.Args()
|
||||||
|
var ctr *libpod.Container
|
||||||
if err := validateFlags(c, attachFlags); err != nil {
|
if err := validateFlags(c, attachFlags); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if len(c.Args()) > 1 || (len(c.Args()) == 0 && !c.Bool("latest")) {
|
||||||
if len(c.Args()) < 1 || len(c.Args()) > 1 {
|
return errors.Errorf("attach requires the name or id of one running container or the latest flag")
|
||||||
return errors.Errorf("attach requires the name or id of one running container")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
runtime, err := getRuntime(c)
|
runtime, err := getRuntime(c)
|
||||||
@ -47,7 +48,11 @@ func attachCmd(c *cli.Context) error {
|
|||||||
}
|
}
|
||||||
defer runtime.Shutdown(false)
|
defer runtime.Shutdown(false)
|
||||||
|
|
||||||
ctr, err := runtime.LookupContainer(args[0])
|
if c.Bool("latest") {
|
||||||
|
ctr, err = runtime.GetLatestContainer()
|
||||||
|
} else {
|
||||||
|
ctr, err = runtime.LookupContainer(args[0])
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "unable to exec into %s", args[0])
|
return errors.Wrapf(err, "unable to exec into %s", args[0])
|
||||||
|
@ -14,6 +14,14 @@ import (
|
|||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
stores = make(map[storage.Store]struct{})
|
||||||
|
LatestFlag = cli.BoolFlag{
|
||||||
|
Name: "latest, l",
|
||||||
|
Usage: "act on the latest container podman is aware of",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
const crioConfigPath = "/etc/crio/crio.conf"
|
const crioConfigPath = "/etc/crio/crio.conf"
|
||||||
|
|
||||||
func getRuntime(c *cli.Context) (*libpod.Runtime, error) {
|
func getRuntime(c *cli.Context) (*libpod.Runtime, error) {
|
||||||
|
@ -27,6 +27,7 @@ var (
|
|||||||
Name: "user, u",
|
Name: "user, u",
|
||||||
Usage: "Sets the username or UID used and optionally the groupname or GID for the specified command",
|
Usage: "Sets the username or UID used and optionally the groupname or GID for the specified command",
|
||||||
},
|
},
|
||||||
|
LatestFlag,
|
||||||
}
|
}
|
||||||
execDescription = `
|
execDescription = `
|
||||||
podman exec
|
podman exec
|
||||||
@ -48,20 +49,30 @@ var (
|
|||||||
func execCmd(c *cli.Context) error {
|
func execCmd(c *cli.Context) error {
|
||||||
var envs []string
|
var envs []string
|
||||||
args := c.Args()
|
args := c.Args()
|
||||||
if len(args) < 1 {
|
var ctr *libpod.Container
|
||||||
|
var err error
|
||||||
|
argStart := 1
|
||||||
|
if len(args) < 1 && !c.Bool("latest") {
|
||||||
return errors.Errorf("you must provide one container name or id")
|
return errors.Errorf("you must provide one container name or id")
|
||||||
}
|
}
|
||||||
if len(args) < 2 {
|
if len(args) < 2 && !c.Bool("latest") {
|
||||||
return errors.Errorf("you must provide a command to exec")
|
return errors.Errorf("you must provide a command to exec")
|
||||||
}
|
}
|
||||||
cmd := args[1:]
|
if c.Bool("latest") {
|
||||||
|
argStart = 0
|
||||||
|
}
|
||||||
|
cmd := args[argStart:]
|
||||||
runtime, err := getRuntime(c)
|
runtime, err := getRuntime(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "error creating libpod runtime")
|
return errors.Wrapf(err, "error creating libpod runtime")
|
||||||
}
|
}
|
||||||
defer runtime.Shutdown(false)
|
defer runtime.Shutdown(false)
|
||||||
|
|
||||||
ctr, err := runtime.LookupContainer(args[0])
|
if c.Bool("latest") {
|
||||||
|
ctr, err = runtime.GetLatestContainer()
|
||||||
|
} else {
|
||||||
|
ctr, err = runtime.LookupContainer(args[0])
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "unable to exec into %s", args[0])
|
return errors.Wrapf(err, "unable to exec into %s", args[0])
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,7 @@ var (
|
|||||||
Name: "size",
|
Name: "size",
|
||||||
Usage: "Display total file size if the type is container",
|
Usage: "Display total file size if the type is container",
|
||||||
},
|
},
|
||||||
|
LatestFlag,
|
||||||
}
|
}
|
||||||
inspectDescription = "This displays the low-level information on containers and images identified by name or ID. By default, this will render all results in a JSON array. If the container and image have the same name, this will return container JSON for unspecified type."
|
inspectDescription = "This displays the low-level information on containers and images identified by name or ID. By default, this will render all results in a JSON array. If the container and image have the same name, this will return container JSON for unspecified type."
|
||||||
inspectCommand = cli.Command{
|
inspectCommand = cli.Command{
|
||||||
@ -47,7 +48,10 @@ var (
|
|||||||
|
|
||||||
func inspectCmd(c *cli.Context) error {
|
func inspectCmd(c *cli.Context) error {
|
||||||
args := c.Args()
|
args := c.Args()
|
||||||
if len(args) == 0 {
|
inspectType := c.String("type")
|
||||||
|
latestContainer := c.Bool("latest")
|
||||||
|
var name string
|
||||||
|
if len(args) == 0 && !latestContainer {
|
||||||
return errors.Errorf("container or image name must be specified: podman inspect [options [...]] name")
|
return errors.Errorf("container or image name must be specified: podman inspect [options [...]] name")
|
||||||
}
|
}
|
||||||
if len(args) > 1 {
|
if len(args) > 1 {
|
||||||
@ -63,17 +67,26 @@ func inspectCmd(c *cli.Context) error {
|
|||||||
}
|
}
|
||||||
defer runtime.Shutdown(false)
|
defer runtime.Shutdown(false)
|
||||||
|
|
||||||
if c.String("type") != inspectTypeContainer && c.String("type") != inspectTypeImage && c.String("type") != inspectAll {
|
if !libpod.StringInSlice(inspectType, []string{inspectTypeContainer, inspectTypeImage, inspectAll}) {
|
||||||
return errors.Errorf("the only recognized types are %q, %q, and %q", inspectTypeContainer, inspectTypeImage, inspectAll)
|
return errors.Errorf("the only recognized types are %q, %q, and %q", inspectTypeContainer, inspectTypeImage, inspectAll)
|
||||||
}
|
}
|
||||||
|
if !latestContainer {
|
||||||
name := args[0]
|
name = args[0]
|
||||||
|
}
|
||||||
|
if latestContainer {
|
||||||
|
inspectType = inspectTypeContainer
|
||||||
|
}
|
||||||
outputFormat := c.String("format")
|
outputFormat := c.String("format")
|
||||||
var data interface{}
|
var data interface{}
|
||||||
switch c.String("type") {
|
switch inspectType {
|
||||||
case inspectTypeContainer:
|
case inspectTypeContainer:
|
||||||
ctr, err := runtime.LookupContainer(name)
|
var ctr *libpod.Container
|
||||||
|
var err error
|
||||||
|
if latestContainer {
|
||||||
|
ctr, err = runtime.GetLatestContainer()
|
||||||
|
} else {
|
||||||
|
ctr, err = runtime.LookupContainer(name)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "error looking up container %q", name)
|
return errors.Wrapf(err, "error looking up container %q", name)
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"os"
|
"os"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
|
"fmt"
|
||||||
"github.com/docker/docker/pkg/signal"
|
"github.com/docker/docker/pkg/signal"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
@ -17,24 +17,29 @@ var (
|
|||||||
Usage: "Signal to send to the container",
|
Usage: "Signal to send to the container",
|
||||||
Value: "KILL",
|
Value: "KILL",
|
||||||
},
|
},
|
||||||
|
LatestFlag,
|
||||||
}
|
}
|
||||||
killDescription = "The main process inside each container specified will be sent SIGKILL, or any signal specified with option --signal."
|
killDescription = "The main process inside each container specified will be sent SIGKILL, or any signal specified with option --signal."
|
||||||
killCommand = cli.Command{
|
killCommand = cli.Command{
|
||||||
Name: "kill",
|
Name: "kill",
|
||||||
Usage: "Kill one or more running containers with a specific signal",
|
Usage: "Kill one or more running containers with a specific signal",
|
||||||
Description: killDescription,
|
Description: killDescription,
|
||||||
Flags: killFlags,
|
Flags: killFlags,
|
||||||
Action: killCmd,
|
Action: killCmd,
|
||||||
ArgsUsage: "[CONTAINER_NAME_OR_ID]",
|
ArgsUsage: "[CONTAINER_NAME_OR_ID]",
|
||||||
|
UseShortOptionHandling: true,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// killCmd kills one or more containers with a signal
|
// killCmd kills one or more containers with a signal
|
||||||
func killCmd(c *cli.Context) error {
|
func killCmd(c *cli.Context) error {
|
||||||
args := c.Args()
|
args := c.Args()
|
||||||
if len(args) == 0 {
|
if len(args) == 0 && !c.Bool("latest") {
|
||||||
return errors.Errorf("specify one or more containers to kill")
|
return errors.Errorf("specify one or more containers to kill")
|
||||||
}
|
}
|
||||||
|
if len(args) > 0 && c.Bool("latest") {
|
||||||
|
return errors.Errorf("you cannot specific any containers to kill with --latest")
|
||||||
|
}
|
||||||
if err := validateFlags(c, killFlags); err != nil {
|
if err := validateFlags(c, killFlags); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -56,8 +61,16 @@ func killCmd(c *cli.Context) error {
|
|||||||
killSignal = uint(sysSignal)
|
killSignal = uint(sysSignal)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if c.Bool("latest") {
|
||||||
|
latestCtr, err := runtime.GetLatestContainer()
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "unable to get latest container")
|
||||||
|
}
|
||||||
|
args = append(args, latestCtr.ID())
|
||||||
|
}
|
||||||
|
|
||||||
var lastError error
|
var lastError error
|
||||||
for _, container := range c.Args() {
|
for _, container := range args {
|
||||||
ctr, err := runtime.LookupContainer(container)
|
ctr, err := runtime.LookupContainer(container)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if lastError != nil {
|
if lastError != nil {
|
||||||
|
@ -37,6 +37,7 @@ var (
|
|||||||
Name: "tail",
|
Name: "tail",
|
||||||
Usage: "Output the specified number of LINES at the end of the logs. Defaults to 0, which prints all lines",
|
Usage: "Output the specified number of LINES at the end of the logs. Defaults to 0, which prints all lines",
|
||||||
},
|
},
|
||||||
|
LatestFlag,
|
||||||
}
|
}
|
||||||
logsDescription = "The podman logs command batch-retrieves whatever logs are present for a container at the time of execution. This does not guarantee execution" +
|
logsDescription = "The podman logs command batch-retrieves whatever logs are present for a container at the time of execution. This does not guarantee execution" +
|
||||||
"order when combined with podman run (i.e. your run may not have generated any logs at the time you execute podman logs"
|
"order when combined with podman run (i.e. your run may not have generated any logs at the time you execute podman logs"
|
||||||
@ -51,6 +52,8 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func logsCmd(c *cli.Context) error {
|
func logsCmd(c *cli.Context) error {
|
||||||
|
var ctr *libpod.Container
|
||||||
|
var err error
|
||||||
if err := validateFlags(c, logsFlags); err != nil {
|
if err := validateFlags(c, logsFlags); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -62,7 +65,7 @@ func logsCmd(c *cli.Context) error {
|
|||||||
defer runtime.Shutdown(false)
|
defer runtime.Shutdown(false)
|
||||||
|
|
||||||
args := c.Args()
|
args := c.Args()
|
||||||
if len(args) != 1 {
|
if len(args) != 1 && !c.Bool("latest") {
|
||||||
return errors.Errorf("'podman logs' requires exactly one container name/ID")
|
return errors.Errorf("'podman logs' requires exactly one container name/ID")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,7 +86,11 @@ func logsCmd(c *cli.Context) error {
|
|||||||
tail: c.Uint64("tail"),
|
tail: c.Uint64("tail"),
|
||||||
}
|
}
|
||||||
|
|
||||||
ctr, err := runtime.LookupContainer(args[0])
|
if c.Bool("latest") {
|
||||||
|
ctr, err = runtime.GetLatestContainer()
|
||||||
|
} else {
|
||||||
|
ctr, err = runtime.LookupContainer(args[0])
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ var (
|
|||||||
Name: "all, a",
|
Name: "all, a",
|
||||||
Usage: "Remove all containers",
|
Usage: "Remove all containers",
|
||||||
},
|
},
|
||||||
|
LatestFlag,
|
||||||
}
|
}
|
||||||
rmDescription = "Remove one or more containers"
|
rmDescription = "Remove one or more containers"
|
||||||
rmCommand = cli.Command{
|
rmCommand = cli.Command{
|
||||||
@ -46,7 +47,11 @@ func rmCmd(c *cli.Context) error {
|
|||||||
defer runtime.Shutdown(false)
|
defer runtime.Shutdown(false)
|
||||||
|
|
||||||
args := c.Args()
|
args := c.Args()
|
||||||
if len(args) == 0 && !c.Bool("all") {
|
if c.Bool("latest") && c.Bool("all") {
|
||||||
|
return errors.Errorf("--all and --latest cannot be used together")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(args) == 0 && !c.Bool("all") && !c.Bool("latest") {
|
||||||
return errors.Errorf("specify one or more containers to remove")
|
return errors.Errorf("specify one or more containers to remove")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,6 +62,12 @@ func rmCmd(c *cli.Context) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "unable to get container list")
|
return errors.Wrapf(err, "unable to get container list")
|
||||||
}
|
}
|
||||||
|
} else if c.Bool("latest") {
|
||||||
|
lastCtr, err := runtime.GetLatestContainer()
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "unable to get latest container")
|
||||||
|
}
|
||||||
|
delContainers = append(delContainers, lastCtr)
|
||||||
} else {
|
} else {
|
||||||
for _, i := range args {
|
for _, i := range args {
|
||||||
container, err := runtime.LookupContainer(i)
|
container, err := runtime.LookupContainer(i)
|
||||||
|
@ -26,6 +26,7 @@ var (
|
|||||||
Name: "interactive, i",
|
Name: "interactive, i",
|
||||||
Usage: "Keep STDIN open even if not attached",
|
Usage: "Keep STDIN open even if not attached",
|
||||||
},
|
},
|
||||||
|
LatestFlag,
|
||||||
}
|
}
|
||||||
startDescription = `
|
startDescription = `
|
||||||
podman start
|
podman start
|
||||||
@ -46,7 +47,7 @@ var (
|
|||||||
|
|
||||||
func startCmd(c *cli.Context) error {
|
func startCmd(c *cli.Context) error {
|
||||||
args := c.Args()
|
args := c.Args()
|
||||||
if len(args) < 1 {
|
if len(args) < 1 && !c.Bool("latest") {
|
||||||
return errors.Errorf("you must provide at least one container name or id")
|
return errors.Errorf("you must provide at least one container name or id")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,7 +66,13 @@ func startCmd(c *cli.Context) error {
|
|||||||
return errors.Wrapf(err, "error creating libpod runtime")
|
return errors.Wrapf(err, "error creating libpod runtime")
|
||||||
}
|
}
|
||||||
defer runtime.Shutdown(false)
|
defer runtime.Shutdown(false)
|
||||||
|
if c.Bool("latest") {
|
||||||
|
lastCtr, err := runtime.GetLatestContainer()
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "unable to get latest container")
|
||||||
|
}
|
||||||
|
args = append(args, lastCtr.ID())
|
||||||
|
}
|
||||||
var lastError error
|
var lastError error
|
||||||
for _, container := range args {
|
for _, container := range args {
|
||||||
// Create a bool channel to track that the console socket attach
|
// Create a bool channel to track that the console socket attach
|
||||||
|
@ -42,7 +42,7 @@ var (
|
|||||||
cli.BoolFlag{
|
cli.BoolFlag{
|
||||||
Name: "no-reset",
|
Name: "no-reset",
|
||||||
Usage: "disable resetting the screen between intervals",
|
Usage: "disable resetting the screen between intervals",
|
||||||
},
|
}, LatestFlag,
|
||||||
}
|
}
|
||||||
|
|
||||||
statsDescription = "display a live stream of one or more containers' resource usage statistics"
|
statsDescription = "display a live stream of one or more containers' resource usage statistics"
|
||||||
@ -61,6 +61,15 @@ func statsCmd(c *cli.Context) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
all := c.Bool("all")
|
||||||
|
|
||||||
|
if c.Bool("latest") && all {
|
||||||
|
return errors.Errorf("--all and --latest cannot be used together")
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.Bool("latest") && len(c.Args()) > 0 {
|
||||||
|
return errors.Errorf("no container names are allowed with --latest")
|
||||||
|
}
|
||||||
runtime, err := getRuntime(c)
|
runtime, err := getRuntime(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "could not get runtime")
|
return errors.Wrapf(err, "could not get runtime")
|
||||||
@ -75,7 +84,6 @@ func statsCmd(c *cli.Context) error {
|
|||||||
var format string
|
var format string
|
||||||
var ctrs []*libpod.Container
|
var ctrs []*libpod.Container
|
||||||
var containerFunc func() ([]*libpod.Container, error)
|
var containerFunc func() ([]*libpod.Container, error)
|
||||||
all := c.Bool("all")
|
|
||||||
|
|
||||||
if c.IsSet("format") {
|
if c.IsSet("format") {
|
||||||
format = c.String("format")
|
format = c.String("format")
|
||||||
@ -85,6 +93,13 @@ func statsCmd(c *cli.Context) error {
|
|||||||
|
|
||||||
if len(c.Args()) > 0 {
|
if len(c.Args()) > 0 {
|
||||||
containerFunc = func() ([]*libpod.Container, error) { return runtime.GetContainersByList(c.Args()) }
|
containerFunc = func() ([]*libpod.Container, error) { return runtime.GetContainersByList(c.Args()) }
|
||||||
|
} else if c.Bool("latest") {
|
||||||
|
containerFunc = func() ([]*libpod.Container, error) {
|
||||||
|
var ctrs []*libpod.Container
|
||||||
|
lastCtr, err := runtime.GetLatestContainer()
|
||||||
|
ctrs = append(ctrs, lastCtr)
|
||||||
|
return ctrs, err
|
||||||
|
}
|
||||||
} else if all {
|
} else if all {
|
||||||
containerFunc = runtime.GetAllContainers
|
containerFunc = runtime.GetAllContainers
|
||||||
} else {
|
} else {
|
||||||
|
@ -19,7 +19,7 @@ var (
|
|||||||
cli.BoolFlag{
|
cli.BoolFlag{
|
||||||
Name: "all, a",
|
Name: "all, a",
|
||||||
Usage: "stop all running containers",
|
Usage: "stop all running containers",
|
||||||
},
|
}, LatestFlag,
|
||||||
}
|
}
|
||||||
stopDescription = `
|
stopDescription = `
|
||||||
podman stop
|
podman stop
|
||||||
@ -41,10 +41,13 @@ var (
|
|||||||
|
|
||||||
func stopCmd(c *cli.Context) error {
|
func stopCmd(c *cli.Context) error {
|
||||||
args := c.Args()
|
args := c.Args()
|
||||||
if c.Bool("all") && len(args) > 0 {
|
if (c.Bool("all") || c.Bool("latest")) && len(args) > 0 {
|
||||||
return errors.Errorf("no arguments are needed with -a")
|
return errors.Errorf("no arguments are needed with --all or --latest")
|
||||||
}
|
}
|
||||||
if len(args) < 1 && !c.Bool("all") {
|
if c.Bool("all") && c.Bool("latest") {
|
||||||
|
return errors.Errorf("--all and --latest cannot be used together")
|
||||||
|
}
|
||||||
|
if len(args) < 1 && !c.Bool("all") && !c.Bool("latest") {
|
||||||
return errors.Errorf("you must provide at least one container name or id")
|
return errors.Errorf("you must provide at least one container name or id")
|
||||||
}
|
}
|
||||||
if err := validateFlags(c, stopFlags); err != nil {
|
if err := validateFlags(c, stopFlags); err != nil {
|
||||||
@ -71,6 +74,12 @@ func stopCmd(c *cli.Context) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "unable to get running containers")
|
return errors.Wrapf(err, "unable to get running containers")
|
||||||
}
|
}
|
||||||
|
} else if c.Bool("latest") {
|
||||||
|
lastCtr, err := runtime.GetLatestContainer()
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "unable to get last created container")
|
||||||
|
}
|
||||||
|
containers = append(containers, lastCtr)
|
||||||
} else {
|
} else {
|
||||||
for _, i := range args {
|
for _, i := range args {
|
||||||
container, err := runtime.LookupContainer(i)
|
container, err := runtime.LookupContainer(i)
|
||||||
|
@ -16,7 +16,7 @@ var (
|
|||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "format",
|
Name: "format",
|
||||||
Usage: "Change the output to JSON",
|
Usage: "Change the output to JSON",
|
||||||
},
|
}, LatestFlag,
|
||||||
}
|
}
|
||||||
topDescription = `
|
topDescription = `
|
||||||
podman top
|
podman top
|
||||||
@ -36,6 +36,8 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func topCmd(c *cli.Context) error {
|
func topCmd(c *cli.Context) error {
|
||||||
|
var container *libpod.Container
|
||||||
|
var err error
|
||||||
doJSON := false
|
doJSON := false
|
||||||
if c.IsSet("format") {
|
if c.IsSet("format") {
|
||||||
if strings.ToUpper(c.String("format")) == "JSON" {
|
if strings.ToUpper(c.String("format")) == "JSON" {
|
||||||
@ -47,7 +49,7 @@ func topCmd(c *cli.Context) error {
|
|||||||
args := c.Args()
|
args := c.Args()
|
||||||
var psArgs []string
|
var psArgs []string
|
||||||
psOpts := []string{"-o", "uid,pid,ppid,c,stime,tname,time,cmd"}
|
psOpts := []string{"-o", "uid,pid,ppid,c,stime,tname,time,cmd"}
|
||||||
if len(args) < 1 {
|
if len(args) < 1 && !c.Bool("latest") {
|
||||||
return errors.Errorf("you must provide the name or id of a running container")
|
return errors.Errorf("you must provide the name or id of a running container")
|
||||||
}
|
}
|
||||||
if err := validateFlags(c, topFlags); err != nil {
|
if err := validateFlags(c, topFlags); err != nil {
|
||||||
@ -63,7 +65,12 @@ func topCmd(c *cli.Context) error {
|
|||||||
psOpts = args[1:]
|
psOpts = args[1:]
|
||||||
}
|
}
|
||||||
|
|
||||||
container, err := runtime.LookupContainer(args[0])
|
if c.Bool("latest") {
|
||||||
|
container, err = runtime.GetLatestContainer()
|
||||||
|
} else {
|
||||||
|
container, err = runtime.LookupContainer(args[0])
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "unable to lookup %s", args[0])
|
return errors.Wrapf(err, "unable to lookup %s", args[0])
|
||||||
}
|
}
|
||||||
|
@ -653,7 +653,10 @@ _podman_attach() {
|
|||||||
local boolean_options="
|
local boolean_options="
|
||||||
--help
|
--help
|
||||||
-h
|
-h
|
||||||
--no-stdin"
|
--latest
|
||||||
|
-l
|
||||||
|
--no-stdin
|
||||||
|
"
|
||||||
_complete_ "$options_with_args" "$boolean_options"
|
_complete_ "$options_with_args" "$boolean_options"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -752,6 +755,8 @@ _podman_exec() {
|
|||||||
-u
|
-u
|
||||||
"
|
"
|
||||||
local boolean_options="
|
local boolean_options="
|
||||||
|
--latest
|
||||||
|
-l
|
||||||
--privileged
|
--privileged
|
||||||
--tty
|
--tty
|
||||||
-t
|
-t
|
||||||
@ -875,6 +880,8 @@ _podman_inspect() {
|
|||||||
local boolean_options="
|
local boolean_options="
|
||||||
--help
|
--help
|
||||||
-h
|
-h
|
||||||
|
--latest
|
||||||
|
-l
|
||||||
"
|
"
|
||||||
local options_with_args="
|
local options_with_args="
|
||||||
--format
|
--format
|
||||||
@ -898,7 +905,10 @@ _podman_kill() {
|
|||||||
"
|
"
|
||||||
local boolean_options="
|
local boolean_options="
|
||||||
--help
|
--help
|
||||||
-h"
|
-h
|
||||||
|
--latest
|
||||||
|
-l
|
||||||
|
"
|
||||||
_complete_ "$options_with_args" "$boolean_options"
|
_complete_ "$options_with_args" "$boolean_options"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -910,6 +920,8 @@ _podman_logs() {
|
|||||||
local boolean_options="
|
local boolean_options="
|
||||||
--follow
|
--follow
|
||||||
-f
|
-f
|
||||||
|
--latest
|
||||||
|
-l
|
||||||
"
|
"
|
||||||
_complete_ "$options_with_args" "$boolean_options"
|
_complete_ "$options_with_args" "$boolean_options"
|
||||||
|
|
||||||
@ -1286,6 +1298,8 @@ _podman_rm() {
|
|||||||
-a
|
-a
|
||||||
--force
|
--force
|
||||||
-f
|
-f
|
||||||
|
--latest
|
||||||
|
-l
|
||||||
"
|
"
|
||||||
|
|
||||||
local options_with_args="
|
local options_with_args="
|
||||||
@ -1355,6 +1369,10 @@ podman_top() {
|
|||||||
local options_with_args="
|
local options_with_args="
|
||||||
"
|
"
|
||||||
local boolean_options="
|
local boolean_options="
|
||||||
|
--help
|
||||||
|
-h
|
||||||
|
--latest
|
||||||
|
-l
|
||||||
"
|
"
|
||||||
_complete_ "$options_with_args" "$boolean_options"
|
_complete_ "$options_with_args" "$boolean_options"
|
||||||
}
|
}
|
||||||
@ -1424,7 +1442,9 @@ _podman_start() {
|
|||||||
-a
|
-a
|
||||||
--attach
|
--attach
|
||||||
-i
|
-i
|
||||||
--interactive"
|
--interactive
|
||||||
|
--latest
|
||||||
|
-l"
|
||||||
_complete_ "$options_with_args" "$boolean_options"
|
_complete_ "$options_with_args" "$boolean_options"
|
||||||
}
|
}
|
||||||
_podman_stop() {
|
_podman_stop() {
|
||||||
@ -1433,7 +1453,9 @@ _podman_stop() {
|
|||||||
"
|
"
|
||||||
local boolean_options="
|
local boolean_options="
|
||||||
--all
|
--all
|
||||||
-a"
|
-a
|
||||||
|
--latest
|
||||||
|
-l"
|
||||||
_complete_ "$options_with_args" "$boolean_options"
|
_complete_ "$options_with_args" "$boolean_options"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +20,10 @@ sequence is CTRL-p CTRL-q. You configure the key sequence using the --detach-key
|
|||||||
Override the key sequence for detaching a container. Format is a single character [a-Z] or
|
Override the key sequence for detaching a container. Format is a single character [a-Z] or
|
||||||
ctrl-<value> where <value> is one of: a-z, @, ^, [, , or _.
|
ctrl-<value> where <value> is one of: a-z, @, ^, [, , or _.
|
||||||
|
|
||||||
|
**--latest, -l**
|
||||||
|
Instead of providing the container name or ID, use the last created container. If you use methods other than Podman
|
||||||
|
to run containers such as CRI-O, the last started container could be from either of those methods.
|
||||||
|
|
||||||
**--no-stdin**
|
**--no-stdin**
|
||||||
Do not attach STDIN. The default is false.
|
Do not attach STDIN. The default is false.
|
||||||
|
|
||||||
@ -30,6 +34,10 @@ podman attach foobar
|
|||||||
[root@localhost /]#
|
[root@localhost /]#
|
||||||
```
|
```
|
||||||
```
|
```
|
||||||
|
podman attach --latest
|
||||||
|
[root@localhost /]#
|
||||||
|
```
|
||||||
|
```
|
||||||
podman attach 1234
|
podman attach 1234
|
||||||
[root@localhost /]#
|
[root@localhost /]#
|
||||||
```
|
```
|
||||||
|
@ -22,6 +22,10 @@ command to be executed.
|
|||||||
**--interactive, -i**
|
**--interactive, -i**
|
||||||
Not supported. All exec commands are interactive by default.
|
Not supported. All exec commands are interactive by default.
|
||||||
|
|
||||||
|
**--latest, -l**
|
||||||
|
Instead of providing the container name or ID, use the last created container. If you use methods other than Podman
|
||||||
|
to run containers such as CRI-O, the last started container could be from either of those methods.
|
||||||
|
|
||||||
**--privileged**
|
**--privileged**
|
||||||
Give the process extended Linux capabilities when running the command in container.
|
Give the process extended Linux capabilities when running the command in container.
|
||||||
|
|
||||||
|
@ -21,6 +21,10 @@ Return data on items of the specified type. Type can be 'container', 'image' or
|
|||||||
|
|
||||||
Format the output using the given Go template
|
Format the output using the given Go template
|
||||||
|
|
||||||
|
**--latest, -l**
|
||||||
|
Instead of providing the container name or ID, use the last created container. If you use methods other than Podman
|
||||||
|
to run containers such as CRI-O, the last started container could be from either of those methods.
|
||||||
|
|
||||||
**--size**
|
**--size**
|
||||||
|
|
||||||
Display the total file size if the type is a container
|
Display the total file size if the type is a container
|
||||||
|
@ -12,6 +12,9 @@ podman kill - Kills one or more containers with a signal
|
|||||||
The main process inside each container specified will be sent SIGKILL, or any signal specified with option --signal.
|
The main process inside each container specified will be sent SIGKILL, or any signal specified with option --signal.
|
||||||
|
|
||||||
## OPTIONS
|
## OPTIONS
|
||||||
|
**--latest, -l**
|
||||||
|
Instead of providing the container name or ID, use the last created container. If you use methods other than Podman
|
||||||
|
to run containers such as CRI-O, the last started container could be from either of those methods.
|
||||||
|
|
||||||
**--signal, s**
|
**--signal, s**
|
||||||
|
|
||||||
@ -26,6 +29,8 @@ podman kill 860a4b23
|
|||||||
|
|
||||||
podman kill --signal TERM 860a4b23
|
podman kill --signal TERM 860a4b23
|
||||||
|
|
||||||
|
podman kill --latest
|
||||||
|
|
||||||
## SEE ALSO
|
## SEE ALSO
|
||||||
podman(1), podman-stop(1)
|
podman(1), podman-stop(1)
|
||||||
|
|
||||||
|
@ -21,6 +21,9 @@ Force the removal of a running container
|
|||||||
|
|
||||||
Remove all containers. Can be used in conjunction with -f as well.
|
Remove all containers. Can be used in conjunction with -f as well.
|
||||||
|
|
||||||
|
**--latest, -l**
|
||||||
|
Instead of providing the container name or ID, use the last created container. If you use methods other than Podman
|
||||||
|
to run containers such as CRI-O, the last started container could be from either of those methods.
|
||||||
## EXAMPLE
|
## EXAMPLE
|
||||||
|
|
||||||
podman rm mywebserver
|
podman rm mywebserver
|
||||||
@ -31,6 +34,8 @@ podman rm -f 860a4b23
|
|||||||
|
|
||||||
podman rm -f -a
|
podman rm -f -a
|
||||||
|
|
||||||
|
podman rm -f --latest
|
||||||
|
|
||||||
## SEE ALSO
|
## SEE ALSO
|
||||||
podman(1), podman-rmi(1)
|
podman(1), podman-rmi(1)
|
||||||
|
|
||||||
|
@ -29,6 +29,9 @@ ctrl-<value> where <value> is one of: a-z, @, ^, [, , or _.
|
|||||||
|
|
||||||
Attach container's STDIN. The default is false.
|
Attach container's STDIN. The default is false.
|
||||||
|
|
||||||
|
**--latest, -l**
|
||||||
|
Instead of providing the container name or ID, use the last created container. If you use methods other than Podman
|
||||||
|
to run containers such as CRI-O, the last started container could be from either of those methods.
|
||||||
|
|
||||||
## EXAMPLE
|
## EXAMPLE
|
||||||
|
|
||||||
@ -38,6 +41,8 @@ podman start 860a4b23 5421ab4
|
|||||||
|
|
||||||
podman start -i -a 860a4b23
|
podman start -i -a 860a4b23
|
||||||
|
|
||||||
|
podman start -i -l
|
||||||
|
|
||||||
## SEE ALSO
|
## SEE ALSO
|
||||||
podman(1), podman-create(1)
|
podman(1), podman-create(1)
|
||||||
|
|
||||||
|
@ -17,6 +17,10 @@ Display a live stream of one or more containers' resource usage statistics
|
|||||||
|
|
||||||
Show all containers. Only running containers are shown by default
|
Show all containers. Only running containers are shown by default
|
||||||
|
|
||||||
|
**--latest, -l**
|
||||||
|
Instead of providing the container name or ID, use the last created container. If you use methods other than Podman
|
||||||
|
to run containers such as CRI-O, the last started container could be from either of those methods.
|
||||||
|
|
||||||
**--no-reset**
|
**--no-reset**
|
||||||
|
|
||||||
Do not clear the terminal/screen in between reporting intervals
|
Do not clear the terminal/screen in between reporting intervals
|
||||||
|
@ -23,6 +23,9 @@ Timeout to wait before forcibly stopping the container
|
|||||||
|
|
||||||
Stop all running containers. This does not include paused containers.
|
Stop all running containers. This does not include paused containers.
|
||||||
|
|
||||||
|
**--latest, -l**
|
||||||
|
Instead of providing the container name or ID, use the last created container. If you use methods other than Podman
|
||||||
|
to run containers such as CRI-O, the last started container could be from either of those methods.
|
||||||
|
|
||||||
## EXAMPLE
|
## EXAMPLE
|
||||||
|
|
||||||
@ -36,6 +39,8 @@ podman stop --timeout 2 860a4b23
|
|||||||
|
|
||||||
podman stop -a
|
podman stop -a
|
||||||
|
|
||||||
|
podman stop --latest
|
||||||
|
|
||||||
## SEE ALSO
|
## SEE ALSO
|
||||||
podman(1), podman-rm(1)
|
podman(1), podman-rm(1)
|
||||||
|
|
||||||
|
@ -21,6 +21,10 @@ Display the running process of the container. ps-OPTION can be any of the option
|
|||||||
**--format**
|
**--format**
|
||||||
Display the output in an alternate format. The only supported format is **JSON**.
|
Display the output in an alternate format. The only supported format is **JSON**.
|
||||||
|
|
||||||
|
**--latest, -l**
|
||||||
|
Instead of providing the container name or ID, use the last created container. If you use methods other than Podman
|
||||||
|
to run containers such as CRI-O, the last started container could be from either of those methods.
|
||||||
|
|
||||||
## EXAMPLES
|
## EXAMPLES
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -3,6 +3,7 @@ package libpod
|
|||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"time"
|
||||||
|
|
||||||
spec "github.com/opencontainers/runtime-spec/specs-go"
|
spec "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
@ -204,7 +205,6 @@ func (r *Runtime) LookupContainer(idOrName string) (*Container, error) {
|
|||||||
if !r.valid {
|
if !r.valid {
|
||||||
return nil, ErrRuntimeStopped
|
return nil, ErrRuntimeStopped
|
||||||
}
|
}
|
||||||
|
|
||||||
return r.state.LookupContainer(idOrName)
|
return r.state.LookupContainer(idOrName)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -268,3 +268,21 @@ func (r *Runtime) GetContainersByList(containers []string) ([]*Container, error)
|
|||||||
}
|
}
|
||||||
return ctrs, nil
|
return ctrs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetLatestContainer returns a container object of the latest created container.
|
||||||
|
func (r *Runtime) GetLatestContainer() (*Container, error) {
|
||||||
|
var lastCreatedIndex int
|
||||||
|
var lastCreatedTime time.Time
|
||||||
|
ctrs, err := r.GetAllContainers()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "unable to find latest container")
|
||||||
|
}
|
||||||
|
for containerIndex, ctr := range ctrs {
|
||||||
|
createdTime := ctr.config.CreatedTime
|
||||||
|
if createdTime.After(lastCreatedTime) {
|
||||||
|
lastCreatedTime = createdTime
|
||||||
|
lastCreatedIndex = containerIndex
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ctrs[lastCreatedIndex], nil
|
||||||
|
}
|
||||||
|
@ -28,3 +28,10 @@ function setup() {
|
|||||||
echo "$output"
|
echo "$output"
|
||||||
[ "$status" -eq 0 ]
|
[ "$status" -eq 0 ]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@test "exec simple command using latest" {
|
||||||
|
${PODMAN_BINARY} ${PODMAN_OPTIONS} run -d -t ${ALPINE} sleep 60
|
||||||
|
run ${PODMAN_BINARY} ${PODMAN_OPTIONS} exec -l ls
|
||||||
|
echo "$output"
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
}
|
||||||
|
@ -45,8 +45,7 @@ function setup() {
|
|||||||
run bash -c "${PODMAN_BINARY} ${PODMAN_OPTIONS} create ${BB} ls"
|
run bash -c "${PODMAN_BINARY} ${PODMAN_OPTIONS} create ${BB} ls"
|
||||||
echo "$output"
|
echo "$output"
|
||||||
[ "$status" -eq 0 ]
|
[ "$status" -eq 0 ]
|
||||||
ctr_id="$output"
|
run bash -c "${PODMAN_BINARY} $PODMAN_OPTIONS inspect --size -l | python -m json.tool | grep SizeRootFs"
|
||||||
run bash -c "${PODMAN_BINARY} $PODMAN_OPTIONS inspect --size $ctr_id | python -m json.tool | grep SizeRootFs"
|
|
||||||
echo "$output"
|
echo "$output"
|
||||||
[ "$status" -eq 0 ]
|
[ "$status" -eq 0 ]
|
||||||
}
|
}
|
||||||
|
@ -62,3 +62,10 @@ function setup() {
|
|||||||
run bash -c "${PODMAN_BINARY} ${PODMAN_OPTIONS} ps --no-trunc"
|
run bash -c "${PODMAN_BINARY} ${PODMAN_OPTIONS} ps --no-trunc"
|
||||||
[ "$status" -eq 0 ]
|
[ "$status" -eq 0 ]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@test "kill the latest container run" {
|
||||||
|
${PODMAN_BINARY} ${PODMAN_OPTIONS} run -d ${ALPINE} sleep 9999
|
||||||
|
run bash -c "${PODMAN_BINARY} ${PODMAN_OPTIONS} kill -l"
|
||||||
|
echo "$output"
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
}
|
||||||
|
@ -42,11 +42,10 @@ function setup() {
|
|||||||
run bash -c "${PODMAN_BINARY} ${PODMAN_OPTIONS} run -d $BB ls"
|
run bash -c "${PODMAN_BINARY} ${PODMAN_OPTIONS} run -d $BB ls"
|
||||||
echo "$output"
|
echo "$output"
|
||||||
[ "$status" -eq 0 ]
|
[ "$status" -eq 0 ]
|
||||||
ctr_id="$output"
|
run bash -c "${PODMAN_BINARY} ${PODMAN_OPTIONS} logs --since 2017-08-07T10:10:09.056611202-04:00 -l"
|
||||||
run bash -c "${PODMAN_BINARY} ${PODMAN_OPTIONS} logs --since 2017-08-07T10:10:09.056611202-04:00 $ctr_id"
|
|
||||||
echo "$output"
|
echo "$output"
|
||||||
[ "$status" -eq 0 ]
|
[ "$status" -eq 0 ]
|
||||||
run bash -c "${PODMAN_BINARY} ${PODMAN_OPTIONS} rm $ctr_id"
|
run bash -c "${PODMAN_BINARY} ${PODMAN_OPTIONS} rm -l"
|
||||||
echo "$output"
|
echo "$output"
|
||||||
[ "$status" -eq 0 ]
|
[ "$status" -eq 0 ]
|
||||||
}
|
}
|
||||||
|
@ -47,3 +47,10 @@ function setup() {
|
|||||||
echo "$output"
|
echo "$output"
|
||||||
[ "$status" -eq 0 ]
|
[ "$status" -eq 0 ]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@test "stop a container with latest" {
|
||||||
|
${PODMAN_BINARY} ${PODMAN_OPTIONS} run -d ${ALPINE} sleep 9999
|
||||||
|
run bash -c "${PODMAN_BINARY} ${PODMAN_OPTIONS} stop -t 1 -l"
|
||||||
|
echo "$output"
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user