Merge pull request #106 from weaveworks/add-containers-topology

Add Containers topology
This commit is contained in:
Peter Bourgon
2015-05-26 17:11:01 +02:00
6 changed files with 67 additions and 3 deletions

View File

@@ -15,7 +15,7 @@ func TestAPITopology(t *testing.T) {
if err := json.Unmarshal(body, &topos); err != nil {
t.Fatalf("JSON parse error: %s", err)
}
equals(t, 2, len(topos))
equals(t, 3, len(topos))
for _, topo := range topos {
is200(t, ts, topo.URL)
if topo.GroupedURL != "" {

View File

@@ -47,5 +47,6 @@ var topologyRegistry = map[string]struct {
hasGrouped bool
}{
"applications": {"Applications", selectProcess, report.ProcessPID, true},
"containers": {"Containers", selectProcess, report.ProcessContainer, true},
"hosts": {"Hosts", selectNetwork, report.NetworkHostname, false},
}

View File

@@ -69,7 +69,6 @@ func checkRequest(t *testing.T, ts *httptest.Server, method, path string, body [
// getRawJSON GETs a file, checks it is JSON, and returns the non-parsed body
func getRawJSON(t *testing.T, ts *httptest.Server, path string) []byte {
res, body := checkGet(t, ts, path)
if res.StatusCode != 200 {

View File

@@ -3,6 +3,7 @@ package main
import (
"fmt"
"log"
"strings"
"sync"
"time"
@@ -135,7 +136,7 @@ func (m *dockerMapper) idMapper() processMapper {
func (m *dockerMapper) nameMapper() processMapper {
return &dockerProcessMapper{m, "docker_name", func(c *docker.Container) string {
return c.Name
return strings.TrimPrefix(c.Name, "/")
}}
}

View File

@@ -48,6 +48,37 @@ func ProcessPID(_ string, m NodeMetadata, grouped bool) (MappedNode, bool) {
}, show
}
// ProcessContainer maps Process topology nodes to the containers they run in.
// We consider container and image IDs to be globally unique, and so don't
// scope them further by e.g. host. If no container metadata is found, nodes
// are grouped into the Uncontained node. If grouped is true, nodes with the
// same container image ID are merged together.
func ProcessContainer(_ string, m NodeMetadata, grouped bool) (MappedNode, bool) {
var (
containerID = m["docker_id"]
containerName = m["docker_name"]
imageID = m["docker_image_id"]
imageName = m["docker_image_name"]
domain = m["domain"]
)
var id, major, minor, rank string
if containerID == "" {
id, major, minor, rank = "uncontained", "Uncontained", "", "uncontained"
} else if grouped {
id, major, minor, rank = imageID, imageName, "", imageID
} else {
id, major, minor, rank = containerID, containerName, domain, imageID
}
return MappedNode{
ID: id,
Major: major,
Minor: minor,
Rank: rank,
}, true
}
// NetworkHostname takes a node NodeMetadata from a Network topology, and
// returns a representation based on the hostname. Major label is the
// hostname, the minor label is the domain, if any.

View File

@@ -51,6 +51,38 @@ func TestUngroupedMapping(t *testing.T) {
wantMinor: "hosta (42)",
wantRank: "42",
},
{
f: ProcessContainer,
id: "foo-id",
meta: NodeMetadata{
"pid": "42",
"name": "curl",
"domain": "hosta",
},
wantOK: true,
wantID: "uncontained",
wantMajor: "Uncontained",
wantMinor: "",
wantRank: "uncontained",
},
{
f: ProcessContainer,
id: "bar-id",
meta: NodeMetadata{
"pid": "42",
"name": "curl",
"domain": "hosta",
"docker_id": "d321fe0",
"docker_name": "walking_sparrow",
"docker_image_id": "1101fff",
"docker_image_name": "org/app:latest",
},
wantOK: true,
wantID: "d321fe0",
wantMajor: "walking_sparrow",
wantMinor: "hosta",
wantRank: "1101fff",
},
} {
identity := fmt.Sprintf("(%d %s %v)", i, c.id, c.meta)