From 22d5b2e3053ad66ce3b30eba3adfca70bc8e389d Mon Sep 17 00:00:00 2001
From: Jhon Honce <jhonce@redhat.com>
Date: Wed, 29 Apr 2020 15:44:44 -0700
Subject: V2 enable ps tests

* Combine cobra.Command helper functions into validate package
  from registry and common packages
* Introduce ChoiceValue for flags

Signed-off-by: Jhon Honce <jhonce@redhat.com>
---
 cmd/podman/common/ports.go            |  6 ++---
 cmd/podman/common/specgen.go          | 20 +++++++--------
 cmd/podman/common/util.go             | 11 ---------
 cmd/podman/containers/container.go    |  3 ++-
 cmd/podman/containers/create.go       |  2 +-
 cmd/podman/containers/diff.go         |  3 ++-
 cmd/podman/containers/list.go         |  4 +--
 cmd/podman/containers/ps.go           | 15 +++++++-----
 cmd/podman/containers/wait.go         |  3 ++-
 cmd/podman/diff.go                    |  3 ++-
 cmd/podman/generate/generate.go       |  3 ++-
 cmd/podman/healthcheck/healthcheck.go |  3 ++-
 cmd/podman/images/image.go            |  3 ++-
 cmd/podman/images/prune.go            |  4 +--
 cmd/podman/manifest/manifest.go       |  3 ++-
 cmd/podman/networks/network.go        |  5 ++--
 cmd/podman/parse/net.go               |  4 +--
 cmd/podman/parse/net_test.go          |  4 +--
 cmd/podman/pods/create.go             |  5 ++--
 cmd/podman/pods/pod.go                |  3 ++-
 cmd/podman/pods/ps.go                 |  6 ++---
 cmd/podman/registry/registry.go       | 17 -------------
 cmd/podman/root.go                    |  3 ++-
 cmd/podman/system/events.go           |  4 +--
 cmd/podman/system/info.go             |  4 +--
 cmd/podman/system/system.go           |  3 ++-
 cmd/podman/system/version.go          | 10 ++++----
 cmd/podman/utils/alias.go             |  2 +-
 cmd/podman/validate/args.go           | 32 ++++++++++++++++++++++++
 cmd/podman/validate/choice.go         | 46 +++++++++++++++++++++++++++++++++++
 cmd/podman/volumes/list.go            |  4 +--
 cmd/podman/volumes/prune.go           |  4 +--
 cmd/podman/volumes/volume.go          |  3 ++-
 33 files changed, 156 insertions(+), 89 deletions(-)
 create mode 100644 cmd/podman/validate/args.go
 create mode 100644 cmd/podman/validate/choice.go

(limited to 'cmd')

