Browse code

Send "Name" and "ID" when stating stopped containers

When `docker stats` stopped containers, client will get empty stats data,
this commit will gurantee client always get "Name" and "ID" field, so
that it can format with `ID` and `Name` fields successfully.

Signed-off-by: Zhang Wei <zhangwei555@huawei.com>

Zhang Wei authored on 2016/12/26 18:43:18
Showing 3 changed files
... ...
@@ -33,7 +33,9 @@ func (daemon *Daemon) ContainerStats(ctx context.Context, prefixOrName string, c
33 33
 
34 34
 	// If the container is either not running or restarting and requires no stream, return an empty stats.
35 35
 	if (!container.IsRunning() || container.IsRestarting()) && !config.Stream {
36
-		return json.NewEncoder(config.OutStream).Encode(&types.Stats{})
36
+		return json.NewEncoder(config.OutStream).Encode(&types.StatsJSON{
37
+			Name: container.Name,
38
+			ID:   container.ID})
37 39
 	}
38 40
 
39 41
 	outStream := config.OutStream
... ...
@@ -6,6 +6,7 @@ import (
6 6
 	"time"
7 7
 
8 8
 	"github.com/Sirupsen/logrus"
9
+	"github.com/docker/docker/api/types"
9 10
 	"github.com/docker/docker/container"
10 11
 	"github.com/docker/docker/pkg/pubsub"
11 12
 )
... ...
@@ -84,7 +85,14 @@ func (s *Collector) Run() {
84 84
 			if err != nil {
85 85
 				if _, ok := err.(notRunningErr); !ok {
86 86
 					logrus.Errorf("collecting stats for %s: %v", pair.container.ID, err)
87
+					continue
87 88
 				}
89
+
90
+				// publish empty stats containing only name and ID if not running
91
+				pair.publisher.Publish(types.StatsJSON{
92
+					Name: pair.container.Name,
93
+					ID:   pair.container.ID,
94
+				})
88 95
 				continue
89 96
 			}
90 97
 			// FIXME: move to containerd on Linux (not Windows)
... ...
@@ -157,3 +157,22 @@ func (s *DockerSuite) TestStatsAllNewContainersAdded(c *check.C) {
157 157
 		// ignore, done
158 158
 	}
159 159
 }
160
+
161
+func (s *DockerSuite) TestStatsFormatAll(c *check.C) {
162
+	// Windows does not support stats
163
+	testRequires(c, DaemonIsLinux)
164
+
165
+	dockerCmd(c, "run", "-d", "--name=RunningOne", "busybox", "top")
166
+	c.Assert(waitRun("RunningOne"), check.IsNil)
167
+	dockerCmd(c, "run", "-d", "--name=ExitedOne", "busybox", "top")
168
+	dockerCmd(c, "stop", "ExitedOne")
169
+	c.Assert(waitExited("ExitedOne", 5*time.Second), check.IsNil)
170
+
171
+	out, _ := dockerCmd(c, "stats", "--no-stream", "--format", "{{.Name}}")
172
+	c.Assert(out, checker.Contains, "RunningOne")
173
+	c.Assert(out, checker.Not(checker.Contains), "ExitedOne")
174
+
175
+	out, _ = dockerCmd(c, "stats", "--all", "--no-stream", "--format", "{{.Name}}")
176
+	c.Assert(out, checker.Contains, "RunningOne")
177
+	c.Assert(out, checker.Contains, "ExitedOne")
178
+}