diff options
Diffstat (limited to 'cmd/podman/pod_ps.go')
-rw-r--r-- | cmd/podman/pod_ps.go | 227 |
1 files changed, 227 insertions, 0 deletions
diff --git a/cmd/podman/pod_ps.go b/cmd/podman/pod_ps.go new file mode 100644 index 000000000..f4e2d0ae5 --- /dev/null +++ b/cmd/podman/pod_ps.go @@ -0,0 +1,227 @@ +package main + +import ( + "reflect" + "strings" + + "github.com/pkg/errors" + "github.com/projectatomic/libpod/cmd/podman/batchcontainer" + "github.com/projectatomic/libpod/cmd/podman/formats" + "github.com/projectatomic/libpod/cmd/podman/libpodruntime" + "github.com/projectatomic/libpod/libpod" + "github.com/urfave/cli" +) + +var ( + opts batchcontainer.PsOptions +) + +type podPsOptions struct { + NoTrunc bool + Format string + Quiet bool + NumberOfContainers bool +} + +type podPsTemplateParams struct { + ID string + Name string + NumberOfContainers int +} + +// podPsJSONParams is used as a base structure for the psParams +// If template output is requested, podPsJSONParams will be converted to +// podPsTemplateParams. +// podPsJSONParams will be populated by data from libpod.Container, +// the members of the struct are the sama data types as their sources. +type podPsJSONParams struct { + ID string `json:"id"` + Name string `json:"name"` + NumberOfContainers int `json:"numberofcontainers"` +} + +var ( + podPsFlags = []cli.Flag{ + cli.BoolFlag{ + Name: "no-trunc", + Usage: "Display the extended information", + }, + cli.BoolFlag{ + Name: "quiet, q", + Usage: "Print the numeric IDs of the pods only", + }, + } + podPsDescription = "Prints out information about pods" + podPsCommand = cli.Command{ + Name: "ps", + Aliases: []string{"ls", "list"}, + Usage: "List pods", + Description: podPsDescription, + Flags: podPsFlags, + Action: podPsCmd, + UseShortOptionHandling: true, + } +) + +func podPsCmd(c *cli.Context) error { + if err := validateFlags(c, podPsFlags); err != nil { + return err + } + + if err := podCheckFlagsPassed(c); err != nil { + return errors.Wrapf(err, "error with flags passed") + } + + runtime, err := libpodruntime.GetRuntime(c) + if err != nil { + return errors.Wrapf(err, "error creating libpod runtime") + } + + defer runtime.Shutdown(false) + + if len(c.Args()) > 0 { + return errors.Errorf("too many arguments, ps takes no arguments") + } + + format := genPodPsFormat(c.Bool("quiet")) + + opts := podPsOptions{ + Format: format, + NoTrunc: c.Bool("no-trunc"), + Quiet: c.Bool("quiet"), + } + + var filterFuncs []libpod.PodFilter + + pods, err := runtime.Pods(filterFuncs...) + if err != nil { + return err + } + + return generatePodPsOutput(pods, opts, runtime) +} + +// podCheckFlagsPassed checks if mutually exclusive flags are passed together +func podCheckFlagsPassed(c *cli.Context) error { + // quiet, and format with Go template are mutually exclusive + flags := 0 + if c.Bool("quiet") { + flags++ + } + if flags > 1 { + return errors.Errorf("quiet, and format with Go template are mutually exclusive") + } + return nil +} + +// generate the template based on conditions given +func genPodPsFormat(quiet bool) string { + if quiet { + return formats.IDString + } + format := "table {{.ID}}\t{{.Name}}" + return format +} + +func podPsToGeneric(templParams []podPsTemplateParams, JSONParams []podPsJSONParams) (genericParams []interface{}) { + if len(templParams) > 0 { + for _, v := range templParams { + genericParams = append(genericParams, interface{}(v)) + } + return + } + for _, v := range JSONParams { + genericParams = append(genericParams, interface{}(v)) + } + return +} + +// generate the accurate header based on template given +func (p *podPsTemplateParams) podHeaderMap() map[string]string { + v := reflect.Indirect(reflect.ValueOf(p)) + values := make(map[string]string) + + for i := 0; i < v.NumField(); i++ { + key := v.Type().Field(i).Name + value := key + if value == "ID" { + value = "Pod" + value + } + values[key] = strings.ToUpper(splitCamelCase(value)) + } + return values +} + +// getPodTemplateOutput returns the modified container information +func getPodTemplateOutput(psParams []podPsJSONParams, opts podPsOptions) ([]podPsTemplateParams, error) { + var ( + psOutput []podPsTemplateParams + ) + + for _, psParam := range psParams { + podID := psParam.ID + + if !opts.NoTrunc { + podID = shortID(psParam.ID) + } + params := podPsTemplateParams{ + ID: podID, + Name: psParam.Name, + } + + psOutput = append(psOutput, params) + } + + return psOutput, nil +} + +// getAndSortPodJSONOutput returns the container info in its raw, sorted form +func getAndSortPodJSONParams(pods []*libpod.Pod, opts podPsOptions, runtime *libpod.Runtime) ([]podPsJSONParams, error) { + var ( + psOutput []podPsJSONParams + ) + + for _, pod := range pods { + ctrs, err := runtime.ContainersInPod(pod) + if err != nil { + return nil, err + } + ctrNum := len(ctrs) + + params := podPsJSONParams{ + ID: pod.ID(), + Name: pod.Name(), + NumberOfContainers: ctrNum, + } + + psOutput = append(psOutput, params) + } + return psOutput, nil +} + +func generatePodPsOutput(pods []*libpod.Pod, opts podPsOptions, runtime *libpod.Runtime) error { + if len(pods) == 0 && opts.Format != formats.JSONString { + return nil + } + psOutput, err := getAndSortPodJSONParams(pods, opts, runtime) + if err != nil { + return err + } + var out formats.Writer + + switch opts.Format { + case formats.JSONString: + if err != nil { + return errors.Wrapf(err, "unable to create JSON for output") + } + out = formats.JSONStructArray{Output: podPsToGeneric([]podPsTemplateParams{}, psOutput)} + default: + psOutput, err := getPodTemplateOutput(psOutput, opts) + if err != nil { + return errors.Wrapf(err, "unable to create output") + } + out = formats.StdoutTemplateArray{Output: podPsToGeneric(psOutput, []podPsJSONParams{}), Template: opts.Format, Fields: psOutput[0].podHeaderMap()} + } + + return formats.Writer(out).Out() +} |