docker ps: add State field to formatting

The State field allows printing the container state without
additional information about uptime, healthcheck, etc.

With this patch, the container's state can be printed independently:

```bash
docker ps -a --format '{{.State}}'
running
paused
exited
created
```

```bash
docker ps -a --format 'table {{.Names}}\t{{.State}}\t{{.Status}}'
NAMES                     STATE               STATUS
elastic_burnell           running             Up About a minute
pausie                    paused              Up 5 minutes (Paused)
peaceful_stonebraker      exited              Exited (0) 10 hours ago
vigilant_shaw             created             Created
```

```bash
docker ps -a --format 'raw'

container_id: 0445f73f3a71
image: docker-cli-dev
command: "ash"
created_at: 2019-07-12 11:16:11 +0000 UTC
state: running
status: Up 2 minutes
names: elastic_burnell
labels:
ports:

container_id: 1aff69a3912c
image: nginx:alpine
command: "nginx -g 'daemon of ..."
created_at: 2019-07-12 11:12:10 +0000 UTC
state: paused
status: Up 6 minutes (Paused)
names: pausie
labels: maintainer=NGINX Docker Maintainers <docker-maint@nginx.com>
ports: 80/tcp

container_id: d48acf66c318
image: alpine:3.9.3
command: "id -u"
created_at: 2019-07-12 00:52:17 +0000 UTC
state: exited
status: Exited (0) 10 hours ago
names: peaceful_stonebraker
labels:
ports:

container_id: a0733fe0dace
image: b7b28af77ffe
command: "/bin/sh -c '#(nop) ..."
created_at: 2019-07-12 00:51:29 +0000 UTC
state: created
status: Created
names: vigilant_shaw
labels:
ports:
```

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn 2019-07-12 13:10:08 +02:00
parent 6fc0dc9176
commit 1fdbd6181e
No known key found for this signature in database
GPG Key ID: 76698F39D527CE8C
4 changed files with 23 additions and 5 deletions

View File

