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:
baude
2018-01-02 16:29:43 -06:00
committed by Atomic Bot
parent 6baf6e461d
commit 7b08aa78e4
27 changed files with 257 additions and 48 deletions

View File

@ -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])

View File

@ -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) {

View File

@ -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])
} }

View File

@ -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)
} }

View File

@ -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 {

View File

@ -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
} }

View File

@ -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)

View File

@ -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

View File

@ -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 {

View File

@ -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)

View File

@ -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])
} }

View File

@ -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"
} }

View File

@ -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 /]#
``` ```

View File

@ -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.

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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
``` ```

View File

@ -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
}

View File

@ -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 ]
}

View File

@ -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 ]
} }

View File

@ -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 ]
}

View File

@ -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 ]
} }

View File

@ -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 ]
}