ps --format: Add config.js doc, fix gofmt, add integration tests

Re-add the docs from @calavera's PR to the moved cli cmd reference docs.
Fix gofmt and vet issues from carried commits
Add integration test for using format with --no-trunc and multi-names
Fix custom_test map order dependency on expected value check
Add docs to reference/commandline/ps.md
Remove "-F" flag option from original carried PR content

Docker-DCO-1.1-Signed-off-by: Phil Estes <estesp@linux.vnet.ibm.com> (github: estesp)
This commit is contained in:
Phil Estes 2015-07-17 00:03:16 -04:00
parent 37209190c7
commit 542b58d8f7
7 changed files with 111 additions and 14 deletions

View File

@ -31,7 +31,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")
format = cmd.String([]string{"F", "-format"}, "", "Pretty-print containers using a Go template")
format = cmd.String([]string{"-format"}, "", "Pretty-print containers using a Go template")
flFilter = opts.NewListOpts(nil)
)
cmd.Require(flag.Exact, 0)

View File

@ -1,6 +1,8 @@
package ps
import (
"reflect"
"strings"
"testing"
"time"
@ -26,7 +28,7 @@ func TestContainerContextID(t *testing.T) {
{types.Container{Image: ""}, true, "<no image>", imageHeader, ctx.Image},
{types.Container{Command: "sh -c 'ls -la'"}, true, `"sh -c 'ls -la'"`, commandHeader, ctx.Command},
{types.Container{Created: int(unix)}, true, time.Unix(unix, 0).String(), createdAtHeader, ctx.CreatedAt},
{types.Container{Ports: []types.Port{types.Port{PrivatePort: 8080, PublicPort: 8080, Type: "tcp"}}}, true, "8080/tcp", portsHeader, ctx.Ports},
{types.Container{Ports: []types.Port{{PrivatePort: 8080, PublicPort: 8080, Type: "tcp"}}}, true, "8080/tcp", portsHeader, ctx.Ports},
{types.Container{Status: "RUNNING"}, true, "RUNNING", statusHeader, ctx.Status},
{types.Container{SizeRw: 10}, true, "10 B", sizeHeader, ctx.Size},
{types.Container{SizeRw: 10, SizeRootFs: 20}, true, "10 B (virtual 20 B)", sizeHeader, ctx.Size},
@ -36,7 +38,26 @@ func TestContainerContextID(t *testing.T) {
for _, c := range cases {
ctx = containerContext{c: c.container, trunc: c.trunc}
v := c.call()
if v != c.expValue {
if strings.Contains(v, ",") {
// comma-separated values means probably a map input, which won't
// be guaranteed to have the same order as our expected value
// We'll create maps and use reflect.DeepEquals to check instead:
entriesMap := make(map[string]string)
expMap := make(map[string]string)
entries := strings.Split(v, ",")
expectedEntries := strings.Split(c.expValue, ",")
for _, entry := range entries {
keyval := strings.Split(entry, "=")
entriesMap[keyval[0]] = keyval[1]
}
for _, expected := range expectedEntries {
keyval := strings.Split(expected, "=")
expMap[keyval[0]] = keyval[1]
}
if !reflect.DeepEqual(expMap, entriesMap) {
t.Fatalf("Expected entries: %v, got: %v", c.expValue, v)
}
} else if v != c.expValue {
t.Fatalf("Expected %s, was %s\n", c.expValue, v)
}
@ -52,17 +73,16 @@ func TestContainerContextID(t *testing.T) {
sid := ctx.Label("com.docker.swarm.swarm-id")
node := ctx.Label("com.docker.swarm.node_name")
if sid != "33" {
t.Fatal("Expected 33, was %s\n", sid)
t.Fatalf("Expected 33, was %s\n", sid)
}
if node != "ubuntu" {
t.Fatal("Expected ubuntu, was %s\n", node)
t.Fatalf("Expected ubuntu, was %s\n", node)
}
h := ctx.fullHeader()
if h != "SWARM ID\tNODE NAME" {
t.Fatal("Expected %s, was %s\n", "SWARM ID\tNODE NAME", h)
t.Fatalf("Expected %s, was %s\n", "SWARM ID\tNODE NAME", h)
}
}

View File

@ -158,7 +158,7 @@ func TestNewJson(t *testing.T) {
func TestJsonWithPsFormat(t *testing.T) {
tmpHome, _ := ioutil.TempDir("", "config-test")
fn := filepath.Join(tmpHome, CONFIGFILE)
fn := filepath.Join(tmpHome, ConfigFileName)
js := `{
"auths": { "https://index.docker.io/v1/": { "auth": "am9lam9lOmhlbGxv", "email": "user@example.com" } },
"psFormat": "table {{.ID}}\\t{{.Label \"com.docker.label.cpu\"}}"
@ -180,7 +180,7 @@ func TestJsonWithPsFormat(t *testing.T) {
t.Fatalf("Failed to save: %q", err)
}
buf, err := ioutil.ReadFile(filepath.Join(tmpHome, CONFIGFILE))
buf, err := ioutil.ReadFile(filepath.Join(tmpHome, ConfigFileName))
if !strings.Contains(string(buf), `"psFormat":`) ||
!strings.Contains(string(buf), "{{.ID}}") {
t.Fatalf("Should have save in new form: %s", string(buf))

View File

@ -85,18 +85,26 @@ mechanisms, you must keep in mind the order of precedence among them. Command
line options override environment variables and environment variables override
properties you specify in a `config.json` file.
The `config.json` file stores a JSON encoding of a single `HttpHeaders`
property. The property specifies a set of headers to include in all messages
The `config.json` file stores a JSON encoding of several properties:
The property `HttpHeaders` specifies a set of headers to include in all messages
sent from the Docker client to the daemon. Docker does not try to interpret or
understand these header; it simply puts them into the messages. Docker does
not allow these headers to change any headers it sets for itself.
The property `psFormat` specifies the default format for `docker ps` output.
When the `--format` flag is not provided with the `docker ps` command,
Docker's client uses this property. If this property is not set, the client
falls back to the default table format. For a list of supported formatting
directives, see the [**Formatting** section in the `docker ps` documentation](../ps)
Following is a sample `config.json` file:
{
"HttpHeaders: {
"MyHeader": "MyValue"
}
},
"psFormat": "table {{.ID}}\\t{{.Image}}\\t{{.Command}}\\t{{.Labels}}"
}
## Help

View File

@ -24,6 +24,7 @@ weight=1
-q, --quiet=false Only display numeric IDs
-s, --size=false Display total file sizes
--since="" Show created since Id or Name, include non-running
--format=[] Pretty-print containers using a Go template
Running `docker ps --no-trunc` showing 2 linked containers.
@ -60,5 +61,42 @@ The currently supported filters are:
This shows all the containers that have exited with status of '0'
## Formatting
The formatting option (`--format`) will pretty-print container output using a Go template.
Valid placeholders for the Go template are listed below:
Placeholder | Description
---- | ----
`.ID` | Container ID
`.Image` | Image ID
`.Command` | Quoted command
`.CreatedAt` | Time when the container was created.
`.RunningFor` | Elapsed time since the container was started.
`.Ports` | Exposed ports.
`.Status` | Container status.
`.Size` | Container disk size.
`.Labels` | All labels asigned to the container.
`.Label` | Value of a specific label for this container. For example `{{.Label "com.docker.swarm.cpu"}}`
When using the `--format` option, the `ps` command will either output the data exactly as the template
declares or, when using the `table` directive, will include column headers as well.
The following example uses a template without headers and outputs the `ID` and `Command`
entries separated by a colon for all running containers:
$ docker ps --format "{{.ID}}: {{.Command}}"
a87ecb4f327c: /bin/sh -c #(nop) MA
01946d9d34d8: /bin/sh -c #(nop) MA
c1d3b0166030: /bin/sh -c yum -y up
41d50ecd2f57: /bin/sh -c #(nop) MA
To list all running containers with their labels in a table format you can use:
$ docker ps --format "table {{.ID}}\t{{.Labels}}"
CONTAINER ID LABELS
a87ecb4f327c com.docker.swarm.node=ubuntu,com.docker.swarm.storage=ssd
01946d9d34d8
c1d3b0166030 com.docker.swarm.node=debian,com.docker.swarm.cpu=6
41d50ecd2f57 com.docker.swarm.node=fedora,com.docker.swarm.cpu=3,com.docker.swarm.storage=ssd

View File

@ -508,3 +508,34 @@ func (s *DockerSuite) TestPsListContainersFilterCreated(c *check.C) {
c.Fatalf("Expected id %s, got %s for filter, out: %s", cID, containerOut, out)
}
}
func (s *DockerSuite) TestPsFormatMultiNames(c *check.C) {
//create 2 containers and link them
dockerCmd(c, "run", "--name=child", "-d", "busybox", "top")
dockerCmd(c, "run", "--name=parent", "--link=child:linkedone", "-d", "busybox", "top")
//use the new format capabilities to only list the names and --no-trunc to get all names
out, _ := dockerCmd(c, "ps", "--format", "{{.Names}}", "--no-trunc")
lines := strings.Split(strings.TrimSpace(string(out)), "\n")
expected := []string{"parent", "child,parent/linkedone"}
var names []string
for _, l := range lines {
names = append(names, l)
}
if !reflect.DeepEqual(expected, names) {
c.Fatalf("Expected array with non-truncated names: %v, got: %v", expected, names)
}
//now list without turning off truncation and make sure we only get the non-link names
out, _ = dockerCmd(c, "ps", "--format", "{{.Names}}")
lines = strings.Split(strings.TrimSpace(string(out)), "\n")
expected = []string{"parent", "child"}
var truncNames []string
for _, l := range lines {
truncNames = append(truncNames, l)
}
if !reflect.DeepEqual(expected, truncNames) {
c.Fatalf("Expected array with truncated names: %v, got: %v", expected, truncNames)
}
}

View File

@ -16,7 +16,7 @@ docker-ps - List containers
[**-q**|**--quiet**[=*false*]]
[**-s**|**--size**[=*false*]]
[**--since**[=*SINCE*]]
[**-F**|**--format**=*"TEMPLATE"*]
[**--format**=*"TEMPLATE"*]
# DESCRIPTION
@ -60,7 +60,7 @@ the running containers.
**--since**=""
Show only containers created since Id or Name, include non-running ones.
**-F**, **--format**=*"TEMPLATE"*
**--format**=*"TEMPLATE"*
Pretty-print containers using a Go template.
Valid placeholders:
.ID - Container ID