summaryrefslogtreecommitdiff
path: root/cmd/podman/pods
diff options
context:
space:
mode:
authorBrent Baude <bbaude@redhat.com>2020-04-16 12:25:26 -0500
committerBrent Baude <bbaude@redhat.com>2020-04-16 15:53:58 -0500
commit241326a9a8c20ad7f2bcf651416b836e7778e090 (patch)
tree4001e8e47a022bb1b9bfbf2332c42e1aeb802f9e /cmd/podman/pods
parent88c6fd06cd54fb9a8826306dfdf1a77e400de5de (diff)
downloadpodman-241326a9a8c20ad7f2bcf651416b836e7778e090.tar.gz
podman-241326a9a8c20ad7f2bcf651416b836e7778e090.tar.bz2
podman-241326a9a8c20ad7f2bcf651416b836e7778e090.zip
Podman V2 birth
remote podman v1 and replace with podman v2. Signed-off-by: Brent Baude <bbaude@redhat.com>
Diffstat (limited to 'cmd/podman/pods')
-rw-r--r--cmd/podman/pods/create.go147
-rw-r--r--cmd/podman/pods/exists.go43
-rw-r--r--cmd/podman/pods/inspect.go64
-rw-r--r--cmd/podman/pods/kill.go68
-rw-r--r--cmd/podman/pods/pause.go66
-rw-r--r--cmd/podman/pods/pod.go25
-rw-r--r--cmd/podman/pods/ps.go229
-rw-r--r--cmd/podman/pods/restart.go68
-rw-r--r--cmd/podman/pods/rm.go71
-rw-r--r--cmd/podman/pods/start.go68
-rw-r--r--cmd/podman/pods/stop.go79
-rw-r--r--cmd/podman/pods/top.go86
-rw-r--r--cmd/podman/pods/unpause.go66
13 files changed, 1080 insertions, 0 deletions
diff --git a/cmd/podman/pods/create.go b/cmd/podman/pods/create.go
new file mode 100644
index 000000000..63dab4707
--- /dev/null
+++ b/cmd/podman/pods/create.go
@@ -0,0 +1,147 @@
+package pods
+
+import (
+ "context"
+ "fmt"
+ "os"
+ "strings"
+
+ "github.com/containers/libpod/cmd/podman/common"
+ "github.com/containers/libpod/cmd/podman/parse"
+ "github.com/containers/libpod/cmd/podman/registry"
+ "github.com/containers/libpod/libpod/define"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/containers/libpod/pkg/errorhandling"
+ "github.com/containers/libpod/pkg/specgen"
+ "github.com/containers/libpod/pkg/util"
+ "github.com/pkg/errors"
+ "github.com/spf13/cobra"
+)
+
+var (
+ podCreateDescription = `After creating the pod, the pod ID is printed to stdout.
+
+ You can then start it at any time with the podman pod start <pod_id> command. The pod will be created with the initial state 'created'.`
+
+ createCommand = &cobra.Command{
+ Use: "create",
+ Args: cobra.NoArgs,
+ Short: "Create a new empty pod",
+ Long: podCreateDescription,
+ RunE: create,
+ }
+)
+
+var (
+ createOptions entities.PodCreateOptions
+ labels, labelFile []string
+ podIDFile string
+ share string
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ Command: createCommand,
+ Parent: podCmd,
+ })
+ flags := createCommand.Flags()
+ flags.SetInterspersed(false)
+ flags.AddFlagSet(common.GetNetFlags())
+ flags.StringVar(&createOptions.CGroupParent, "cgroup-parent", "", "Set parent cgroup for the pod")
+ flags.BoolVar(&createOptions.Infra, "infra", true, "Create an infra container associated with the pod to share namespaces with")
+ flags.StringVar(&createOptions.InfraImage, "infra-image", define.DefaultInfraImage, "The image of the infra container to associate with the pod")
+ flags.StringVar(&createOptions.InfraCommand, "infra-command", define.DefaultInfraCommand, "The command to run on the infra container when the pod is started")
+ flags.StringSliceVar(&labelFile, "label-file", []string{}, "Read in a line delimited file of labels")
+ flags.StringSliceVarP(&labels, "label", "l", []string{}, "Set metadata on pod (default [])")
+ flags.StringVarP(&createOptions.Name, "name", "n", "", "Assign a name to the pod")
+ flags.StringVarP(&createOptions.Hostname, "hostname", "", "", "Set a hostname to the pod")
+ flags.StringVar(&podIDFile, "pod-id-file", "", "Write the pod ID to the file")
+ flags.StringVar(&share, "share", common.DefaultKernelNamespaces, "A comma delimited list of kernel namespaces the pod will share")
+}
+
+func create(cmd *cobra.Command, args []string) error {
+ var (
+ err error
+ podIdFile *os.File
+ )
+ createOptions.Labels, err = parse.GetAllLabels(labelFile, labels)
+ if err != nil {
+ return errors.Wrapf(err, "unable to process labels")
+ }
+
+ if !createOptions.Infra && cmd.Flag("share").Changed && share != "none" && share != "" {
+ return errors.Errorf("You cannot share kernel namespaces on the pod level without an infra container")
+ }
+ createOptions.Share = strings.Split(share, ",")
+ if cmd.Flag("pod-id-file").Changed {
+ podIdFile, err = util.OpenExclusiveFile(podIDFile)
+ if err != nil && os.IsExist(err) {
+ return errors.Errorf("pod id file exists. Ensure another pod is not using it or delete %s", podIDFile)
+ }
+ if err != nil {
+ return errors.Errorf("error opening pod-id-file %s", podIDFile)
+ }
+ defer errorhandling.CloseQuiet(podIdFile)
+ defer errorhandling.SyncQuiet(podIdFile)
+ }
+
+ createOptions.Net, err = common.NetFlagsToNetOptions(cmd)
+ if err != nil {
+ return err
+ }
+ netInput, err := cmd.Flags().GetString("network")
+ if err != nil {
+ return err
+ }
+ n := specgen.Namespace{}
+ switch netInput {
+ case "bridge":
+ n.NSMode = specgen.Bridge
+ case "host":
+ n.NSMode = specgen.Host
+ case "slip4netns":
+ n.NSMode = specgen.Slirp
+ default:
+ if strings.HasPrefix(netInput, "container:") { //nolint
+ split := strings.Split(netInput, ":")
+ if len(split) != 2 {
+ return errors.Errorf("invalid network paramater: %q", netInput)
+ }
+ n.NSMode = specgen.FromContainer
+ n.Value = split[1]
+ } else if strings.HasPrefix(netInput, "ns:") {
+ return errors.New("the ns: network option is not supported for pods")
+ } else {
+ n.NSMode = specgen.Bridge
+ createOptions.Net.CNINetworks = strings.Split(netInput, ",")
+ }
+ }
+ if len(createOptions.Net.PublishPorts) > 0 {
+ if !createOptions.Infra {
+ return errors.Errorf("you must have an infra container to publish port bindings to the host")
+ }
+ }
+
+ if !createOptions.Infra {
+ if cmd.Flag("infra-command").Changed {
+ return errors.New("cannot set infra-command without an infra container")
+ }
+ createOptions.InfraCommand = ""
+ if cmd.Flag("infra-image").Changed {
+ return errors.New("cannot set infra-image without an infra container")
+ }
+ createOptions.InfraImage = ""
+ if cmd.Flag("share").Changed {
+ return errors.New("cannot set share namespaces without an infra container")
+ }
+ createOptions.Share = nil
+ }
+
+ response, err := registry.ContainerEngine().PodCreate(context.Background(), createOptions)
+ if err != nil {
+ return err
+ }
+ fmt.Println(response.Id)
+ return nil
+}
diff --git a/cmd/podman/pods/exists.go b/cmd/podman/pods/exists.go
new file mode 100644
index 000000000..ad0e28b90
--- /dev/null
+++ b/cmd/podman/pods/exists.go
@@ -0,0 +1,43 @@
+package pods
+
+import (
+ "context"
+ "os"
+
+ "github.com/containers/libpod/cmd/podman/registry"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/spf13/cobra"
+)
+
+var (
+ podExistsDescription = `If the named pod exists in local storage, podman pod exists exits with 0, otherwise the exit code will be 1.`
+
+ existsCommand = &cobra.Command{
+ Use: "exists POD",
+ Short: "Check if a pod exists in local storage",
+ Long: podExistsDescription,
+ RunE: exists,
+ Args: cobra.ExactArgs(1),
+ Example: `podman pod exists podID
+ podman pod exists mypod || podman pod create --name mypod`,
+ }
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ Command: existsCommand,
+ Parent: podCmd,
+ })
+}
+
+func exists(cmd *cobra.Command, args []string) error {
+ response, err := registry.ContainerEngine().PodExists(context.Background(), args[0])
+ if err != nil {
+ return err
+ }
+ if !response.Value {
+ os.Exit(1)
+ }
+ return nil
+}
diff --git a/cmd/podman/pods/inspect.go b/cmd/podman/pods/inspect.go
new file mode 100644
index 000000000..901ae50b2
--- /dev/null
+++ b/cmd/podman/pods/inspect.go
@@ -0,0 +1,64 @@
+package pods
+
+import (
+ "context"
+ "fmt"
+
+ "github.com/containers/libpod/cmd/podman/registry"
+ "github.com/containers/libpod/pkg/domain/entities"
+ jsoniter "github.com/json-iterator/go"
+ "github.com/pkg/errors"
+ "github.com/spf13/cobra"
+)
+
+var (
+ inspectOptions = entities.PodInspectOptions{}
+)
+
+var (
+ inspectDescription = fmt.Sprintf(`Display the configuration for a pod by name or id
+
+ By default, this will render all results in a JSON array.`)
+
+ inspectCmd = &cobra.Command{
+ Use: "inspect [flags] POD [POD...]",
+ Short: "Displays a pod configuration",
+ Long: inspectDescription,
+ RunE: inspect,
+ Example: `podman pod inspect podID`,
+ }
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ Command: inspectCmd,
+ Parent: podCmd,
+ })
+ flags := inspectCmd.Flags()
+ flags.BoolVarP(&inspectOptions.Latest, "latest", "l", false, "Act on the latest pod podman is aware of")
+ if registry.IsRemote() {
+ _ = flags.MarkHidden("latest")
+ }
+}
+
+func inspect(cmd *cobra.Command, args []string) error {
+
+ if len(args) < 1 && !inspectOptions.Latest {
+ return errors.Errorf("you must provide the name or id of a running pod")
+ }
+
+ if !inspectOptions.Latest {
+ inspectOptions.NameOrID = args[0]
+ }
+ responses, err := registry.ContainerEngine().PodInspect(context.Background(), inspectOptions)
+ if err != nil {
+ return err
+ }
+ b, err := jsoniter.MarshalIndent(responses, "", " ")
+ if err != nil {
+ return err
+ }
+ fmt.Println(string(b))
+ return nil
+}
diff --git a/cmd/podman/pods/kill.go b/cmd/podman/pods/kill.go
new file mode 100644
index 000000000..02089016e
--- /dev/null
+++ b/cmd/podman/pods/kill.go
@@ -0,0 +1,68 @@
+package pods
+
+import (
+ "context"
+ "fmt"
+
+ "github.com/containers/libpod/cmd/podman/parse"
+ "github.com/containers/libpod/cmd/podman/registry"
+ "github.com/containers/libpod/cmd/podman/utils"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/spf13/cobra"
+)
+
+var (
+ podKillDescription = `Signals are sent to the main process of each container inside the specified pod.
+
+ The default signal is SIGKILL, or any signal specified with option --signal.`
+ killCommand = &cobra.Command{
+ Use: "kill [flags] POD [POD...]",
+ Short: "Send the specified signal or SIGKILL to containers in pod",
+ Long: podKillDescription,
+ RunE: kill,
+ Args: func(cmd *cobra.Command, args []string) error {
+ return parse.CheckAllLatestAndCIDFile(cmd, args, false, false)
+ },
+ Example: `podman pod kill podID
+ podman pod kill --signal TERM mywebserver
+ podman pod kill --latest`,
+ }
+)
+
+var (
+ killOpts entities.PodKillOptions
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ Command: killCommand,
+ Parent: podCmd,
+ })
+ flags := killCommand.Flags()
+ flags.BoolVarP(&killOpts.All, "all", "a", false, "Kill all containers in all pods")
+ flags.BoolVarP(&killOpts.Latest, "latest", "l", false, "Act on the latest pod podman is aware of")
+ flags.StringVarP(&killOpts.Signal, "signal", "s", "KILL", "Signal to send to the containers in the pod")
+ if registry.IsRemote() {
+ _ = flags.MarkHidden("latest")
+ }
+
+}
+func kill(cmd *cobra.Command, args []string) error {
+ var (
+ errs utils.OutputErrors
+ )
+ responses, err := registry.ContainerEngine().PodKill(context.Background(), args, killOpts)
+ if err != nil {
+ return err
+ }
+ // in the cli, first we print out all the successful attempts
+ for _, r := range responses {
+ if len(r.Errs) == 0 {
+ fmt.Println(r.Id)
+ } else {
+ errs = append(errs, r.Errs...)
+ }
+ }
+ return errs.PrintErrors()
+}
diff --git a/cmd/podman/pods/pause.go b/cmd/podman/pods/pause.go
new file mode 100644
index 000000000..4ee182661
--- /dev/null
+++ b/cmd/podman/pods/pause.go
@@ -0,0 +1,66 @@
+package pods
+
+import (
+ "context"
+ "fmt"
+
+ "github.com/containers/libpod/cmd/podman/parse"
+ "github.com/containers/libpod/cmd/podman/registry"
+ "github.com/containers/libpod/cmd/podman/utils"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/spf13/cobra"
+)
+
+var (
+ podPauseDescription = `The pod name or ID can be used.
+
+ All running containers within each specified pod will then be paused.`
+ pauseCommand = &cobra.Command{
+ Use: "pause [flags] POD [POD...]",
+ Short: "Pause one or more pods",
+ Long: podPauseDescription,
+ RunE: pause,
+ Args: func(cmd *cobra.Command, args []string) error {
+ return parse.CheckAllLatestAndCIDFile(cmd, args, false, false)
+ },
+ Example: `podman pod pause podID1 podID2
+ podman pod pause --latest
+ podman pod pause --all`,
+ }
+)
+
+var (
+ pauseOptions entities.PodPauseOptions
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ Command: pauseCommand,
+ Parent: podCmd,
+ })
+ flags := pauseCommand.Flags()
+ flags.BoolVarP(&pauseOptions.All, "all", "a", false, "Pause all running pods")
+ flags.BoolVarP(&pauseOptions.Latest, "latest", "l", false, "Act on the latest pod podman is aware of")
+ if registry.IsRemote() {
+ _ = flags.MarkHidden("latest")
+ }
+}
+func pause(cmd *cobra.Command, args []string) error {
+ var (
+ errs utils.OutputErrors
+ )
+ responses, err := registry.ContainerEngine().PodPause(context.Background(), args, pauseOptions)
+ if err != nil {
+ return err
+ }
+ // in the cli, first we print out all the successful attempts
+ for _, r := range responses {
+ if len(r.Errs) == 0 {
+ fmt.Println(r.Id)
+ } else {
+ errs = append(errs, r.Errs...)
+ }
+ }
+ return errs.PrintErrors()
+}
diff --git a/cmd/podman/pods/pod.go b/cmd/podman/pods/pod.go
new file mode 100644
index 000000000..1cac50e40
--- /dev/null
+++ b/cmd/podman/pods/pod.go
@@ -0,0 +1,25 @@
+package pods
+
+import (
+ "github.com/containers/libpod/cmd/podman/registry"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/spf13/cobra"
+)
+
+var (
+ // Command: podman _pod_
+ podCmd = &cobra.Command{
+ Use: "pod",
+ Short: "Manage pods",
+ Long: "Manage pods",
+ TraverseChildren: true,
+ RunE: registry.SubCommandExists,
+ }
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ Command: podCmd,
+ })
+}
diff --git a/cmd/podman/pods/ps.go b/cmd/podman/pods/ps.go
new file mode 100644
index 000000000..8cb7b6266
--- /dev/null
+++ b/cmd/podman/pods/ps.go
@@ -0,0 +1,229 @@
+package pods
+
+import (
+ "context"
+ "encoding/json"
+ "fmt"
+ "io"
+ "os"
+ "strings"
+ "text/tabwriter"
+ "text/template"
+ "time"
+
+ "github.com/docker/go-units"
+
+ "github.com/containers/libpod/cmd/podman/registry"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/pkg/errors"
+ "github.com/spf13/cobra"
+)
+
+var (
+ psDescription = "List all pods on system including their names, ids and current state."
+
+ // Command: podman pod _ps_
+ psCmd = &cobra.Command{
+ Use: "ps",
+ Aliases: []string{"ls", "list"},
+ Short: "list pods",
+ Long: psDescription,
+ RunE: pods,
+ }
+)
+
+var (
+ defaultHeaders string = "POD ID\tNAME\tSTATUS\tCREATED"
+ inputFilters string
+ noTrunc bool
+ psInput entities.PodPSOptions
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ Command: psCmd,
+ Parent: podCmd,
+ })
+ flags := psCmd.Flags()
+ flags.BoolVar(&psInput.CtrNames, "ctr-names", false, "Display the container names")
+ flags.BoolVar(&psInput.CtrIds, "ctr-ids", false, "Display the container UUIDs. If no-trunc is not set they will be truncated")
+ flags.BoolVar(&psInput.CtrStatus, "ctr-status", false, "Display the container status")
+ // TODO should we make this a [] ?
+ flags.StringVarP(&inputFilters, "filter", "f", "", "Filter output based on conditions given")
+ flags.StringVar(&psInput.Format, "format", "", "Pretty-print pods to JSON or using a Go template")
+ flags.BoolVarP(&psInput.Latest, "latest", "l", false, "Act on the latest pod podman is aware of")
+ flags.BoolVar(&psInput.Namespace, "namespace", false, "Display namespace information of the pod")
+ flags.BoolVar(&psInput.Namespace, "ns", false, "Display namespace information of the pod")
+ flags.BoolVar(&noTrunc, "no-trunc", false, "Do not truncate pod and container IDs")
+ flags.BoolVarP(&psInput.Quiet, "quiet", "q", false, "Print the numeric IDs of the pods only")
+ flags.StringVar(&psInput.Sort, "sort", "created", "Sort output by created, id, name, or number")
+ if registry.IsRemote() {
+ _ = flags.MarkHidden("latest")
+ }
+}
+
+func pods(cmd *cobra.Command, args []string) error {
+ var (
+ w io.Writer = os.Stdout
+ row string
+ lpr []ListPodReporter
+ )
+ if cmd.Flag("filter").Changed {
+ for _, f := range strings.Split(inputFilters, ",") {
+ split := strings.Split(f, "=")
+ if len(split) < 2 {
+ return errors.Errorf("filter input must be in the form of filter=value: %s is invalid", f)
+ }
+ psInput.Filters[split[0]] = append(psInput.Filters[split[0]], split[1])
+ }
+ }
+ responses, err := registry.ContainerEngine().PodPs(context.Background(), psInput)
+ if err != nil {
+ return err
+ }
+
+ if psInput.Format == "json" {
+ b, err := json.MarshalIndent(responses, "", " ")
+ if err != nil {
+ return err
+ }
+ fmt.Println(string(b))
+ return nil
+ }
+
+ for _, r := range responses {
+ lpr = append(lpr, ListPodReporter{r})
+ }
+ headers, row := createPodPsOut()
+ if psInput.Quiet {
+ if noTrunc {
+ row = "{{.Id}}\n"
+ } else {
+ row = "{{slice .Id 0 12}}\n"
+ }
+ }
+ if cmd.Flag("format").Changed {
+ row = psInput.Format
+ if !strings.HasPrefix(row, "\n") {
+ row += "\n"
+ }
+ }
+ format := "{{range . }}" + row + "{{end}}"
+ if !psInput.Quiet && !cmd.Flag("format").Changed {
+ format = headers + format
+ }
+ tmpl, err := template.New("listPods").Parse(format)
+ if err != nil {
+ return err
+ }
+ if !psInput.Quiet {
+ w = tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0)
+ }
+ if err := tmpl.Execute(w, lpr); err != nil {
+ return err
+ }
+ if flusher, ok := w.(interface{ Flush() error }); ok {
+ return flusher.Flush()
+ }
+ return nil
+}
+
+func createPodPsOut() (string, string) {
+ var row string
+ headers := defaultHeaders
+ if noTrunc {
+ row += "{{.Id}}"
+ } else {
+ row += "{{slice .Id 0 12}}"
+ }
+
+ row += "\t{{.Name}}\t{{.Status}}\t{{.Created}}"
+
+ if psInput.CtrIds {
+ headers += "\tIDS"
+ row += "\t{{.ContainerIds}}"
+ }
+ if psInput.CtrNames {
+ headers += "\tNAMES"
+ row += "\t{{.ContainerNames}}"
+ }
+ if psInput.CtrStatus {
+ headers += "\tSTATUS"
+ row += "\t{{.ContainerStatuses}}"
+ }
+ if psInput.Namespace {
+ headers += "\tCGROUP\tNAMESPACES"
+ row += "\t{{.Cgroup}}\t{{.Namespace}}"
+ }
+ if !psInput.CtrStatus && !psInput.CtrNames && !psInput.CtrIds {
+ headers += "\t# OF CONTAINERS"
+ row += "\t{{.NumberOfContainers}}"
+
+ }
+ headers += "\tINFRA ID\n"
+ if noTrunc {
+ row += "\t{{.InfraId}}\n"
+ } else {
+ row += "\t{{slice .InfraId 0 12}}\n"
+ }
+ return headers, row
+}
+
+// ListPodReporter is a struct for pod ps output
+type ListPodReporter struct {
+ *entities.ListPodsReport
+}
+
+// Created returns a human readable created time/date
+func (l ListPodReporter) Created() string {
+ return units.HumanDuration(time.Since(l.ListPodsReport.Created)) + " ago"
+}
+
+// NumberofContainers returns an int representation for
+// the number of containers belonging to the pod
+func (l ListPodReporter) NumberOfContainers() int {
+ return len(l.Containers)
+}
+
+// Added for backwards compatibility with podmanv1
+func (l ListPodReporter) InfraID() string {
+ return l.InfraId()
+}
+
+// InfraId returns the infra container id for the pod
+// depending on trunc
+func (l ListPodReporter) InfraId() string {
+ if noTrunc {
+ return l.ListPodsReport.InfraId
+ }
+ return l.ListPodsReport.InfraId[0:12]
+}
+
+func (l ListPodReporter) ContainerIds() string {
+ var ctrids []string
+ for _, c := range l.Containers {
+ id := c.Id
+ if !noTrunc {
+ id = id[0:12]
+ }
+ ctrids = append(ctrids, id)
+ }
+ return strings.Join(ctrids, ",")
+}
+
+func (l ListPodReporter) ContainerNames() string {
+ var ctrNames []string
+ for _, c := range l.Containers {
+ ctrNames = append(ctrNames, c.Names)
+ }
+ return strings.Join(ctrNames, ",")
+}
+
+func (l ListPodReporter) ContainerStatuses() string {
+ var statuses []string
+ for _, c := range l.Containers {
+ statuses = append(statuses, c.Status)
+ }
+ return strings.Join(statuses, ",")
+}
diff --git a/cmd/podman/pods/restart.go b/cmd/podman/pods/restart.go
new file mode 100644
index 000000000..1f617a277
--- /dev/null
+++ b/cmd/podman/pods/restart.go
@@ -0,0 +1,68 @@
+package pods
+
+import (
+ "context"
+ "fmt"
+
+ "github.com/containers/libpod/cmd/podman/parse"
+ "github.com/containers/libpod/cmd/podman/registry"
+ "github.com/containers/libpod/cmd/podman/utils"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/spf13/cobra"
+)
+
+var (
+ podRestartDescription = `The pod ID or name can be used.
+
+ All of the containers within each of the specified pods will be restarted. If a container in a pod is not currently running it will be started.`
+ restartCommand = &cobra.Command{
+ Use: "restart [flags] POD [POD...]",
+ Short: "Restart one or more pods",
+ Long: podRestartDescription,
+ RunE: restart,
+ Args: func(cmd *cobra.Command, args []string) error {
+ return parse.CheckAllLatestAndCIDFile(cmd, args, false, false)
+ },
+ Example: `podman pod restart podID1 podID2
+ podman pod restart --latest
+ podman pod restart --all`,
+ }
+)
+
+var (
+ restartOptions = entities.PodRestartOptions{}
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ Command: restartCommand,
+ Parent: podCmd,
+ })
+
+ flags := restartCommand.Flags()
+ flags.BoolVarP(&restartOptions.All, "all", "a", false, "Restart all running pods")
+ flags.BoolVarP(&restartOptions.Latest, "latest", "l", false, "Restart the latest pod podman is aware of")
+ if registry.IsRemote() {
+ _ = flags.MarkHidden("latest")
+ }
+}
+
+func restart(cmd *cobra.Command, args []string) error {
+ var (
+ errs utils.OutputErrors
+ )
+ responses, err := registry.ContainerEngine().PodRestart(context.Background(), args, restartOptions)
+ if err != nil {
+ return err
+ }
+ // in the cli, first we print out all the successful attempts
+ for _, r := range responses {
+ if len(r.Errs) == 0 {
+ fmt.Println(r.Id)
+ } else {
+ errs = append(errs, r.Errs...)
+ }
+ }
+ return errs.PrintErrors()
+}
diff --git a/cmd/podman/pods/rm.go b/cmd/podman/pods/rm.go
new file mode 100644
index 000000000..ea3a6476a
--- /dev/null
+++ b/cmd/podman/pods/rm.go
@@ -0,0 +1,71 @@
+package pods
+
+import (
+ "context"
+ "fmt"
+
+ "github.com/containers/libpod/cmd/podman/parse"
+ "github.com/containers/libpod/cmd/podman/registry"
+ "github.com/containers/libpod/cmd/podman/utils"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/spf13/cobra"
+)
+
+var (
+ podRmDescription = fmt.Sprintf(`podman rm will remove one or more stopped pods and their containers from the host.
+
+ The pod name or ID can be used. A pod with containers will not be removed without --force. If --force is specified, all containers will be stopped, then removed.`)
+ rmCommand = &cobra.Command{
+ Use: "rm [flags] POD [POD...]",
+ Short: "Remove one or more pods",
+ Long: podRmDescription,
+ RunE: rm,
+ Args: func(cmd *cobra.Command, args []string) error {
+ return parse.CheckAllLatestAndCIDFile(cmd, args, false, false)
+ },
+ Example: `podman pod rm mywebserverpod
+ podman pod rm -f 860a4b23
+ podman pod rm -f -a`,
+ }
+)
+
+var (
+ rmOptions = entities.PodRmOptions{}
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ Command: rmCommand,
+ Parent: podCmd,
+ })
+
+ flags := rmCommand.Flags()
+ flags.BoolVarP(&rmOptions.All, "all", "a", false, "Restart all running pods")
+ flags.BoolVarP(&rmOptions.Force, "force", "f", false, "Force removal of a running pod by first stopping all containers, then removing all containers in the pod. The default is false")
+ flags.BoolVarP(&rmOptions.Ignore, "ignore", "i", false, "Ignore errors when a specified pod is missing")
+ flags.BoolVarP(&rmOptions.Latest, "latest", "l", false, "Restart the latest pod podman is aware of")
+ if registry.IsRemote() {
+ _ = flags.MarkHidden("latest")
+ _ = flags.MarkHidden("ignore")
+ }
+}
+
+func rm(cmd *cobra.Command, args []string) error {
+ var (
+ errs utils.OutputErrors
+ )
+ responses, err := registry.ContainerEngine().PodRm(context.Background(), args, rmOptions)
+ if err != nil {
+ return err
+ }
+ // in the cli, first we print out all the successful attempts
+ for _, r := range responses {
+ if r.Err == nil {
+ fmt.Println(r.Id)
+ } else {
+ errs = append(errs, r.Err)
+ }
+ }
+ return errs.PrintErrors()
+}
diff --git a/cmd/podman/pods/start.go b/cmd/podman/pods/start.go
new file mode 100644
index 000000000..d0150a3c2
--- /dev/null
+++ b/cmd/podman/pods/start.go
@@ -0,0 +1,68 @@
+package pods
+
+import (
+ "context"
+ "fmt"
+
+ "github.com/containers/libpod/cmd/podman/parse"
+ "github.com/containers/libpod/cmd/podman/registry"
+ "github.com/containers/libpod/cmd/podman/utils"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/spf13/cobra"
+)
+
+var (
+ podStartDescription = `The pod name or ID can be used.
+
+ All containers defined in the pod will be started.`
+ startCommand = &cobra.Command{
+ Use: "start [flags] POD [POD...]",
+ Short: "Start one or more pods",
+ Long: podStartDescription,
+ RunE: start,
+ Args: func(cmd *cobra.Command, args []string) error {
+ return parse.CheckAllLatestAndCIDFile(cmd, args, false, false)
+ },
+ Example: `podman pod start podID
+ podman pod start --latest
+ podman pod start --all`,
+ }
+)
+
+var (
+ startOptions = entities.PodStartOptions{}
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ Command: startCommand,
+ Parent: podCmd,
+ })
+
+ flags := startCommand.Flags()
+ flags.BoolVarP(&startOptions.All, "all", "a", false, "Restart all running pods")
+ flags.BoolVarP(&startOptions.Latest, "latest", "l", false, "Restart the latest pod podman is aware of")
+ if registry.IsRemote() {
+ _ = flags.MarkHidden("latest")
+ }
+}
+
+func start(cmd *cobra.Command, args []string) error {
+ var (
+ errs utils.OutputErrors
+ )
+ responses, err := registry.ContainerEngine().PodStart(context.Background(), args, startOptions)
+ if err != nil {
+ return err
+ }
+ // in the cli, first we print out all the successful attempts
+ for _, r := range responses {
+ if len(r.Errs) == 0 {
+ fmt.Println(r.Id)
+ } else {
+ errs = append(errs, r.Errs...)
+ }
+ }
+ return errs.PrintErrors()
+}
diff --git a/cmd/podman/pods/stop.go b/cmd/podman/pods/stop.go
new file mode 100644
index 000000000..683d9c00a
--- /dev/null
+++ b/cmd/podman/pods/stop.go
@@ -0,0 +1,79 @@
+package pods
+
+import (
+ "context"
+ "fmt"
+
+ "github.com/containers/libpod/cmd/podman/parse"
+ "github.com/containers/libpod/cmd/podman/registry"
+ "github.com/containers/libpod/cmd/podman/utils"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/spf13/cobra"
+)
+
+var (
+ podStopDescription = `The pod name or ID can be used.
+
+ This command will stop all running containers in each of the specified pods.`
+
+ stopCommand = &cobra.Command{
+ Use: "stop [flags] POD [POD...]",
+ Short: "Stop one or more pods",
+ Long: podStopDescription,
+ RunE: stop,
+ Args: func(cmd *cobra.Command, args []string) error {
+ return parse.CheckAllLatestAndCIDFile(cmd, args, false, false)
+ },
+ Example: `podman pod stop mywebserverpod
+ podman pod stop --latest
+ podman pod stop --time 0 490eb 3557fb`,
+ }
+)
+
+var (
+ stopOptions = entities.PodStopOptions{
+ Timeout: -1,
+ }
+ timeout uint
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ Command: stopCommand,
+ Parent: podCmd,
+ })
+ flags := stopCommand.Flags()
+ flags.BoolVarP(&stopOptions.All, "all", "a", false, "Stop all running pods")
+ flags.BoolVarP(&stopOptions.Ignore, "ignore", "i", false, "Ignore errors when a specified pod is missing")
+ flags.BoolVarP(&stopOptions.Latest, "latest", "l", false, "Stop the latest pod podman is aware of")
+ flags.UintVarP(&timeout, "time", "t", 0, "Seconds to wait for pod stop before killing the container")
+ if registry.IsRemote() {
+ _ = flags.MarkHidden("latest")
+ _ = flags.MarkHidden("ignore")
+
+ }
+ flags.SetNormalizeFunc(utils.AliasFlags)
+}
+
+func stop(cmd *cobra.Command, args []string) error {
+ var (
+ errs utils.OutputErrors
+ )
+ if cmd.Flag("time").Changed {
+ stopOptions.Timeout = int(timeout)
+ }
+ responses, err := registry.ContainerEngine().PodStop(context.Background(), args, stopOptions)
+ if err != nil {
+ return err
+ }
+ // in the cli, first we print out all the successful attempts
+ for _, r := range responses {
+ if len(r.Errs) == 0 {
+ fmt.Println(r.Id)
+ } else {
+ errs = append(errs, r.Errs...)
+ }
+ }
+ return errs.PrintErrors()
+}
diff --git a/cmd/podman/pods/top.go b/cmd/podman/pods/top.go
new file mode 100644
index 000000000..ad602f4ea
--- /dev/null
+++ b/cmd/podman/pods/top.go
@@ -0,0 +1,86 @@
+package pods
+
+import (
+ "context"
+ "fmt"
+ "os"
+ "strings"
+ "text/tabwriter"
+
+ "github.com/containers/libpod/cmd/podman/registry"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/containers/psgo"
+ "github.com/pkg/errors"
+ "github.com/spf13/cobra"
+)
+
+var (
+ topDescription = fmt.Sprintf(`Specify format descriptors to alter the output.
+
+ You may run "podman pod top -l pid pcpu seccomp" to print the process ID, the CPU percentage and the seccomp mode of each process of the latest pod.
+ Format Descriptors:
+ %s`, strings.Join(psgo.ListDescriptors(), ","))
+
+ topOptions = entities.PodTopOptions{}
+
+ topCommand = &cobra.Command{
+ Use: "top [flags] POD [FORMAT-DESCRIPTORS|ARGS]",
+ Short: "Display the running processes in a pod",
+ Long: topDescription,
+ RunE: top,
+ Args: cobra.ArbitraryArgs,
+ Example: `podman pod top podID
+podman pod top --latest
+podman pod top podID pid seccomp args %C
+podman pod top podID -eo user,pid,comm`,
+ }
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ Command: topCommand,
+ Parent: podCmd,
+ })
+
+ flags := topCommand.Flags()
+ flags.SetInterspersed(false)
+ flags.BoolVar(&topOptions.ListDescriptors, "list-descriptors", false, "")
+ flags.BoolVarP(&topOptions.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
+
+ _ = flags.MarkHidden("list-descriptors") // meant only for bash completion
+ if registry.IsRemote() {
+ _ = flags.MarkHidden("latest")
+ }
+}
+
+func top(cmd *cobra.Command, args []string) error {
+ if topOptions.ListDescriptors {
+ fmt.Println(strings.Join(psgo.ListDescriptors(), "\n"))
+ return nil
+ }
+
+ if len(args) < 1 && !topOptions.Latest {
+ return errors.Errorf("you must provide the name or id of a running pod")
+ }
+
+ if topOptions.Latest {
+ topOptions.Descriptors = args
+ } else {
+ topOptions.NameOrID = args[0]
+ topOptions.Descriptors = args[1:]
+ }
+
+ topResponse, err := registry.ContainerEngine().PodTop(context.Background(), topOptions)
+ if err != nil {
+ return err
+ }
+
+ w := tabwriter.NewWriter(os.Stdout, 5, 1, 3, ' ', 0)
+ for _, proc := range topResponse.Value {
+ if _, err := fmt.Fprintln(w, proc); err != nil {
+ return err
+ }
+ }
+ return w.Flush()
+}
diff --git a/cmd/podman/pods/unpause.go b/cmd/podman/pods/unpause.go
new file mode 100644
index 000000000..b30bd930a
--- /dev/null
+++ b/cmd/podman/pods/unpause.go
@@ -0,0 +1,66 @@
+package pods
+
+import (
+ "context"
+ "fmt"
+
+ "github.com/containers/libpod/cmd/podman/parse"
+ "github.com/containers/libpod/cmd/podman/registry"
+ "github.com/containers/libpod/cmd/podman/utils"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/spf13/cobra"
+)
+
+var (
+ podUnpauseDescription = `The podman unpause command will unpause all "paused" containers assigned to the pod.
+
+ The pod name or ID can be used.`
+ unpauseCommand = &cobra.Command{
+ Use: "unpause [flags] POD [POD...]",
+ Short: "Unpause one or more pods",
+ Long: podUnpauseDescription,
+ RunE: unpause,
+ Args: func(cmd *cobra.Command, args []string) error {
+ return parse.CheckAllLatestAndCIDFile(cmd, args, false, false)
+ },
+ Example: `podman pod unpause podID1 podID2
+ podman pod unpause --all
+ podman pod unpause --latest`,
+ }
+)
+
+var (
+ unpauseOptions entities.PodunpauseOptions
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ Command: unpauseCommand,
+ Parent: podCmd,
+ })
+ flags := unpauseCommand.Flags()
+ flags.BoolVarP(&unpauseOptions.All, "all", "a", false, "Pause all running pods")
+ flags.BoolVarP(&unpauseOptions.Latest, "latest", "l", false, "Act on the latest pod podman is aware of")
+ if registry.IsRemote() {
+ _ = flags.MarkHidden("latest")
+ }
+}
+func unpause(cmd *cobra.Command, args []string) error {
+ var (
+ errs utils.OutputErrors
+ )
+ responses, err := registry.ContainerEngine().PodUnpause(context.Background(), args, unpauseOptions)
+ if err != nil {
+ return err
+ }
+ // in the cli, first we print out all the successful attempts
+ for _, r := range responses {
+ if len(r.Errs) == 0 {
+ fmt.Println(r.Id)
+ } else {
+ errs = append(errs, r.Errs...)
+ }
+ }
+ return errs.PrintErrors()
+}