@ -44,6 +44,7 @@ func NewContainerFormat(source string, quiet bool, size bool) Format {
image: {{.Image}} image: {{.Image}}
command: {{.Command}} command: {{.Command}}
created_at: {{.CreatedAt}} created_at: {{.CreatedAt}}
state: {{- pad .State 1 0}}
status: {{- pad .Status 1 0}} status: {{- pad .Status 1 0}}
names: {{.Names}} names: {{.Names}}
labels: {{- pad .Labels 1 0}} labels: {{- pad .Labels 1 0}}
@ -87,6 +88,7 @@ func newContainerContext() *containerContext {
"CreatedAt": CreatedAtHeader, "CreatedAt": CreatedAtHeader,
"RunningFor": runningForHeader, "RunningFor": runningForHeader,
"Ports": PortsHeader, "Ports": PortsHeader,
"State": StateHeader,
"Status": StatusHeader, "Status": StatusHeader,
"Size": SizeHeader, "Size": SizeHeader,
"Labels": LabelsHeader, "Labels": LabelsHeader,
@ -169,6 +171,10 @@ func (c *containerContext) Ports() string {
return DisplayablePorts(c.c.Ports) return DisplayablePorts(c.c.Ports)
} }
func (c *containerContext) State() string {
return c.c.State
}
func (c *containerContext) Status() string { func (c *containerContext) Status() string {
return c.c.Status return c.c.Status
} }

View File

@ -168,6 +168,10 @@ containerID2 ubuntu "" 24 hours ago
Context{Format: NewContainerFormat("table", true, false)}, Context{Format: NewContainerFormat("table", true, false)},
"containerID1\ncontainerID2\n", "containerID1\ncontainerID2\n",
}, },
{
Context{Format: NewContainerFormat("table {{.State}}", false, true)},
"STATE\nrunning\nrunning\n",
},
// Raw Format // Raw Format
{ {
Context{Format: NewContainerFormat("raw", false, false)}, Context{Format: NewContainerFormat("raw", false, false)},
@ -175,6 +179,7 @@ containerID2 ubuntu "" 24 hours ago
image: ubuntu image: ubuntu
command: "" command: ""
created_at: %s created_at: %s
state: running
status: status:
names: foobar_baz names: foobar_baz
labels: labels:
@ -184,6 +189,7 @@ container_id: containerID2
image: ubuntu image: ubuntu
command: "" command: ""
created_at: %s created_at: %s
state: running
status: status:
names: foobar_bar names: foobar_bar
labels: labels:
@ -197,6 +203,7 @@ ports:
image: ubuntu image: ubuntu
command: "" command: ""
created_at: %s created_at: %s
state: running
status: status:
names: foobar_baz names: foobar_baz
labels: labels:
@ -207,6 +214,7 @@ container_id: containerID2
image: ubuntu image: ubuntu
command: "" command: ""
created_at: %s created_at: %s
state: running
status: status:
names: foobar_bar names: foobar_bar
labels: labels:
@ -237,8 +245,8 @@ size: 0B
for _, testcase := range cases { for _, testcase := range cases {
containers := []types.Container{ containers := []types.Container{
{ID: "containerID1", Names: []string{"/foobar_baz"}, Image: "ubuntu", Created: unixTime}, {ID: "containerID1", Names: []string{"/foobar_baz"}, Image: "ubuntu", Created: unixTime, State: "running"},
{ID: "containerID2", Names: []string{"/foobar_bar"}, Image: "ubuntu", Created: unixTime}, {ID: "containerID2", Names: []string{"/foobar_bar"}, Image: "ubuntu", Created: unixTime, State: "running"},
} }
out := bytes.NewBufferString("") out := bytes.NewBufferString("")
testcase.context.Output = out testcase.context.Output = out
@ -314,8 +322,8 @@ func TestContainerContextWriteWithNoContainers(t *testing.T) {
func TestContainerContextWriteJSON(t *testing.T) { func TestContainerContextWriteJSON(t *testing.T) {
unix := time.Now().Add(-65 * time.Second).Unix() unix := time.Now().Add(-65 * time.Second).Unix()
containers := []types.Container{ containers := []types.Container{
{ID: "containerID1", Names: []string{"/foobar_baz"}, Image: "ubuntu", Created: unix}, {ID: "containerID1", Names: []string{"/foobar_baz"}, Image: "ubuntu", Created: unix, State: "running"},
{ID: "containerID2", Names: []string{"/foobar_bar"}, Image: "ubuntu", Created: unix}, {ID: "containerID2", Names: []string{"/foobar_bar"}, Image: "ubuntu", Created: unix, State: "running"},
} }
expectedCreated := time.Unix(unix, 0).String() expectedCreated := time.Unix(unix, 0).String()
expectedJSONs := []map[string]interface{}{ expectedJSONs := []map[string]interface{}{
@ -332,6 +340,7 @@ func TestContainerContextWriteJSON(t *testing.T) {
"Ports": "", "Ports": "",
"RunningFor": "About a minute ago", "RunningFor": "About a minute ago",
"Size": "0B", "Size": "0B",
"State": "running",
"Status": "", "Status": "",
}, },
{ {
@ -347,6 +356,7 @@ func TestContainerContextWriteJSON(t *testing.T) {
"Ports": "", "Ports": "",
"RunningFor": "About a minute ago", "RunningFor": "About a minute ago",
"Size": "0B", "Size": "0B",
"State": "running",
"Status": "", "Status": "",
}, },
} }

View File

@ -12,6 +12,7 @@ const (
DescriptionHeader = "DESCRIPTION" DescriptionHeader = "DESCRIPTION"
DriverHeader = "DRIVER" DriverHeader = "DRIVER"
ScopeHeader = "SCOPE" ScopeHeader = "SCOPE"
StateHeader = "STATE"
StatusHeader = "STATUS" StatusHeader = "STATUS"
PortsHeader = "PORTS" PortsHeader = "PORTS"
ImageHeader = "IMAGE" ImageHeader = "IMAGE"

View File

@ -397,7 +397,8 @@ Valid placeholders for the Go template are listed below:
| `.CreatedAt` | Time when the container was created. | | `.CreatedAt` | Time when the container was created. |
| `.RunningFor` | Elapsed time since the container was started. | | `.RunningFor` | Elapsed time since the container was started. |
| `.Ports` | Exposed ports. | | `.Ports` | Exposed ports. |
| `.Status` | Container status. | | `.State` | Container status (for example; "created", "running", "exited"). |
| `.Status` | Container status with details about duration and health-status. |
| `.Size` | Container disk size. | | `.Size` | Container disk size. |
| `.Names` | Container names. | | `.Names` | Container names. |
| `.Labels` | All labels assigned to the container. | | `.Labels` | All labels assigned to the container. |