summaryrefslogtreecommitdiff
path: root/cmd/podmanV2
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/podmanV2')
-rw-r--r--cmd/podmanV2/README.md113
-rw-r--r--cmd/podmanV2/containers/container.go33
-rw-r--r--cmd/podmanV2/containers/inspect.go42
-rw-r--r--cmd/podmanV2/containers/list.go34
-rw-r--r--cmd/podmanV2/containers/ps.go29
-rw-r--r--cmd/podmanV2/images/history.go79
-rw-r--r--cmd/podmanV2/images/image.go33
-rw-r--r--cmd/podmanV2/images/images.go46
-rw-r--r--cmd/podmanV2/images/inspect.go124
-rw-r--r--cmd/podmanV2/images/list.go33
-rw-r--r--cmd/podmanV2/main.go84
-rw-r--r--cmd/podmanV2/networks/network.go33
-rw-r--r--cmd/podmanV2/pods/pod.go33
-rw-r--r--cmd/podmanV2/pods/ps.go32
-rw-r--r--cmd/podmanV2/registry/registry.go96
-rw-r--r--cmd/podmanV2/report/templates.go61
-rw-r--r--cmd/podmanV2/root.go35
-rw-r--r--cmd/podmanV2/system/system.go33
-rw-r--r--cmd/podmanV2/volumes/volume.go33
19 files changed, 1006 insertions, 0 deletions
diff --git a/cmd/podmanV2/README.md b/cmd/podmanV2/README.md
new file mode 100644
index 000000000..a17e6f850
--- /dev/null
+++ b/cmd/podmanV2/README.md
@@ -0,0 +1,113 @@
+# Adding a podman V2 commands
+
+## Build podman V2
+
+```shell script
+$ cd $GOPATH/src/github.com/containers/libpod/cmd/podmanV2
+```
+If you wish to include the libpod library in your program,
+```shell script
+$ go build -tags 'ABISupport' .
+```
+The `--remote` flag may be used to connect to the Podman service using the API.
+Otherwise, direct calls will be made to the Libpod library.
+```shell script
+$ go build -tags '!ABISupport' .
+```
+The Libpod library is not linked into the executable.
+All calls are made via the API and `--remote=False` is an error condition.
+
+## Adding a new command `podman manifests`
+```shell script
+$ mkdir -p $GOPATH/src/github.com/containers/libpod/cmd/podmanV2/manifests
+```
+Create the file ```$GOPATH/src/github.com/containers/libpod/cmd/podmanV2/manifests/manifest.go```
+```go
+package manifests
+
+import (
+ "github.com/containers/libpod/cmd/podmanV2/registry"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/spf13/cobra"
+)
+
+var (
+ // podman _manifests_
+ manifestCmd = &cobra.Command{
+ Use: "manifest",
+ Short: "Manage manifests",
+ Long: "Manage manifests",
+ Example: "podman manifests IMAGE",
+ TraverseChildren: true,
+ PersistentPreRunE: preRunE,
+ RunE: registry.SubCommandExists, // Report error if there is no sub command given
+ }
+)
+func init() {
+ // Subscribe command to podman
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ // _podman manifest_ will support both ABIMode and TunnelMode
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ // The definition for this command
+ Command: manifestCmd,
+ })
+ // Setup cobra templates, sub commands will inherit
+ manifestCmd.SetHelpTemplate(registry.HelpTemplate())
+ manifestCmd.SetUsageTemplate(registry.UsageTemplate())
+}
+
+// preRunE populates the image engine for sub commands
+func preRunE(cmd *cobra.Command, args []string) error {
+ _, err := registry.NewImageEngine(cmd, args)
+ return err
+}
+```
+To "wire" in the `manifest` command, edit the file ```$GOPATH/src/github.com/containers/libpod/cmd/podmanV2/main.go``` to add:
+```go
+package main
+
+import _ "github.com/containers/libpod/cmd/podmanV2/manifests"
+```
+
+## Adding a new sub command `podman manifests list`
+Create the file ```$GOPATH/src/github.com/containers/libpod/cmd/podmanV2/manifests/inspect.go```
+```go
+package manifests
+
+import (
+ "github.com/containers/libpod/cmd/podmanV2/registry"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/spf13/cobra"
+)
+
+var (
+ // podman manifests _inspect_
+ inspectCmd = &cobra.Command{
+ Use: "inspect IMAGE",
+ Short: "Display manifest from image",
+ Long: "Displays the low-level information on a manifest identified by image name or ID",
+ RunE: inspect,
+ Example: "podman manifest DEADBEEF",
+ }
+)
+
+func init() {
+ // Subscribe inspect sub command to manifest command
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ // _podman manifest inspect_ will support both ABIMode and TunnelMode
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ // The definition for this command
+ Command: inspectCmd,
+ Parent: manifestCmd,
+ })
+
+ // This is where you would configure the cobra flags using inspectCmd.Flags()
+}
+
+// Business logic: cmd is inspectCmd, args is the positional arguments from os.Args
+func inspect(cmd *cobra.Command, args []string) error {
+ // Business logic using registry.ImageEngine
+ // Do not pull from libpod directly use the domain objects and types
+ return nil
+}
+```
diff --git a/cmd/podmanV2/containers/container.go b/cmd/podmanV2/containers/container.go
new file mode 100644
index 000000000..6b44f2a3e
--- /dev/null
+++ b/cmd/podmanV2/containers/container.go
@@ -0,0 +1,33 @@
+package containers
+
+import (
+ "github.com/containers/libpod/cmd/podmanV2/registry"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/spf13/cobra"
+)
+
+var (
+ // Command: podman _container_
+ containerCmd = &cobra.Command{
+ Use: "container",
+ Short: "Manage containers",
+ Long: "Manage containers",
+ TraverseChildren: true,
+ PersistentPreRunE: preRunE,
+ RunE: registry.SubCommandExists,
+ }
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ Command: containerCmd,
+ })
+ containerCmd.SetHelpTemplate(registry.HelpTemplate())
+ containerCmd.SetUsageTemplate(registry.UsageTemplate())
+}
+
+func preRunE(cmd *cobra.Command, args []string) error {
+ _, err := registry.NewContainerEngine(cmd, args)
+ return err
+}
diff --git a/cmd/podmanV2/containers/inspect.go b/cmd/podmanV2/containers/inspect.go
new file mode 100644
index 000000000..635be4789
--- /dev/null
+++ b/cmd/podmanV2/containers/inspect.go
@@ -0,0 +1,42 @@
+package containers
+
+import (
+ "github.com/containers/libpod/cmd/podmanV2/registry"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/spf13/cobra"
+)
+
+var (
+ // podman container _inspect_
+ inspectCmd = &cobra.Command{
+ Use: "inspect [flags] CONTAINER",
+ Short: "Display the configuration of a container",
+ Long: `Displays the low-level information on a container identified by name or ID.`,
+ PreRunE: inspectPreRunE,
+ RunE: inspect,
+ Example: `podman container inspect myCtr
+ podman container inspect -l --format '{{.Id}} {{.Config.Labels}}'`,
+ }
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ Command: inspectCmd,
+ Parent: containerCmd,
+ })
+}
+
+func inspectPreRunE(cmd *cobra.Command, args []string) (err error) {
+ err = preRunE(cmd, args)
+ if err != nil {
+ return
+ }
+
+ _, err = registry.NewImageEngine(cmd, args)
+ return err
+}
+
+func inspect(cmd *cobra.Command, args []string) error {
+ return nil
+}
diff --git a/cmd/podmanV2/containers/list.go b/cmd/podmanV2/containers/list.go
new file mode 100644
index 000000000..630d9bbc7
--- /dev/null
+++ b/cmd/podmanV2/containers/list.go
@@ -0,0 +1,34 @@
+package containers
+
+import (
+ "github.com/containers/libpod/cmd/podmanV2/registry"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/spf13/cobra"
+)
+
+var (
+ // podman container _list_
+ listCmd = &cobra.Command{
+ Use: "list",
+ Aliases: []string{"ls"},
+ Args: cobra.NoArgs,
+ Short: "List containers",
+ Long: "Prints out information about the containers",
+ RunE: containers,
+ Example: `podman container list -a
+ podman container list -a --format "{{.ID}} {{.Image}} {{.Labels}} {{.Mounts}}"
+ podman container list --size --sort names`,
+ }
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ Command: listCmd,
+ Parent: containerCmd,
+ })
+}
+
+func containers(cmd *cobra.Command, args []string) error {
+ return nil
+}
diff --git a/cmd/podmanV2/containers/ps.go b/cmd/podmanV2/containers/ps.go
new file mode 100644
index 000000000..ce3d66c51
--- /dev/null
+++ b/cmd/podmanV2/containers/ps.go
@@ -0,0 +1,29 @@
+package containers
+
+import (
+ "strings"
+
+ "github.com/containers/libpod/cmd/podmanV2/registry"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/spf13/cobra"
+)
+
+var (
+ // podman _ps_
+ psCmd = &cobra.Command{
+ Use: "ps",
+ Args: cobra.NoArgs,
+ Short: listCmd.Short,
+ Long: listCmd.Long,
+ PersistentPreRunE: preRunE,
+ RunE: containers,
+ Example: strings.Replace(listCmd.Example, "container list", "ps", -1),
+ }
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ Command: psCmd,
+ })
+}
diff --git a/cmd/podmanV2/images/history.go b/cmd/podmanV2/images/history.go
new file mode 100644
index 000000000..c75ae6ddc
--- /dev/null
+++ b/cmd/podmanV2/images/history.go
@@ -0,0 +1,79 @@
+package images
+
+import (
+ "context"
+ "fmt"
+ "os"
+ "text/tabwriter"
+ "text/template"
+
+ "github.com/containers/libpod/cmd/podmanV2/registry"
+ "github.com/containers/libpod/cmd/podmanV2/report"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/pkg/errors"
+ "github.com/spf13/cobra"
+)
+
+var (
+ long = `Displays the history of an image.
+
+ The information can be printed out in an easy to read, or user specified format, and can be truncated.`
+
+ // podman _history_
+ historyCmd = &cobra.Command{
+ Use: "history [flags] IMAGE",
+ Short: "Show history of a specified image",
+ Long: long,
+ Example: "podman history quay.io/fedora/fedora",
+ Args: cobra.ExactArgs(1),
+ PersistentPreRunE: preRunE,
+ RunE: history,
+ }
+)
+
+var cmdFlags = struct {
+ Human bool
+ NoTrunc bool
+ Quiet bool
+ Format string
+}{}
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ Command: historyCmd,
+ })
+
+ historyCmd.SetHelpTemplate(registry.HelpTemplate())
+ historyCmd.SetUsageTemplate(registry.UsageTemplate())
+ flags := historyCmd.Flags()
+ flags.StringVar(&cmdFlags.Format, "format", "", "Change the output to JSON or a Go template")
+ flags.BoolVarP(&cmdFlags.Human, "human", "H", true, "Display sizes and dates in human readable format")
+ flags.BoolVar(&cmdFlags.NoTrunc, "no-trunc", false, "Do not truncate the output")
+ flags.BoolVar(&cmdFlags.NoTrunc, "notruncate", false, "Do not truncate the output")
+ flags.BoolVarP(&cmdFlags.Quiet, "quiet", "q", false, "Display the numeric IDs only")
+}
+
+func history(cmd *cobra.Command, args []string) error {
+ results, err := registry.ImageEngine().History(context.Background(), args[0], entities.ImageHistoryOptions{})
+ if err != nil {
+ return err
+ }
+
+ row := "{{slice $x.ID 0 12}}\t{{toRFC3339 $x.Created}}\t{{ellipsis $x.CreatedBy 45}}\t{{$x.Size}}\t{{$x.Comment}}\n"
+ if cmdFlags.Human {
+ row = "{{slice $x.ID 0 12}}\t{{toHumanDuration $x.Created}}\t{{ellipsis $x.CreatedBy 45}}\t{{toHumanSize $x.Size}}\t{{$x.Comment}}\n"
+ }
+ format := "{{range $y, $x := . }}" + row + "{{end}}"
+
+ tmpl := template.Must(template.New("report").Funcs(report.PodmanTemplateFuncs()).Parse(format))
+ w := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0)
+
+ _, _ = w.Write(report.ReportHeader("id", "created", "created by", "size", "comment"))
+ err = tmpl.Execute(w, results.Layers)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, errors.Wrapf(err, "Failed to print report"))
+ }
+ w.Flush()
+ return nil
+}
diff --git a/cmd/podmanV2/images/image.go b/cmd/podmanV2/images/image.go
new file mode 100644
index 000000000..a15c3e826
--- /dev/null
+++ b/cmd/podmanV2/images/image.go
@@ -0,0 +1,33 @@
+package images
+
+import (
+ "github.com/containers/libpod/cmd/podmanV2/registry"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/spf13/cobra"
+)
+
+var (
+ // Command: podman _image_
+ imageCmd = &cobra.Command{
+ Use: "image",
+ Short: "Manage images",
+ Long: "Manage images",
+ TraverseChildren: true,
+ PersistentPreRunE: preRunE,
+ RunE: registry.SubCommandExists,
+ }
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ Command: imageCmd,
+ })
+ imageCmd.SetHelpTemplate(registry.HelpTemplate())
+ imageCmd.SetUsageTemplate(registry.UsageTemplate())
+}
+
+func preRunE(cmd *cobra.Command, args []string) error {
+ _, err := registry.NewImageEngine(cmd, args)
+ return err
+}
diff --git a/cmd/podmanV2/images/images.go b/cmd/podmanV2/images/images.go
new file mode 100644
index 000000000..a1e56396a
--- /dev/null
+++ b/cmd/podmanV2/images/images.go
@@ -0,0 +1,46 @@
+package images
+
+import (
+ "strings"
+
+ "github.com/containers/libpod/cmd/podmanV2/registry"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/spf13/cobra"
+)
+
+var (
+ // podman _images_
+ imagesCmd = &cobra.Command{
+ Use: strings.Replace(listCmd.Use, "list", "images", 1),
+ Short: listCmd.Short,
+ Long: listCmd.Long,
+ PersistentPreRunE: preRunE,
+ RunE: images,
+ Example: strings.Replace(listCmd.Example, "podman image list", "podman images", -1),
+ }
+
+ imagesOpts = entities.ImageListOptions{}
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ Command: imagesCmd,
+ })
+ imagesCmd.SetHelpTemplate(registry.HelpTemplate())
+ imagesCmd.SetUsageTemplate(registry.UsageTemplate())
+
+ flags := imagesCmd.Flags()
+ flags.BoolVarP(&imagesOpts.All, "all", "a", false, "Show all images (default hides intermediate images)")
+ flags.BoolVar(&imagesOpts.Digests, "digests", false, "Show digests")
+ flags.StringSliceVarP(&imagesOpts.Filter, "filter", "f", []string{}, "Filter output based on conditions provided (default [])")
+ flags.StringVar(&imagesOpts.Format, "format", "", "Change the output format to JSON or a Go template")
+ flags.BoolVarP(&imagesOpts.Noheading, "noheading", "n", false, "Do not print column headings")
+ // TODO Need to learn how to deal with second name being a string instead of a char.
+ // This needs to be "no-trunc, notruncate"
+ flags.BoolVar(&imagesOpts.NoTrunc, "no-trunc", false, "Do not truncate output")
+ flags.BoolVar(&imagesOpts.NoTrunc, "notruncate", false, "Do not truncate output")
+ flags.BoolVarP(&imagesOpts.Quiet, "quiet", "q", false, "Display only image IDs")
+ flags.StringVar(&imagesOpts.Sort, "sort", "created", "Sort by created, id, repository, size, or tag")
+ flags.BoolVarP(&imagesOpts.History, "history", "", false, "Display the image name history")
+}
diff --git a/cmd/podmanV2/images/inspect.go b/cmd/podmanV2/images/inspect.go
new file mode 100644
index 000000000..9c44cea35
--- /dev/null
+++ b/cmd/podmanV2/images/inspect.go
@@ -0,0 +1,124 @@
+package images
+
+import (
+ "strings"
+
+ "github.com/containers/buildah/pkg/formats"
+ "github.com/containers/libpod/cmd/podmanV2/registry"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/containers/libpod/pkg/util"
+ "github.com/pkg/errors"
+ "github.com/spf13/cobra"
+)
+
+var (
+ inspectOpts = entities.ImageInspectOptions{}
+
+ // Command: podman image _inspect_
+ inspectCmd = &cobra.Command{
+ Use: "inspect [flags] IMAGE",
+ Short: "Display the configuration of an image",
+ Long: `Displays the low-level information on an image identified by name or ID.`,
+ PreRunE: populateEngines,
+ RunE: imageInspect,
+ Example: `podman image inspect alpine`,
+ }
+
+ containerEngine entities.ContainerEngine
+)
+
+// Inspect is unique in that it needs both an ImageEngine and a ContainerEngine
+func populateEngines(cmd *cobra.Command, args []string) (err error) {
+ // Populate registry.ImageEngine
+ err = preRunE(cmd, args)
+ if err != nil {
+ return
+ }
+
+ // Populate registry.ContainerEngine
+ containerEngine, err = registry.NewContainerEngine(cmd, args)
+ return
+}
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ Command: inspectCmd,
+ Parent: imageCmd,
+ })
+
+ flags := inspectCmd.Flags()
+ flags.BoolVarP(&inspectOpts.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
+ flags.BoolVarP(&inspectOpts.Size, "size", "s", false, "Display total file size")
+ flags.StringVarP(&inspectOpts.Format, "format", "f", "", "Change the output format to a Go template")
+
+ if registry.GlobalFlags.EngineMode == entities.ABIMode {
+ // TODO: This is the same as V1. We could skip creating the flag altogether in V2...
+ _ = flags.MarkHidden("latest")
+ }
+}
+
+const (
+ inspectTypeContainer = "container"
+ inspectTypeImage = "image"
+ inspectAll = "all"
+)
+
+func imageInspect(cmd *cobra.Command, args []string) error {
+ inspectType := inspectTypeImage
+ latestContainer := inspectOpts.Latest
+
+ if len(args) == 0 && !latestContainer {
+ return errors.Errorf("container or image name must be specified: podman inspect [options [...]] name")
+ }
+
+ if len(args) > 0 && latestContainer {
+ return errors.Errorf("you cannot provide additional arguments with --latest")
+ }
+
+ if !util.StringInSlice(inspectType, []string{inspectTypeContainer, inspectTypeImage, inspectAll}) {
+ return errors.Errorf("the only recognized types are %q, %q, and %q", inspectTypeContainer, inspectTypeImage, inspectAll)
+ }
+
+ outputFormat := inspectOpts.Format
+ if strings.Contains(outputFormat, "{{.Id}}") {
+ outputFormat = strings.Replace(outputFormat, "{{.Id}}", formats.IDString, -1)
+ }
+ // These fields were renamed, so we need to provide backward compat for
+ // the old names.
+ if strings.Contains(outputFormat, ".Src") {
+ outputFormat = strings.Replace(outputFormat, ".Src", ".Source", -1)
+ }
+ if strings.Contains(outputFormat, ".Dst") {
+ outputFormat = strings.Replace(outputFormat, ".Dst", ".Destination", -1)
+ }
+ if strings.Contains(outputFormat, ".ImageID") {
+ outputFormat = strings.Replace(outputFormat, ".ImageID", ".Image", -1)
+ }
+ _ = outputFormat
+ // if latestContainer {
+ // lc, err := ctnrRuntime.GetLatestContainer()
+ // if err != nil {
+ // return err
+ // }
+ // args = append(args, lc.ID())
+ // inspectType = inspectTypeContainer
+ // }
+
+ // inspectedObjects, iterateErr := iterateInput(getContext(), c.Size, args, runtime, inspectType)
+ // if iterateErr != nil {
+ // return iterateErr
+ // }
+ //
+ // var out formats.Writer
+ // if outputFormat != "" && outputFormat != formats.JSONString {
+ // // template
+ // out = formats.StdoutTemplateArray{Output: inspectedObjects, Template: outputFormat}
+ // } else {
+ // // default is json output
+ // out = formats.JSONStructArray{Output: inspectedObjects}
+ // }
+ //
+ // return out.Out()
+ return nil
+}
diff --git a/cmd/podmanV2/images/list.go b/cmd/podmanV2/images/list.go
new file mode 100644
index 000000000..cfdfaaed2
--- /dev/null
+++ b/cmd/podmanV2/images/list.go
@@ -0,0 +1,33 @@
+package images
+
+import (
+ "github.com/containers/libpod/cmd/podmanV2/registry"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/spf13/cobra"
+)
+
+var (
+ // Command: podman image _list_
+ listCmd = &cobra.Command{
+ Use: "list [flag] [IMAGE]",
+ Aliases: []string{"ls"},
+ Short: "List images in local storage",
+ Long: "Lists images previously pulled to the system or created on the system.",
+ RunE: images,
+ Example: `podman image list --format json
+ podman image list --sort repository --format "table {{.ID}} {{.Repository}} {{.Tag}}"
+ podman image list --filter dangling=true`,
+ }
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ Command: listCmd,
+ Parent: imageCmd,
+ })
+}
+
+func images(cmd *cobra.Command, args []string) error {
+ return nil
+}
diff --git a/cmd/podmanV2/main.go b/cmd/podmanV2/main.go
new file mode 100644
index 000000000..0df086352
--- /dev/null
+++ b/cmd/podmanV2/main.go
@@ -0,0 +1,84 @@
+package main
+
+import (
+ "fmt"
+ "os"
+ "reflect"
+ "runtime"
+
+ _ "github.com/containers/libpod/cmd/podmanV2/containers"
+ _ "github.com/containers/libpod/cmd/podmanV2/images"
+ _ "github.com/containers/libpod/cmd/podmanV2/networks"
+ _ "github.com/containers/libpod/cmd/podmanV2/pods"
+ "github.com/containers/libpod/cmd/podmanV2/registry"
+ _ "github.com/containers/libpod/cmd/podmanV2/volumes"
+ "github.com/containers/libpod/libpod"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/sirupsen/logrus"
+ "github.com/spf13/cobra"
+)
+
+func init() {
+ if err := libpod.SetXdgDirs(); err != nil {
+ logrus.Errorf(err.Error())
+ os.Exit(1)
+ }
+ initCobra()
+}
+
+func initCobra() {
+ switch runtime.GOOS {
+ case "darwin":
+ fallthrough
+ case "windows":
+ registry.GlobalFlags.EngineMode = entities.TunnelMode
+ case "linux":
+ registry.GlobalFlags.EngineMode = entities.ABIMode
+ default:
+ logrus.Errorf("%s is not a supported OS", runtime.GOOS)
+ os.Exit(1)
+ }
+
+ // TODO: Is there a Cobra way to "peek" at os.Args?
+ if ok := Contains("--remote", os.Args); ok {
+ registry.GlobalFlags.EngineMode = entities.TunnelMode
+ }
+
+ cobra.OnInitialize(func() {})
+}
+
+func main() {
+ fmt.Fprintf(os.Stderr, "Number of commands: %d\n", len(registry.Commands))
+ for _, c := range registry.Commands {
+ if Contains(registry.GlobalFlags.EngineMode, c.Mode) {
+ parent := rootCmd
+ if c.Parent != nil {
+ parent = c.Parent
+ }
+ parent.AddCommand(c.Command)
+ }
+ }
+
+ Execute()
+ os.Exit(0)
+}
+
+func Contains(item interface{}, slice interface{}) bool {
+ s := reflect.ValueOf(slice)
+
+ switch s.Kind() {
+ case reflect.Array:
+ fallthrough
+ case reflect.Slice:
+ break
+ default:
+ return false
+ }
+
+ for i := 0; i < s.Len(); i++ {
+ if s.Index(i).Interface() == item {
+ return true
+ }
+ }
+ return false
+}
diff --git a/cmd/podmanV2/networks/network.go b/cmd/podmanV2/networks/network.go
new file mode 100644
index 000000000..fc92d2321
--- /dev/null
+++ b/cmd/podmanV2/networks/network.go
@@ -0,0 +1,33 @@
+package images
+
+import (
+ "github.com/containers/libpod/cmd/podmanV2/registry"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/spf13/cobra"
+)
+
+var (
+ // Command: podman _network_
+ cmd = &cobra.Command{
+ Use: "network",
+ Short: "Manage networks",
+ Long: "Manage networks",
+ TraverseChildren: true,
+ PersistentPreRunE: preRunE,
+ RunE: registry.SubCommandExists,
+ }
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode},
+ Command: cmd,
+ })
+ cmd.SetHelpTemplate(registry.HelpTemplate())
+ cmd.SetUsageTemplate(registry.UsageTemplate())
+}
+
+func preRunE(cmd *cobra.Command, args []string) error {
+ _, err := registry.NewContainerEngine(cmd, args)
+ return err
+}
diff --git a/cmd/podmanV2/pods/pod.go b/cmd/podmanV2/pods/pod.go
new file mode 100644
index 000000000..81c0d33e1
--- /dev/null
+++ b/cmd/podmanV2/pods/pod.go
@@ -0,0 +1,33 @@
+package pods
+
+import (
+ "github.com/containers/libpod/cmd/podmanV2/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,
+ PersistentPreRunE: preRunE,
+ RunE: registry.SubCommandExists,
+ }
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ Command: podCmd,
+ })
+ podCmd.SetHelpTemplate(registry.HelpTemplate())
+ podCmd.SetUsageTemplate(registry.UsageTemplate())
+}
+
+func preRunE(cmd *cobra.Command, args []string) error {
+ _, err := registry.NewContainerEngine(cmd, args)
+ return err
+}
diff --git a/cmd/podmanV2/pods/ps.go b/cmd/podmanV2/pods/ps.go
new file mode 100644
index 000000000..d4c625b2e
--- /dev/null
+++ b/cmd/podmanV2/pods/ps.go
@@ -0,0 +1,32 @@
+package pods
+
+import (
+ "github.com/containers/libpod/cmd/podmanV2/registry"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "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,
+ }
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ Command: psCmd,
+ Parent: podCmd,
+ })
+}
+
+func pods(cmd *cobra.Command, args []string) error {
+ return nil
+}
diff --git a/cmd/podmanV2/registry/registry.go b/cmd/podmanV2/registry/registry.go
new file mode 100644
index 000000000..fa51d6535
--- /dev/null
+++ b/cmd/podmanV2/registry/registry.go
@@ -0,0 +1,96 @@
+package registry
+
+import (
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/containers/libpod/pkg/domain/infra"
+ "github.com/pkg/errors"
+ "github.com/spf13/cobra"
+)
+
+type CliCommand struct {
+ Mode []entities.EngineMode
+ Command *cobra.Command
+ Parent *cobra.Command
+}
+
+var (
+ Commands []CliCommand
+ GlobalFlags entities.EngineFlags
+ imageEngine entities.ImageEngine
+ containerEngine entities.ContainerEngine
+ PodmanTunnel bool
+)
+
+// HelpTemplate returns the help template for podman commands
+// This uses the short and long options.
+// command should not use this.
+func HelpTemplate() string {
+ return `{{.Short}}
+
+Description:
+ {{.Long}}
+
+{{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}}`
+}
+
+// UsageTemplate returns the usage template for podman commands
+// This blocks the displaying of the global options. The main podman
+// command should not use this.
+func UsageTemplate() string {
+ return `Usage(v2):{{if (and .Runnable (not .HasAvailableSubCommands))}}
+ {{.UseLine}}{{end}}{{if .HasAvailableSubCommands}}
+ {{.CommandPath}} [command]{{end}}{{if gt (len .Aliases) 0}}
+
+Aliases:
+ {{.NameAndAliases}}{{end}}{{if .HasExample}}
+
+Examples:
+ {{.Example}}{{end}}{{if .HasAvailableSubCommands}}
+
+Available Commands:{{range .Commands}}{{if (or .IsAvailableCommand (eq .Name "help"))}}
+ {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableLocalFlags}}
+
+Flags:
+{{.LocalFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasAvailableInheritedFlags}}
+{{end}}
+`
+}
+
+func ImageEngine() entities.ImageEngine {
+ return imageEngine
+}
+
+// NewImageEngine is a wrapper for building an ImageEngine to be used for PreRunE functions
+func NewImageEngine(cmd *cobra.Command, args []string) (entities.ImageEngine, error) {
+ if imageEngine == nil {
+ engine, err := infra.NewImageEngine(GlobalFlags.EngineMode, entities.EngineOptions{})
+ if err != nil {
+ return nil, err
+ }
+ imageEngine = engine
+ }
+ return imageEngine, nil
+}
+
+func ContainerEngine() entities.ContainerEngine {
+ return containerEngine
+}
+
+// NewContainerEngine is a wrapper for building an ContainerEngine to be used for PreRunE functions
+func NewContainerEngine(cmd *cobra.Command, args []string) (entities.ContainerEngine, error) {
+ if containerEngine == nil {
+ engine, err := infra.NewContainerEngine(GlobalFlags.EngineMode, entities.EngineOptions{})
+ if err != nil {
+ return nil, err
+ }
+ containerEngine = engine
+ }
+ return containerEngine, nil
+}
+
+func SubCommandExists(cmd *cobra.Command, args []string) error {
+ if len(args) > 0 {
+ return errors.Errorf("unrecognized command `%[1]s %[2]s`\nTry '%[1]s --help' for more information.", cmd.CommandPath(), args[0])
+ }
+ return errors.Errorf("missing command '%[1]s COMMAND'\nTry '%[1]s --help' for more information.", cmd.CommandPath())
+}
diff --git a/cmd/podmanV2/report/templates.go b/cmd/podmanV2/report/templates.go
new file mode 100644
index 000000000..dc43d4f9b
--- /dev/null
+++ b/cmd/podmanV2/report/templates.go
@@ -0,0 +1,61 @@
+package report
+
+import (
+ "strings"
+ "text/template"
+ "time"
+
+ "github.com/docker/go-units"
+)
+
+var defaultFuncMap = template.FuncMap{
+ "ellipsis": func(s string, length int) string {
+ if len(s) > length {
+ return s[:length-3] + "..."
+ }
+ return s
+ },
+ // TODO: Remove on Go 1.14 port
+ "slice": func(s string, i, j int) string {
+ if i > j || len(s) < i {
+ return s
+ }
+ if len(s) < j {
+ return s[i:]
+ }
+ return s[i:j]
+ },
+ "toRFC3339": func(t int64) string {
+ return time.Unix(t, 0).Format(time.RFC3339)
+ },
+ "toHumanDuration": func(t int64) string {
+ return units.HumanDuration(time.Since(time.Unix(t, 0))) + " ago"
+ },
+ "toHumanSize": func(sz int64) string {
+ return units.HumanSize(float64(sz))
+ },
+}
+
+func ReportHeader(columns ...string) []byte {
+ hdr := make([]string, len(columns))
+ for i, h := range columns {
+ hdr[i] = strings.ToUpper(h)
+ }
+ return []byte(strings.Join(hdr, "\t") + "\n")
+}
+
+func AppendFuncMap(funcMap template.FuncMap) template.FuncMap {
+ merged := PodmanTemplateFuncs()
+ for k, v := range funcMap {
+ merged[k] = v
+ }
+ return merged
+}
+
+func PodmanTemplateFuncs() template.FuncMap {
+ merged := make(template.FuncMap)
+ for k, v := range defaultFuncMap {
+ merged[k] = v
+ }
+ return merged
+}
diff --git a/cmd/podmanV2/root.go b/cmd/podmanV2/root.go
new file mode 100644
index 000000000..778184f28
--- /dev/null
+++ b/cmd/podmanV2/root.go
@@ -0,0 +1,35 @@
+package main
+
+import (
+ "fmt"
+ "os"
+ "path"
+
+ "github.com/containers/libpod/cmd/podmanV2/registry"
+ "github.com/containers/libpod/version"
+ "github.com/spf13/cobra"
+)
+
+var rootCmd = &cobra.Command{
+ Use: path.Base(os.Args[0]),
+ Long: "Manage pods, containers and images",
+ SilenceUsage: true,
+ SilenceErrors: true,
+ TraverseChildren: true,
+ RunE: registry.SubCommandExists,
+ Version: version.Version,
+}
+
+func init() {
+ // Override default --help information of `--version` global flag}
+ var dummyVersion bool
+ rootCmd.PersistentFlags().BoolVarP(&dummyVersion, "version", "v", false, "Version of podman")
+ rootCmd.PersistentFlags().BoolVarP(&registry.PodmanTunnel, "remote", "r", false, "Access service via SSH tunnel")
+}
+
+func Execute() {
+ if err := rootCmd.Execute(); err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ }
+}
diff --git a/cmd/podmanV2/system/system.go b/cmd/podmanV2/system/system.go
new file mode 100644
index 000000000..30ed328e8
--- /dev/null
+++ b/cmd/podmanV2/system/system.go
@@ -0,0 +1,33 @@
+package images
+
+import (
+ "github.com/containers/libpod/cmd/podmanV2/registry"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/spf13/cobra"
+)
+
+var (
+ // Command: podman _system_
+ cmd = &cobra.Command{
+ Use: "system",
+ Short: "Manage podman",
+ Long: "Manage podman",
+ TraverseChildren: true,
+ PersistentPreRunE: preRunE,
+ RunE: registry.SubCommandExists,
+ }
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ Command: cmd,
+ })
+ cmd.SetHelpTemplate(registry.HelpTemplate())
+ cmd.SetUsageTemplate(registry.UsageTemplate())
+}
+
+func preRunE(cmd *cobra.Command, args []string) error {
+ _, err := registry.NewContainerEngine(cmd, args)
+ return err
+}
diff --git a/cmd/podmanV2/volumes/volume.go b/cmd/podmanV2/volumes/volume.go
new file mode 100644
index 000000000..245c06da0
--- /dev/null
+++ b/cmd/podmanV2/volumes/volume.go
@@ -0,0 +1,33 @@
+package images
+
+import (
+ "github.com/containers/libpod/cmd/podmanV2/registry"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/spf13/cobra"
+)
+
+var (
+ // Command: podman _volume_
+ cmd = &cobra.Command{
+ Use: "volume",
+ Short: "Manage volumes",
+ Long: "Volumes are created in and can be shared between containers",
+ TraverseChildren: true,
+ PersistentPreRunE: preRunE,
+ RunE: registry.SubCommandExists,
+ }
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ Command: cmd,
+ })
+ cmd.SetHelpTemplate(registry.HelpTemplate())
+ cmd.SetUsageTemplate(registry.UsageTemplate())
+}
+
+func preRunE(cmd *cobra.Command, args []string) error {
+ _, err := registry.NewContainerEngine(cmd, args)
+ return err
+}