diff --git a/cmd/podman/common/ports.go b/cmd/podman/common/ports.go
index a96bafabd..2092bbe53 100644
--- a/cmd/podman/common/ports.go
+++ b/cmd/podman/common/ports.go
@@ -9,10 +9,10 @@ func verifyExpose(expose []string) error {
 	// add the expose ports from the user (--expose)
 	// can be single or a range
 	for _, expose := range expose {
-		//support two formats for expose, original format <portnum>/[<proto>] or <startport-endport>/[<proto>]
+		// support two formats for expose, original format <portnum>/[<proto>] or <startport-endport>/[<proto>]
 		_, port := nat.SplitProtoPort(expose)
-		//parse the start and end port and create a sequence of ports to expose
-		//if expose a port, the start and end port are the same
+		// parse the start and end port and create a sequence of ports to expose
+		// if expose a port, the start and end port are the same
 		_, _, err := nat.ParsePortRange(port)
 		if err != nil {
 			return errors.Wrapf(err, "invalid range format for --expose: %s", expose)
diff --git a/cmd/podman/common/specgen.go b/cmd/podman/common/specgen.go
index f8c58f1a4..96cd630a3 100644
--- a/cmd/podman/common/specgen.go
+++ b/cmd/podman/common/specgen.go
@@ -192,7 +192,7 @@ func getMemoryLimits(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []strin
 func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string) error {
 	var (
 		err error
-		//namespaces map[string]string
+		// namespaces map[string]string
 	)
 
 	// validate flags as needed
@@ -485,7 +485,7 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string
 	// TODO
 	// ouitside of specgen and oci though
 	// defaults to true, check spec/storage
-	//s.readon = c.ReadOnlyTmpFS
+	// s.readon = c.ReadOnlyTmpFS
 	//  TODO convert to map?
 	// check if key=value and convert
 	sysmap := make(map[string]string)
@@ -528,7 +528,7 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string
 
 	// Only add read-only tmpfs mounts in case that we are read-only and the
 	// read-only tmpfs flag has been set.
-	mounts, volumes, err := parseVolumes(c.Volume, c.Mount, c.TmpFS, (c.ReadOnlyTmpFS && c.ReadOnly))
+	mounts, volumes, err := parseVolumes(c.Volume, c.Mount, c.TmpFS, c.ReadOnlyTmpFS && c.ReadOnly)
 	if err != nil {
 		return err
 	}
@@ -536,12 +536,12 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string
 	s.Volumes = volumes
 
 	// TODO any idea why this was done
-	//devices := rtc.Containers.Devices
+	// devices := rtc.Containers.Devices
 	// TODO conflict on populate?
 	//
-	//if c.Changed("device") {
+	// if c.Changed("device") {
 	//	devices = append(devices, c.StringSlice("device")...)
-	//}
+	// }
 
 	for _, dev := range c.Devices {
 		s.Devices = append(s.Devices, specs.LinuxDevice{Path: dev})
@@ -553,7 +553,7 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string
 	// initpath
 	s.Stdin = c.Interactive
 	// quiet
-	//DeviceCgroupRules: c.StringSlice("device-cgroup-rule"),
+	// DeviceCgroupRules: c.StringSlice("device-cgroup-rule"),
 
 	// Rlimits/Ulimits
 	for _, u := range c.Ulimit {
@@ -573,10 +573,10 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string
 		s.Rlimits = append(s.Rlimits, rl)
 	}
 
-	//Tmpfs:         c.StringArray("tmpfs"),
+	// Tmpfs:         c.StringArray("tmpfs"),
 
 	// TODO how to handle this?
-	//Syslog:        c.Bool("syslog"),
+	// Syslog:        c.Bool("syslog"),
 
 	logOpts := make(map[string]string)
 	for _, o := range c.LogOptions {
@@ -602,7 +602,7 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string
 	s.StopTimeout = &c.StopTimeout
 
 	// TODO where should we do this?
-	//func verifyContainerResources(config *cc.CreateConfig, update bool) ([]string, error) {
+	// func verifyContainerResources(config *cc.CreateConfig, update bool) ([]string, error) {
 	return nil
 }
 
diff --git a/cmd/podman/common/util.go b/cmd/podman/common/util.go
index 5b99b8398..47bbe12fa 100644
--- a/cmd/podman/common/util.go
+++ b/cmd/podman/common/util.go
@@ -1,11 +1,8 @@
 package common
 
 import (
-	"fmt"
 	"strconv"
 
-	"github.com/spf13/cobra"
-
 	"github.com/cri-o/ocicni/pkg/ocicni"
 	"github.com/docker/go-connections/nat"
 	"github.com/pkg/errors"
@@ -44,11 +41,3 @@ func createPortBindings(ports []string) ([]ocicni.PortMapping, error) {
 	}
 	return portBindings, nil
 }
-
-// NoArgs returns an error if any args are included.
-func NoArgs(cmd *cobra.Command, args []string) error {
-	if len(args) > 0 {
-		return fmt.Errorf("`%s` takes no arguments", cmd.CommandPath())
-	}
-	return nil
-}
diff --git a/cmd/podman/containers/container.go b/cmd/podman/containers/container.go
index 97b73cdd0..a102318fb 100644
--- a/cmd/podman/containers/container.go
+++ b/cmd/podman/containers/container.go
@@ -2,6 +2,7 @@ package containers
 
 import (
 	"github.com/containers/libpod/cmd/podman/registry"
+	"github.com/containers/libpod/cmd/podman/validate"
 	"github.com/containers/libpod/pkg/domain/entities"
 	"github.com/containers/libpod/pkg/util"
 	"github.com/spf13/cobra"
@@ -17,7 +18,7 @@ var (
 		Short:            "Manage containers",
 		Long:             "Manage containers",
 		TraverseChildren: true,
-		RunE:             registry.SubCommandExists,
+		RunE:             validate.SubCommandExists,
 	}
 
 	containerConfig = util.DefaultContainerConfig()
diff --git a/cmd/podman/containers/create.go b/cmd/podman/containers/create.go
index da550b606..3e47a8b4f 100644
--- a/cmd/podman/containers/create.go
+++ b/cmd/podman/containers/create.go
@@ -59,7 +59,7 @@ func init() {
 		Mode:    []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
 		Command: createCommand,
 	})
-	//common.GetCreateFlags(createCommand)
+	// common.GetCreateFlags(createCommand)
 	flags := createCommand.Flags()
 	createFlags(flags)
 
diff --git a/cmd/podman/containers/diff.go b/cmd/podman/containers/diff.go
index 046dac53e..59b788010 100644
--- a/cmd/podman/containers/diff.go
+++ b/cmd/podman/containers/diff.go
@@ -3,6 +3,7 @@ package containers
 import (
 	"github.com/containers/libpod/cmd/podman/registry"
 	"github.com/containers/libpod/cmd/podman/report"
+	"github.com/containers/libpod/cmd/podman/validate"
 	"github.com/containers/libpod/pkg/domain/entities"
 	"github.com/pkg/errors"
 	"github.com/spf13/cobra"
@@ -12,7 +13,7 @@ var (
 	// podman container _diff_
 	diffCmd = &cobra.Command{
 		Use:   "diff [flags] CONTAINER",
-		Args:  registry.IdOrLatestArgs,
+		Args:  validate.IdOrLatestArgs,
 		Short: "Inspect changes on container's file systems",
 		Long:  `Displays changes on a container filesystem.  The container will be compared to its parent layer.`,
 		RunE:  diff,
diff --git a/cmd/podman/containers/list.go b/cmd/podman/containers/list.go
index 22fa15b7e..c200a49aa 100644
--- a/cmd/podman/containers/list.go
+++ b/cmd/podman/containers/list.go
@@ -1,8 +1,8 @@
 package containers
 
 import (
-	"github.com/containers/libpod/cmd/podman/common"
 	"github.com/containers/libpod/cmd/podman/registry"
+	"github.com/containers/libpod/cmd/podman/validate"
 	"github.com/containers/libpod/pkg/domain/entities"
 	"github.com/spf13/cobra"
 )
@@ -12,7 +12,7 @@ var (
 	listCmd = &cobra.Command{
 		Use:     "list",
 		Aliases: []string{"ls"},
-		Args:    common.NoArgs,
+		Args:    validate.NoArgs,
 		Short:   "List containers",
 		Long:    "Prints out information about the containers",
 		RunE:    ps,
diff --git a/cmd/podman/containers/ps.go b/cmd/podman/containers/ps.go
index 44f50bab2..c5696a158 100644
--- a/cmd/podman/containers/ps.go
+++ b/cmd/podman/containers/ps.go
@@ -12,8 +12,8 @@ import (
 
 	tm "github.com/buger/goterm"
 	"github.com/containers/buildah/pkg/formats"
-	"github.com/containers/libpod/cmd/podman/common"
 	"github.com/containers/libpod/cmd/podman/registry"
+	"github.com/containers/libpod/cmd/podman/validate"
 	"github.com/containers/libpod/pkg/domain/entities"
 	"github.com/cri-o/ocicni/pkg/ocicni"
 	"github.com/docker/go-units"
@@ -26,7 +26,7 @@ var (
 	psDescription = "Prints out information about the containers"
 	psCommand     = &cobra.Command{
 		Use:   "ps",
-		Args:  common.NoArgs,
+		Args:  validate.NoArgs,
 		Short: "List containers",
 		Long:  psDescription,
 		RunE:  ps,
@@ -41,7 +41,7 @@ var (
 	}
 	filters        []string
 	noTrunc        bool
-	defaultHeaders string = "CONTAINER ID\tIMAGE\tCOMMAND\tCREATED\tSTATUS\tPORTS\tNAMES"
+	defaultHeaders = "CONTAINER ID\tIMAGE\tCOMMAND\tCREATED\tSTATUS\tPORTS\tNAMES"
 )
 
 func init() {
@@ -64,9 +64,12 @@ func listFlagSet(flags *pflag.FlagSet) {
 	flags.BoolVarP(&listOpts.Pod, "pod", "p", false, "Print the ID and name of the pod the containers are associated with")
 	flags.BoolVarP(&listOpts.Quiet, "quiet", "q", false, "Print the numeric IDs of the containers only")
 	flags.BoolVarP(&listOpts.Size, "size", "s", false, "Display the total file sizes")
-	flags.StringVar(&listOpts.Sort, "sort", "created", "Sort output by command, created, id, image, names, runningfor, size, or status")
 	flags.BoolVar(&listOpts.Sync, "sync", false, "Sync container state with OCI runtime")
 	flags.UintVarP(&listOpts.Watch, "watch", "w", 0, "Watch the ps output on an interval in seconds")
+
+	created := validate.ChoiceValue(&listOpts.Sort, "command", "created", "id", "image", "names", "runningfor", "size", "status")
+	flags.Var(created, "sort", "Sort output by: "+created.Choices())
+
 	if registry.IsRemote() {
 		_ = flags.MarkHidden("latest")
 	}
@@ -175,7 +178,7 @@ func ps(cmd *cobra.Command, args []string) error {
 
 	headers, format := createPsOut()
 	if cmd.Flag("format").Changed {
-		format = listOpts.Format
+		format = strings.TrimPrefix(listOpts.Format, "table ")
 		if !strings.HasPrefix(format, "\n") {
 			format += "\n"
 		}
@@ -352,7 +355,7 @@ func portsToString(ports []ocicni.PortMapping) string {
 	if len(ports) == 0 {
 		return ""
 	}
-	//Sort the ports, so grouping continuous ports become easy.
+	// Sort the ports, so grouping continuous ports become easy.
 	sort.Slice(ports, func(i, j int) bool {
 		return comparePorts(ports[i], ports[j])
 	})
diff --git a/cmd/podman/containers/wait.go b/cmd/podman/containers/wait.go
index da746361d..eac1e2956 100644
--- a/cmd/podman/containers/wait.go
+++ b/cmd/podman/containers/wait.go
@@ -7,6 +7,7 @@ import (
 
 	"github.com/containers/libpod/cmd/podman/registry"
 	"github.com/containers/libpod/cmd/podman/utils"
+	"github.com/containers/libpod/cmd/podman/validate"
 	"github.com/containers/libpod/libpod/define"
 	"github.com/containers/libpod/pkg/domain/entities"
 	"github.com/pkg/errors"
@@ -22,7 +23,7 @@ var (
 		Short: "Block on one or more containers",
 		Long:  waitDescription,
 		RunE:  wait,
-		Args:  registry.IdOrLatestArgs,
+		Args:  validate.IdOrLatestArgs,
 		Example: `podman wait --latest
   podman wait --interval 5000 ctrID
   podman wait ctrID1 ctrID2`,
diff --git a/cmd/podman/diff.go b/cmd/podman/diff.go
index ec94c0918..1ff2fce40 100644
--- a/cmd/podman/diff.go
+++ b/cmd/podman/diff.go
@@ -6,6 +6,7 @@ import (
 	"github.com/containers/libpod/cmd/podman/containers"
 	"github.com/containers/libpod/cmd/podman/images"
 	"github.com/containers/libpod/cmd/podman/registry"
+	"github.com/containers/libpod/cmd/podman/validate"
 	"github.com/containers/libpod/pkg/domain/entities"
 	"github.com/spf13/cobra"
 )
@@ -17,7 +18,7 @@ var (
 	diffDescription = `Displays changes on a container or image's filesystem.  The container or image will be compared to its parent layer.`
 	diffCmd         = &cobra.Command{
 		Use:              "diff [flags] {CONTAINER_ID | IMAGE_ID}",
-		Args:             registry.IdOrLatestArgs,
+		Args:             validate.IdOrLatestArgs,
 		Short:            "Display the changes of object's file system",
 		Long:             diffDescription,
 		TraverseChildren: true,
diff --git a/cmd/podman/generate/generate.go b/cmd/podman/generate/generate.go
index f04ef58a5..b112e666a 100644
--- a/cmd/podman/generate/generate.go
+++ b/cmd/podman/generate/generate.go
@@ -2,6 +2,7 @@ package pods
 
 import (
 	"github.com/containers/libpod/cmd/podman/registry"
+	"github.com/containers/libpod/cmd/podman/validate"
 	"github.com/containers/libpod/pkg/domain/entities"
 	"github.com/containers/libpod/pkg/util"
 	"github.com/spf13/cobra"
@@ -14,7 +15,7 @@ var (
 		Short:            "Generate structured data based on containers and pods.",
 		Long:             "Generate structured data (e.g., Kubernetes yaml or systemd units) based on containers and pods.",
 		TraverseChildren: true,
-		RunE:             registry.SubCommandExists,
+		RunE:             validate.SubCommandExists,
 	}
 	containerConfig = util.DefaultContainerConfig()
 )
diff --git a/cmd/podman/healthcheck/healthcheck.go b/cmd/podman/healthcheck/healthcheck.go
index 794a94615..ce90dba31 100644
--- a/cmd/podman/healthcheck/healthcheck.go
+++ b/cmd/podman/healthcheck/healthcheck.go
@@ -2,6 +2,7 @@ package healthcheck
 
 import (
 	"github.com/containers/libpod/cmd/podman/registry"
+	"github.com/containers/libpod/cmd/podman/validate"
 	"github.com/containers/libpod/pkg/domain/entities"
 	"github.com/spf13/cobra"
 )
@@ -13,7 +14,7 @@ var (
 		Short:            "Manage Healthcheck",
 		Long:             "Manage Healthcheck",
 		TraverseChildren: true,
-		RunE:             registry.SubCommandExists,
+		RunE:             validate.SubCommandExists,
 	}
 )
 
diff --git a/cmd/podman/images/image.go b/cmd/podman/images/image.go
index 604f49251..790c16c05 100644
--- a/cmd/podman/images/image.go
+++ b/cmd/podman/images/image.go
@@ -2,6 +2,7 @@ package images
 
 import (
 	"github.com/containers/libpod/cmd/podman/registry"
+	"github.com/containers/libpod/cmd/podman/validate"
 	"github.com/containers/libpod/pkg/domain/entities"
 	"github.com/spf13/cobra"
 )
@@ -16,7 +17,7 @@ var (
 		Short:            "Manage images",
 		Long:             "Manage images",
 		TraverseChildren: true,
-		RunE:             registry.SubCommandExists,
+		RunE:             validate.SubCommandExists,
 	}
 )
 
diff --git a/cmd/podman/images/prune.go b/cmd/podman/images/prune.go
index eb9e4a7e4..53a1966c1 100644
--- a/cmd/podman/images/prune.go
+++ b/cmd/podman/images/prune.go
@@ -6,8 +6,8 @@ import (
 	"os"
 	"strings"
 
-	"github.com/containers/libpod/cmd/podman/common"
 	"github.com/containers/libpod/cmd/podman/registry"
+	"github.com/containers/libpod/cmd/podman/validate"
 	"github.com/containers/libpod/pkg/domain/entities"
 	"github.com/pkg/errors"
 	"github.com/spf13/cobra"
@@ -19,7 +19,7 @@ var (
   If an image is not being used by a container, it will be removed from the system.`
 	pruneCmd = &cobra.Command{
 		Use:     "prune",
-		Args:    common.NoArgs,
+		Args:    validate.NoArgs,
 		Short:   "Remove unused images",
 		Long:    pruneDescription,
 		RunE:    prune,
diff --git a/cmd/podman/manifest/manifest.go b/cmd/podman/manifest/manifest.go
index b9ac7ea68..b78879b34 100644
--- a/cmd/podman/manifest/manifest.go
+++ b/cmd/podman/manifest/manifest.go
@@ -2,6 +2,7 @@ package manifest
 
 import (
 	"github.com/containers/libpod/cmd/podman/registry"
+	"github.com/containers/libpod/cmd/podman/validate"
 	"github.com/containers/libpod/pkg/domain/entities"
 	"github.com/spf13/cobra"
 )
@@ -13,7 +14,7 @@ var (
 		Short:            "Manipulate manifest lists and image indexes",
 		Long:             manifestDescription,
 		TraverseChildren: true,
-		RunE:             registry.SubCommandExists,
+		RunE:             validate.SubCommandExists,
 		Example: `podman manifest create localhost/list
   podman manifest inspect localhost/list`,
 	}
diff --git a/cmd/podman/networks/network.go b/cmd/podman/networks/network.go
index a0e412098..e2a928312 100644
--- a/cmd/podman/networks/network.go
+++ b/cmd/podman/networks/network.go
@@ -2,6 +2,7 @@ package images
 
 import (
 	"github.com/containers/libpod/cmd/podman/registry"
+	"github.com/containers/libpod/cmd/podman/validate"
 	"github.com/containers/libpod/pkg/domain/entities"
 	"github.com/spf13/cobra"
 )
@@ -13,13 +14,13 @@ var (
 		Short:            "Manage networks",
 		Long:             "Manage networks",
 		TraverseChildren: true,
-		RunE:             registry.SubCommandExists,
+		RunE:             validate.SubCommandExists,
 	}
 )
 
 // TODO add the following to main.go to get networks back onto the
 // command list.
-//_ "github.com/containers/libpod/cmd/podman/networks"
+// _ "github.com/containers/libpod/cmd/podman/networks"
 func init() {
 	registry.Commands = append(registry.Commands, registry.CliCommand{
 		Mode:    []entities.EngineMode{entities.ABIMode},
diff --git a/cmd/podman/parse/net.go b/cmd/podman/parse/net.go
index 03cda268c..f93c4ab1e 100644
--- a/cmd/podman/parse/net.go
+++ b/cmd/podman/parse/net.go
@@ -1,4 +1,4 @@
-//nolint
+// nolint
 // most of these validate and parse functions have been taken from projectatomic/docker
 // and modified for cri-o
 package parse
@@ -46,7 +46,7 @@ var (
 // validateExtraHost validates that the specified string is a valid extrahost and returns it.
 // ExtraHost is in the form of name:ip where the ip has to be a valid ip (ipv4 or ipv6).
 // for add-host flag
-func ValidateExtraHost(val string) (string, error) { //nolint
+func ValidateExtraHost(val string) (string, error) { // nolint
 	// allow for IPv6 addresses in extra hosts by only splitting on first ":"
 	arr := strings.SplitN(val, ":", 2)
 	if len(arr) != 2 || len(arr[0]) == 0 {
diff --git a/cmd/podman/parse/net_test.go b/cmd/podman/parse/net_test.go
index a6ddc2be9..51c8509df 100644
--- a/cmd/podman/parse/net_test.go
+++ b/cmd/podman/parse/net_test.go
@@ -1,4 +1,4 @@
-//nolint
+// nolint
 // most of these validate and parse functions have been taken from projectatomic/docker
 // and modified for cri-o
 package parse
@@ -41,7 +41,7 @@ func TestValidateExtraHost(t *testing.T) {
 		want    string
 		wantErr bool
 	}{
-		//2001:0db8:85a3:0000:0000:8a2e:0370:7334
+		// 2001:0db8:85a3:0000:0000:8a2e:0370:7334
 		{name: "good-ipv4", args: args{val: "foobar:192.168.1.1"}, want: "foobar:192.168.1.1", wantErr: false},
 		{name: "bad-ipv4", args: args{val: "foobar:999.999.999.99"}, want: "", wantErr: true},
 		{name: "bad-ipv4", args: args{val: "foobar:999.999.999"}, want: "", wantErr: true},
diff --git a/cmd/podman/pods/create.go b/cmd/podman/pods/create.go
index 0c0d07b3e..85b96d37b 100644
--- a/cmd/podman/pods/create.go
+++ b/cmd/podman/pods/create.go
@@ -9,6 +9,7 @@ import (
 	"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/cmd/podman/validate"
 	"github.com/containers/libpod/pkg/domain/entities"
 	"github.com/containers/libpod/pkg/errorhandling"
 	"github.com/containers/libpod/pkg/specgen"
@@ -24,7 +25,7 @@ var (
 
 	createCommand = &cobra.Command{
 		Use:   "create",
-		Args:  common.NoArgs,
+		Args:  validate.NoArgs,
 		Short: "Create a new empty pod",
 		Long:  podCreateDescription,
 		RunE:  create,
@@ -116,7 +117,7 @@ func create(cmd *cobra.Command, args []string) error {
 	case "slip4netns":
 		n.NSMode = specgen.Slirp
 	default:
-		if strings.HasPrefix(netInput, "container:") { //nolint
+		if strings.HasPrefix(netInput, "container:") { // nolint
 			split := strings.Split(netInput, ":")
 			if len(split) != 2 {
 				return errors.Errorf("invalid network paramater: %q", netInput)
diff --git a/cmd/podman/pods/pod.go b/cmd/podman/pods/pod.go
index e86b8aba4..edca08202 100644
--- a/cmd/podman/pods/pod.go
+++ b/cmd/podman/pods/pod.go
@@ -2,6 +2,7 @@ package pods
 
 import (
 	"github.com/containers/libpod/cmd/podman/registry"
+	"github.com/containers/libpod/cmd/podman/validate"
 	"github.com/containers/libpod/pkg/domain/entities"
 	"github.com/containers/libpod/pkg/util"
 	"github.com/spf13/cobra"
@@ -17,7 +18,7 @@ var (
 		Short:            "Manage pods",
 		Long:             "Manage pods",
 		TraverseChildren: true,
-		RunE:             registry.SubCommandExists,
+		RunE:             validate.SubCommandExists,
 	}
 	containerConfig = util.DefaultContainerConfig()
 )
diff --git a/cmd/podman/pods/ps.go b/cmd/podman/pods/ps.go
index 8ae1f91a8..b97dfeb66 100644
--- a/cmd/podman/pods/ps.go
+++ b/cmd/podman/pods/ps.go
@@ -11,8 +11,8 @@ import (
 	"text/template"
 	"time"
 
-	"github.com/containers/libpod/cmd/podman/common"
 	"github.com/containers/libpod/cmd/podman/registry"
+	"github.com/containers/libpod/cmd/podman/validate"
 	"github.com/containers/libpod/pkg/domain/entities"
 	"github.com/docker/go-units"
 	"github.com/pkg/errors"
@@ -29,12 +29,12 @@ var (
 		Short:   "list pods",
 		Long:    psDescription,
 		RunE:    pods,
-		Args:    common.NoArgs,
+		Args:    validate.NoArgs,
 	}
 )
 
 var (
-	defaultHeaders string = "POD ID\tNAME\tSTATUS\tCREATED"
+	defaultHeaders = "POD ID\tNAME\tSTATUS\tCREATED"
 	inputFilters   []string
 	noTrunc        bool
 	psInput        entities.PodPSOptions
diff --git a/cmd/podman/registry/registry.go b/cmd/podman/registry/registry.go
index 993b14cbc..69e2babfc 100644
--- a/cmd/podman/registry/registry.go
+++ b/cmd/podman/registry/registry.go
@@ -2,11 +2,9 @@ package registry
 
 import (
 	"context"
-	"fmt"
 
 	"github.com/containers/libpod/pkg/domain/entities"
 	"github.com/containers/libpod/pkg/domain/infra"
-	"github.com/pkg/errors"
 	"github.com/spf13/cobra"
 )
 
@@ -77,21 +75,6 @@ func NewContainerEngine(cmd *cobra.Command, args []string) (entities.ContainerEn
 	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())
-}
-
-// IdOrLatestArgs used to validate a nameOrId was provided or the "--latest" flag
-func IdOrLatestArgs(cmd *cobra.Command, args []string) error {
-	if len(args) > 1 || (len(args) == 0 && !cmd.Flag("latest").Changed) {
-		return fmt.Errorf("%s requires a name, id or the '--latest' flag", cmd.Name())
-	}
-	return nil
-}
-
 type PodmanOptionsKey struct{}
 
 func Context() context.Context {
diff --git a/cmd/podman/root.go b/cmd/podman/root.go
index 8baed42cf..375faf8b1 100644
--- a/cmd/podman/root.go
+++ b/cmd/podman/root.go
@@ -9,6 +9,7 @@ import (
 	"strings"
 
 	"github.com/containers/libpod/cmd/podman/registry"
+	"github.com/containers/libpod/cmd/podman/validate"
 	"github.com/containers/libpod/pkg/domain/entities"
 	"github.com/containers/libpod/pkg/rootless"
 	"github.com/containers/libpod/pkg/tracing"
@@ -60,7 +61,7 @@ var (
 		SilenceErrors:      true,
 		TraverseChildren:   true,
 		PersistentPreRunE:  persistentPreRunE,
-		RunE:               registry.SubCommandExists,
+		RunE:               validate.SubCommandExists,
 		PersistentPostRunE: persistentPostRunE,
 		Version:            version.Version,
 	}
diff --git a/cmd/podman/system/events.go b/cmd/podman/system/events.go
index 31dd9aa77..6aae62dc0 100644
--- a/cmd/podman/system/events.go
+++ b/cmd/podman/system/events.go
@@ -7,8 +7,8 @@ import (
 	"os"
 
 	"github.com/containers/buildah/pkg/formats"
-	"github.com/containers/libpod/cmd/podman/common"
 	"github.com/containers/libpod/cmd/podman/registry"
+	"github.com/containers/libpod/cmd/podman/validate"
 	"github.com/containers/libpod/libpod/events"
 	"github.com/containers/libpod/pkg/domain/entities"
 	"github.com/pkg/errors"
@@ -19,7 +19,7 @@ var (
 	eventsDescription = "Monitor podman events"
 	eventsCommand     = &cobra.Command{
 		Use:   "events",
-		Args:  common.NoArgs,
+		Args:  validate.NoArgs,
 		Short: "Show podman events",
 		Long:  eventsDescription,
 		RunE:  eventsCmd,
diff --git a/cmd/podman/system/info.go b/cmd/podman/system/info.go
index 143796938..26be794c5 100644
--- a/cmd/podman/system/info.go
+++ b/cmd/podman/system/info.go
@@ -5,8 +5,8 @@ import (
 	"os"
 	"text/template"
 
-	"github.com/containers/libpod/cmd/podman/common"
 	"github.com/containers/libpod/cmd/podman/registry"
+	"github.com/containers/libpod/cmd/podman/validate"
 	"github.com/containers/libpod/pkg/domain/entities"
 	"github.com/ghodss/yaml"
 	"github.com/spf13/cobra"
@@ -19,7 +19,7 @@ var (
 `
 	infoCommand = &cobra.Command{
 		Use:     "info",
-		Args:    common.NoArgs,
+		Args:    validate.NoArgs,
 		Long:    infoDescription,
 		Short:   "Display podman system information",
 		RunE:    info,
diff --git a/cmd/podman/system/system.go b/cmd/podman/system/system.go
index 2d55e8c13..d9691ad2a 100644
--- a/cmd/podman/system/system.go
+++ b/cmd/podman/system/system.go
@@ -2,6 +2,7 @@ package system
 
 import (
 	"github.com/containers/libpod/cmd/podman/registry"
+	"github.com/containers/libpod/cmd/podman/validate"
 	"github.com/containers/libpod/pkg/domain/entities"
 	"github.com/spf13/cobra"
 )
@@ -16,7 +17,7 @@ var (
 		Short:            "Manage podman",
 		Long:             "Manage podman",
 		TraverseChildren: true,
-		RunE:             registry.SubCommandExists,
+		RunE:             validate.SubCommandExists,
 	}
 )
 
diff --git a/cmd/podman/system/version.go b/cmd/podman/system/version.go
index b0f4eb528..065eef309 100644
--- a/cmd/podman/system/version.go
+++ b/cmd/podman/system/version.go
@@ -9,8 +9,8 @@ import (
 	"time"
 
 	"github.com/containers/buildah/pkg/formats"
-	"github.com/containers/libpod/cmd/podman/common"
 	"github.com/containers/libpod/cmd/podman/registry"
+	"github.com/containers/libpod/cmd/podman/validate"
 	"github.com/containers/libpod/libpod/define"
 	"github.com/containers/libpod/pkg/domain/entities"
 	"github.com/pkg/errors"
@@ -20,7 +20,7 @@ import (
 var (
 	versionCommand = &cobra.Command{
 		Use:   "version",
-		Args:  common.NoArgs,
+		Args:  validate.NoArgs,
 		Short: "Display the Podman Version Information",
 		RunE:  version,
 		Annotations: map[string]string{
@@ -56,14 +56,14 @@ func version(cmd *cobra.Command, args []string) error {
 	// TODO we need to discuss how to implement
 	// this more. current endpoints dont have a
 	// version endpoint.  maybe we use info?
-	//if remote {
+	// if remote {
 	//	v.Server, err = getRemoteVersion(c)
 	//	if err != nil {
 	//		return err
 	//	}
-	//} else {
+	// } else {
 	v.Server = v.Client
-	//}
+	// }
 
 	versionOutputFormat := versionFormat
 	if versionOutputFormat != "" {
diff --git a/cmd/podman/utils/alias.go b/cmd/podman/utils/alias.go
index 54b3c5e89..e484461c5 100644
--- a/cmd/podman/utils/alias.go
+++ b/cmd/podman/utils/alias.go
@@ -2,7 +2,7 @@ package utils
 
 import "github.com/spf13/pflag"
 
-// AliasFlags is a function to handle backwards compatability with old flags
+// AliasFlags is a function to handle backwards compatibility with old flags
 func AliasFlags(f *pflag.FlagSet, name string) pflag.NormalizedName {
 	switch name {
 	case "healthcheck-command":
diff --git a/cmd/podman/validate/args.go b/cmd/podman/validate/args.go
new file mode 100644
index 000000000..14b4d7897
--- /dev/null
+++ b/cmd/podman/validate/args.go
@@ -0,0 +1,32 @@
+package validate
+
+import (
+	"fmt"
+
+	"github.com/pkg/errors"
+	"github.com/spf13/cobra"
+)
+
+// NoArgs returns an error if any args are included.
+func NoArgs(cmd *cobra.Command, args []string) error {
+	if len(args) > 0 {
+		return fmt.Errorf("`%s` takes no arguments", cmd.CommandPath())
+	}
+	return nil
+}
+
+// SubCommandExists returns an error if no sub command is provided
+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())
+}
+
+// IdOrLatestArgs used to validate a nameOrId was provided or the "--latest" flag
+func IdOrLatestArgs(cmd *cobra.Command, args []string) error {
+	if len(args) > 1 || (len(args) == 0 && !cmd.Flag("latest").Changed) {
+		return fmt.Errorf("`%s` requires a name, id  or the \"--latest\" flag", cmd.CommandPath())
+	}
+	return nil
+}
diff --git a/cmd/podman/validate/choice.go b/cmd/podman/validate/choice.go
new file mode 100644
index 000000000..572c5f4a5
--- /dev/null
+++ b/cmd/podman/validate/choice.go
@@ -0,0 +1,46 @@
+package validate
+
+import (
+	"fmt"
+	"strings"
+)
+
+// Honors cobra.Value interface
+type choiceValue struct {
+	value   *string
+	choices []string
+}
+
+// ChoiceValue may be used in cobra FlagSet methods Var/VarP/VarPF() to select from a set of values
+//
+// Example:
+// 	created := validate.ChoiceValue(&opts.Sort, "command", "created", "id", "image", "names", "runningfor", "size", "status")
+//	flags.Var(created, "sort", "Sort output by: "+created.Choices())
+func ChoiceValue(p *string, choices ...string) *choiceValue {
+	return &choiceValue{
+		value:   p,
+		choices: choices,
+	}
+}
+
+func (c *choiceValue) String() string {
+	return *c.value
+}
+
+func (c *choiceValue) Set(value string) error {
+	for _, v := range c.choices {
+		if v == value {
+			*c.value = value
+			return nil
+		}
+	}
+	return fmt.Errorf("%q is not a valid value.  Choose from: %q", value, c.Choices())
+}
+
+func (c *choiceValue) Choices() string {
+	return strings.Join(c.choices, ", ")
+}
+
+func (c *choiceValue) Type() string {
+	return "choice"
+}
diff --git a/cmd/podman/volumes/list.go b/cmd/podman/volumes/list.go
index 8cc6fb301..72bf9f25b 100644
--- a/cmd/podman/volumes/list.go
+++ b/cmd/podman/volumes/list.go
@@ -9,8 +9,8 @@ import (
 	"strings"
 	"text/tabwriter"
 
-	"github.com/containers/libpod/cmd/podman/common"
 	"github.com/containers/libpod/cmd/podman/registry"
+	"github.com/containers/libpod/cmd/podman/validate"
 	"github.com/containers/libpod/pkg/domain/entities"
 	"github.com/pkg/errors"
 	"github.com/spf13/cobra"
@@ -25,7 +25,7 @@ and the output format can be changed to JSON or a user specified Go template.`
 	lsCommand = &cobra.Command{
 		Use:     "ls",
 		Aliases: []string{"list"},
-		Args:    common.NoArgs,
+		Args:    validate.NoArgs,
 		Short:   "List volumes",
 		Long:    volumeLsDescription,
 		RunE:    list,
diff --git a/cmd/podman/volumes/prune.go b/cmd/podman/volumes/prune.go
index 77138f4b7..2c3ed88f3 100644
--- a/cmd/podman/volumes/prune.go
+++ b/cmd/podman/volumes/prune.go
@@ -7,9 +7,9 @@ import (
 	"os"
 	"strings"
 
-	"github.com/containers/libpod/cmd/podman/common"
 	"github.com/containers/libpod/cmd/podman/registry"
 	"github.com/containers/libpod/cmd/podman/utils"
+	"github.com/containers/libpod/cmd/podman/validate"
 	"github.com/containers/libpod/pkg/domain/entities"
 	"github.com/pkg/errors"
 	"github.com/spf13/cobra"
@@ -22,7 +22,7 @@ var (
   Note all data will be destroyed.`
 	pruneCommand = &cobra.Command{
 		Use:   "prune",
-		Args:  common.NoArgs,
+		Args:  validate.NoArgs,
 		Short: "Remove all unused volumes",
 		Long:  volumePruneDescription,
 		RunE:  prune,
diff --git a/cmd/podman/volumes/volume.go b/cmd/podman/volumes/volume.go
index 4d74ff084..3e90d178c 100644
--- a/cmd/podman/volumes/volume.go
+++ b/cmd/podman/volumes/volume.go
@@ -2,6 +2,7 @@ package volumes
 
 import (
 	"github.com/containers/libpod/cmd/podman/registry"
+	"github.com/containers/libpod/cmd/podman/validate"
 	"github.com/containers/libpod/pkg/domain/entities"
 	"github.com/spf13/cobra"
 )
@@ -16,7 +17,7 @@ var (
 		Short:            "Manage volumes",
 		Long:             "Volumes are created in and can be shared between containers",
 		TraverseChildren: true,
-		RunE:             registry.SubCommandExists,
+		RunE:             validate.SubCommandExists,
 	}
 )
 
-- 
cgit v1.2.3-54-g00ecf