Skip to content

Commit

Permalink
Merge pull request moby#21904 from yongtang/21848-stats-connected-con…
Browse files Browse the repository at this point in the history
…tainers

Docker stats is not working when a container is using another container's network.
  • Loading branch information
LK4D4 committed Apr 12, 2016
2 parents 7b5a684 + faf2b6f commit d648d40
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 1 deletion.
21 changes: 20 additions & 1 deletion daemon/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -1422,8 +1422,27 @@ func (daemon *Daemon) GetContainerStats(container *container.Container) (*types.
return stats, nil
}

// Resolve Network SandboxID in case the container reuse another container's network stack
func (daemon *Daemon) getNetworkSandboxID(c *container.Container) (string, error) {
curr := c
for curr.HostConfig.NetworkMode.IsContainer() {
containerID := curr.HostConfig.NetworkMode.ConnectedContainer()
connected, err := daemon.GetContainer(containerID)
if err != nil {
return "", fmt.Errorf("Could not get container for %s", containerID)
}
curr = connected
}
return curr.NetworkSettings.SandboxID, nil
}

func (daemon *Daemon) getNetworkStats(c *container.Container) (map[string]types.NetworkStats, error) {
sb, err := daemon.netController.SandboxByID(c.NetworkSettings.SandboxID)
sandboxID, err := daemon.getNetworkSandboxID(c)
if err != nil {
return nil, err
}

sb, err := daemon.netController.SandboxByID(sandboxID)
if err != nil {
return nil, err
}
Expand Down
39 changes: 39 additions & 0 deletions integration-cli/docker_api_stats_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -255,3 +255,42 @@ func (s *DockerSuite) TestApiStatsContainerGetMemoryLimit(c *check.C) {
body.Close()
c.Assert(fmt.Sprintf("%d", v.MemoryStats.Limit), checker.Equals, fmt.Sprintf("%d", info.MemTotal))
}

func (s *DockerSuite) TestApiStatsNoStreamConnectedContainers(c *check.C) {
testRequires(c, DaemonIsLinux)

out1, _ := runSleepingContainer(c)
id1 := strings.TrimSpace(out1)
c.Assert(waitRun(id1), checker.IsNil)

out2, _ := runSleepingContainer(c, "--net", "container:"+id1)
id2 := strings.TrimSpace(out2)
c.Assert(waitRun(id2), checker.IsNil)

ch := make(chan error)
go func() {
resp, body, err := sockRequestRaw("GET", fmt.Sprintf("/containers/%s/stats?stream=false", id2), nil, "")
defer body.Close()
if err != nil {
ch <- err
}
if resp.StatusCode != http.StatusOK {
ch <- fmt.Errorf("Invalid StatusCode %v", resp.StatusCode)
}
if resp.Header.Get("Content-Type") != "application/json" {
ch <- fmt.Errorf("Invalid 'Content-Type' %v", resp.Header.Get("Content-Type"))
}
var v *types.Stats
if err := json.NewDecoder(body).Decode(&v); err != nil {
ch <- err
}
ch <- nil
}()

select {
case err := <-ch:
c.Assert(err, checker.IsNil, check.Commentf("Error in stats remote API: %v", err))
case <-time.After(15 * time.Second):
c.Fatalf("Stats did not return after timeout")
}
}

0 comments on commit d648d40

Please sign in to comment.