From 7bb9c5397e69866fcb1142cda430b842a710f751 Mon Sep 17 00:00:00 2001 From: Yong Tang Date: Sat, 20 Aug 2016 15:43:15 -0700 Subject: [PATCH] Fix issue in `docker stats` with `NetworkDisabled=true` This fix tries to address the issue in 25000 where `docker stats` will not show network stats with `NetworkDisabled=true`. The `NetworkDisabled=true` could be either invoked through remote API, or through `docker daemon -b none`. The issue was that when `NetworkDisabled=true` either by API or by daemon config, there is no SandboxKey for container so an error will be returned. This fix fixes this issue by skipping obtaining SandboxKey if `NetworkDisabled=true`. Additional test has bee added to cover the changes. This fix fixes 25000. Signed-off-by: Yong Tang --- daemon/stats.go | 6 ++- integration-cli/docker_api_containers_test.go | 52 +++++++++++++++++++ 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/daemon/stats.go b/daemon/stats.go index f76a689775..3eafecc256 100644 --- a/daemon/stats.go +++ b/daemon/stats.go @@ -138,8 +138,10 @@ func (daemon *Daemon) GetContainerStats(container *container.Container) (*types. return nil, err } - if stats.Networks, err = daemon.getNetworkStats(container); err != nil { - return nil, err + if !container.Config.NetworkDisabled { + if stats.Networks, err = daemon.getNetworkStats(container); err != nil { + return nil, err + } } return stats, nil diff --git a/integration-cli/docker_api_containers_test.go b/integration-cli/docker_api_containers_test.go index 8c1afad910..dc37f0f5e6 100644 --- a/integration-cli/docker_api_containers_test.go +++ b/integration-cli/docker_api_containers_test.go @@ -1432,3 +1432,55 @@ func (s *DockerSuite) TestContainerApiDeleteWithEmptyName(c *check.C) { c.Assert(status, checker.Equals, http.StatusBadRequest) c.Assert(string(out), checker.Contains, "No container name or ID supplied") } + +func (s *DockerSuite) TestContainerApiStatsWithNetworkDisabled(c *check.C) { + // Problematic on Windows as Windows does not support stats + testRequires(c, DaemonIsLinux) + + name := "testing-network-disabled" + config := map[string]interface{}{ + "Image": "busybox", + "Cmd": []string{"top"}, + "NetworkDisabled": true, + } + + status, _, err := sockRequest("POST", "/containers/create?name="+name, config) + c.Assert(err, checker.IsNil) + c.Assert(status, checker.Equals, http.StatusCreated) + + status, _, err = sockRequest("POST", "/containers/"+name+"/start", nil) + c.Assert(err, checker.IsNil) + c.Assert(status, checker.Equals, http.StatusNoContent) + + c.Assert(waitRun(name), check.IsNil) + + type b struct { + status int + body []byte + err error + } + bc := make(chan b, 1) + go func() { + status, body, err := sockRequest("GET", "/containers/"+name+"/stats", nil) + bc <- b{status, body, err} + }() + + // allow some time to stream the stats from the container + time.Sleep(4 * time.Second) + dockerCmd(c, "rm", "-f", name) + + // collect the results from the stats stream or timeout and fail + // if the stream was not disconnected. + select { + case <-time.After(2 * time.Second): + c.Fatal("stream was not closed after container was removed") + case sr := <-bc: + c.Assert(sr.err, checker.IsNil) + c.Assert(sr.status, checker.Equals, http.StatusOK) + + // decode only one object from the stream + var s *types.Stats + dec := json.NewDecoder(bytes.NewBuffer(sr.body)) + c.Assert(dec.Decode(&s), checker.IsNil) + } +}