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/commands.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 Jan 21, 2015
1 parent 649ad2d commit dcbc92c
Showing 1 changed file with 91 additions and 42 deletions.
133 changes: 91 additions & 42 deletions api/client/commands.go
Expand Up @@ -1567,6 +1567,7 @@ func (cli *DockerCli) CmdPs(args ...string) error {
since = cmd.String([]string{"#sinceId", "#-since-id", "-since"}, "", "Show only containers created since Id or Name, include non-running ones.")
before = cmd.String([]string{"#beforeId", "#-before-id", "-before"}, "", "Show only container created before Id or Name, include non-running ones.")
last = cmd.Int([]string{"n"}, -1, "Show n last created containers, include non-running ones.")
fields = cmd.String([]string{"-fields"}, "cimtspn", "Choose fields to print, and order ((c)ontainerid,(i)mage,m,t,s,p,n,z)")
flFilter = opts.NewListOpts(nil)
)
cmd.Require(flag.Exact, 0)
Expand Down Expand Up @@ -1626,13 +1627,35 @@ func (cli *DockerCli) CmdPs(args ...string) error {
}

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

if *size {

}

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

headers := make([]string, 0)
for _, v := range *fields {
if title, ok := headermap[v]; ok {
headers = append(v)
}
}

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

Expand All @@ -1644,60 +1667,86 @@ func (cli *DockerCli) CmdPs(args ...string) error {
return ss
}

for _, out := range outs.Data {
outID := out.Get("Id")

if !*noTrunc {
outID = utils.TruncateID(outID)
}

if *quiet {
fmt.Fprintln(w, outID)

continue
}

var (
outNames = stripNamePrefix(out.GetList("Names"))
outCommand = strconv.Quote(out.Get("Command"))
ports = engine.NewTable("", 0)
)
type containerMeta struct {
c string
i string
m string
t string
s string
p string
n string
z string
}

outp := make([]containerMeta, 0)
for _, out := range outs.Data {
portTable := engine.NewTable("", 0)
portTable.ReadListFrom([]byte(out.Get("Ports")))

next := containerMeta{
c: out.Get("Id"),
n: "",
m: strconv.Quote(out.Get("Command")),
i: out.Get("Image"),
t: units.HumanDuration(time.Now().UTC().Sub(time.Unix(out.GetInt64("Created"), 0))) + " ago",
s: out.Get("Status"),
p: api.DisplayablePorts(portTable),
z: fmt.Sprintf("%s", units.HumanSize(float64(out.GetInt64("SizeRw")))),
}

// handle truncation
outNames := stripNamePrefix(out.GetList("Names"))
if !*noTrunc {
outCommand = utils.Trunc(outCommand, 20)

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

break
}
}
}
next.n = strings.Join(outNames, ",")

ports.ReadListFrom([]byte(out.Get("Ports")))
if next.i == "" {
next.i = "<no image>"
}

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

fmt.Fprintf(w, "%s\t%s\t%s\t%s ago\t%s\t%s\t%s\t", outID, image, outCommand,
units.HumanDuration(time.Now().UTC().Sub(time.Unix(out.GetInt64("Created"), 0))),
out.Get("Status"), api.DisplayablePorts(ports), strings.Join(outNames, ","))
outp = append(outp, next)
}

if *size {
if out.GetInt("SizeRootFs") > 0 {
fmt.Fprintf(w, "%s (virtual %s)\n", units.HumanSize(float64(out.GetInt64("SizeRw"))), units.HumanSize(float64(out.GetInt64("SizeRootFs"))))
} else {
fmt.Fprintf(w, "%s\n", units.HumanSize(float64(out.GetInt64("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 dcbc92c

Please sign in to comment.