Skip to content

Commit

Permalink
docker ps: add fields for ordering and column selection
Browse files Browse the repository at this point in the history
* api/client/ps.go: Refactor CmdPs to use a fields list of
  characters to determine which columns to print on `docker ps`
  invocation.

This adds an ability for the docker command to print the columns of
output in arbitrary order.

Signed-off-by: Jeff Mickey <j@codemac.net>
  • Loading branch information
codemac committed May 18, 2015
1 parent 6a18412 commit 7998dca
Showing 1 changed file with 89 additions and 39 deletions.
128 changes: 89 additions & 39 deletions api/client/ps.go
Expand Up @@ -38,6 +38,7 @@ func (cli *DockerCli) CmdPs(args ...string) error {
since = cmd.String([]string{"#sinceId", "#-since-id", "-since"}, "", "Show created since Id or Name, include non-running")
before = cmd.String([]string{"#beforeId", "#-before-id", "-before"}, "", "Show only container created before Id or Name")
last = cmd.Int([]string{"n"}, -1, "Show n last created containers, include non-running")
fields = cmd.String([]string{"-fields"}, "cimtspn", "Choose fields to print, and order (c,i,m,t,s,p,n,z)")
flFilter = opts.NewListOpts(nil)
)
cmd.Require(flag.Exact, 0)
Expand Down Expand Up @@ -97,13 +98,35 @@ func (cli *DockerCli) CmdPs(args ...string) error {
}

w := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0)
if *quiet {
*fields = "c"
}

if *size {
*fields = *fields + "z"
}

if !*quiet {
fmt.Fprint(w, "CONTAINER ID\tIMAGE\tCOMMAND\tCREATED\tSTATUS\tPORTS\tNAMES")
headermap := map[rune]string{
'c': "CONTAINER ID",
'i': "IMAGE",
'm': "COMMAND",
's': "STATUS",
't': "CREATED",
'p': "PORTS",
'n': "NAMES",
'z': "SIZE",
}

if *size {
fmt.Fprintln(w, "\tSIZE")
} else {
fmt.Fprint(w, "\n")
headers := make([]string, 0)
for _, v := range *fields {
if title, ok := headermap[v]; ok {
headers = append(headers, title)
}
}

if len(headers) > 0 {
fmt.Fprint(w, strings.Join(headers, "\t")+"\n")
}
}

Expand All @@ -115,56 +138,83 @@ func (cli *DockerCli) CmdPs(args ...string) error {
return ss
}

for _, container := range containers {
ID := container.ID

if !*noTrunc {
ID = stringid.TruncateID(ID)
}

if *quiet {
fmt.Fprintln(w, ID)
type containerMeta struct {
c string
i string
m string
t string
s string
p string
n string
z string
}

continue
outp := make([]containerMeta, 0)
for _, container := range containers {
next := containerMeta{
c: container.ID,
n: "",
m: strconv.Quote(container.Command),
i: container.Image,
t: units.HumanDuration(time.Now().UTC().Sub(time.Unix(container.Created, 0))) + " ago",
s: container.Status,
p: api.DisplayablePorts(container.Ports),
z: fmt.Sprintf("%s", units.HumanSize(float64(container.SizeRw))),
}

var (
names = stripNamePrefix(container.Names)
command = strconv.Quote(container.Command)
)

// handle truncation
outNames := stripNamePrefix(container.Names)
if !*noTrunc {
command = stringutils.Truncate(command, 20)

next.c = stringid.TruncateID(next.c)
next.m = stringutils.Truncate(next.m, 20)
// only display the default name for the container with notrunc is passed
for _, name := range names {
for _, name := range outNames {
if len(strings.Split(name, "/")) == 1 {
names = []string{name}
outNames = []string{name}
break
}
}
}
next.n = strings.Join(outNames, ",")

if next.i == "" {
next.i = "<no image>"
}

image := container.Image
if image == "" {
image = "<no image>"
// handle rootfs sizing
if container.SizeRootFs > 0 {
next.z = next.z + fmt.Sprintf(" (virtual %s)", units.HumanSize(float64(container.SizeRootFs)))
}

fmt.Fprintf(w, "%s\t%s\t%s\t%s ago\t%s\t%s\t%s\t", ID, image, command,
units.HumanDuration(time.Now().UTC().Sub(time.Unix(int64(container.Created), 0))),
container.Status, api.DisplayablePorts(container.Ports), strings.Join(names, ","))
outp = append(outp, next)
}

if *size {
if container.SizeRootFs > 0 {
fmt.Fprintf(w, "%s (virtual %s)\n", units.HumanSize(float64(container.SizeRw)), units.HumanSize(float64(container.SizeRootFs)))
} else {
fmt.Fprintf(w, "%s\n", units.HumanSize(float64(container.SizeRw)))
}
for _, out := range outp {
of := make([]string, 0)
for _, v := range *fields {
switch v {
case 'c':
of = append(of, out.c)
case 'i':
of = append(of, out.i)
case 'm':
of = append(of, out.m)
case 't':
of = append(of, out.t)
case 's':
of = append(of, out.s)
case 'p':
of = append(of, out.p)
case 'n':
of = append(of, out.n)
case 'z':
of = append(of, out.z)

continue
}
}
if len(of) > 0 {
fmt.Fprintf(w, "%s\n", strings.Join(of, "\t"))
}

fmt.Fprint(w, "\n")
}

if !*quiet {
Expand Down

0 comments on commit 7998dca

Please sign in to comment.