diff --git a/probe/docker/registry.go b/probe/docker/registry.go index 37b750f28..8014a87ab 100644 --- a/probe/docker/registry.go +++ b/probe/docker/registry.go @@ -1,6 +1,8 @@ package docker import ( + "fmt" + "strings" "sync" "time" @@ -401,3 +403,14 @@ func (r *registry) WalkImages(f func(*docker_client.APIImages)) { return false }) } + +// ImageNameWithoutVersion splits the image name apart, returning the name +// without the version, if possible +func ImageNameWithoutVersion(name string) string { + parts := strings.SplitN(name, "/", 3) + if len(parts) == 3 { + name = fmt.Sprintf("%s/%s", parts[1], parts[2]) + } + parts = strings.SplitN(name, ":", 2) + return parts[0] +} diff --git a/probe/docker/registry_test.go b/probe/docker/registry_test.go index c1b494fb4..44471f8d8 100644 --- a/probe/docker/registry_test.go +++ b/probe/docker/registry_test.go @@ -451,3 +451,18 @@ func TestRegistryDelete(t *testing.T) { } }) } + +func TestDockerImageName(t *testing.T) { + for _, input := range []struct{ in, name string }{ + {"foo/bar", "foo/bar"}, + {"foo/bar:baz", "foo/bar"}, + {"reg:123/foo/bar:baz", "foo/bar"}, + {"docker-registry.domain.name:5000/repo/image1:ver", "repo/image1"}, + {"foo", "foo"}, + } { + name := docker.ImageNameWithoutVersion(input.in) + if name != input.name { + t.Fatalf("%s: %s != %s", input.in, name, input.name) + } + } +} diff --git a/probe/kubernetes/reporter.go b/probe/kubernetes/reporter.go index 624baac9d..fcf7ea9fa 100644 --- a/probe/kubernetes/reporter.go +++ b/probe/kubernetes/reporter.go @@ -8,6 +8,7 @@ import ( "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/labels" + "github.com/weaveworks/scope/common/mtime" "github.com/weaveworks/scope/probe" "github.com/weaveworks/scope/probe/controls" "github.com/weaveworks/scope/probe/docker" @@ -90,6 +91,27 @@ func (r *Reporter) podEvent(e Event, pod Pod) { } } +func isPauseContainer(n report.Node, rpt report.Report) bool { + containerImageIDs, ok := n.Sets.Lookup(report.ContainerImage) + if !ok { + return false + } + for _, imageNodeID := range containerImageIDs { + imageNode, ok := rpt.ContainerImage.Nodes[imageNodeID] + if !ok { + continue + } + imageName, ok := imageNode.Latest.Lookup(docker.ImageName) + if !ok { + continue + } + if docker.ImageNameWithoutVersion(imageName) == "google_containers/pause" { + return true + } + } + return false +} + // Tag adds pod parents to container nodes. func (r *Reporter) Tag(rpt report.Report) (report.Report, error) { for id, n := range rpt.Container.Nodes { @@ -97,6 +119,12 @@ func (r *Reporter) Tag(rpt report.Report) (report.Report, error) { if !ok { continue } + + // Tag the pause containers with "does-not-make-connections" + if isPauseContainer(n, rpt) { + n = n.WithLatest(report.DoesNotMakeConnections, mtime.Now(), "") + } + rpt.Container.Nodes[id] = n.WithParents(report.EmptySets.Add( report.Pod, report.EmptyStringSet.Add(report.MakePodNodeID(uid)), diff --git a/render/container.go b/render/container.go index c16a4611e..e337b615d 100644 --- a/render/container.go +++ b/render/container.go @@ -1,7 +1,6 @@ package render import ( - "fmt" "net" "regexp" "strings" @@ -173,6 +172,12 @@ func MapContainer2IP(m report.Node, _ report.Networks) report.Nodes { return report.Nodes{} } + // if this container doesn't make connections, we can ignore it + _, doesntMakeConnections := m.Latest.Lookup(report.DoesNotMakeConnections) + if doesntMakeConnections { + return report.Nodes{} + } + result := report.Nodes{} if addrs, ok := m.Sets.Lookup(docker.ContainerIPsWithScopes); ok { for _, addr := range addrs { @@ -326,17 +331,6 @@ func MapContainer2Hostname(n report.Node, _ report.Networks) report.Nodes { return report.Nodes{id: node} } -// ImageNameWithoutVersion splits the image name apart, returning the name -// without the version, if possible -func ImageNameWithoutVersion(name string) string { - parts := strings.SplitN(name, "/", 3) - if len(parts) == 3 { - name = fmt.Sprintf("%s/%s", parts[1], parts[2]) - } - parts = strings.SplitN(name, ":", 2) - return parts[0] -} - // MapToEmpty removes all the attributes, children, etc, of a node. Useful when // we just want to count the presence of nodes. func MapToEmpty(n report.Node, _ report.Networks) report.Nodes { diff --git a/render/container_internal_test.go b/render/container_internal_test.go deleted file mode 100644 index c04e2778d..000000000 --- a/render/container_internal_test.go +++ /dev/null @@ -1,20 +0,0 @@ -package render - -import ( - "testing" -) - -func TestDockerImageName(t *testing.T) { - for _, input := range []struct{ in, name string }{ - {"foo/bar", "foo/bar"}, - {"foo/bar:baz", "foo/bar"}, - {"reg:123/foo/bar:baz", "foo/bar"}, - {"docker-registry.domain.name:5000/repo/image1:ver", "repo/image1"}, - {"foo", "foo"}, - } { - name := ImageNameWithoutVersion(input.in) - if name != input.name { - t.Fatalf("%s: %s != %s", input.in, name, input.name) - } - } -} diff --git a/render/detailed/parents.go b/render/detailed/parents.go index e24aaf938..d813acce3 100644 --- a/render/detailed/parents.go +++ b/render/detailed/parents.go @@ -6,7 +6,6 @@ import ( "github.com/weaveworks/scope/probe/docker" "github.com/weaveworks/scope/probe/host" "github.com/weaveworks/scope/probe/kubernetes" - "github.com/weaveworks/scope/render" "github.com/weaveworks/scope/report" ) @@ -85,7 +84,7 @@ func containerImageParent(n report.Node) Parent { imageName, _ := n.Latest.Lookup(docker.ImageName) return Parent{ ID: n.ID, - Label: render.ImageNameWithoutVersion(imageName), + Label: docker.ImageNameWithoutVersion(imageName), TopologyID: "containers-by-image", } } diff --git a/render/detailed/summary.go b/render/detailed/summary.go index 7779cc1e2..c00962de2 100644 --- a/render/detailed/summary.go +++ b/render/detailed/summary.go @@ -203,7 +203,7 @@ func containerNodeSummary(base NodeSummary, n report.Node) (NodeSummary, bool) { base.LabelMinor = report.ExtractHostID(n) if imageName, ok := n.Latest.Lookup(docker.ImageName); ok { - base.Rank = render.ImageNameWithoutVersion(imageName) + base.Rank = docker.ImageNameWithoutVersion(imageName) } return base, true @@ -215,7 +215,7 @@ func containerImageNodeSummary(base NodeSummary, n report.Node) (NodeSummary, bo return NodeSummary{}, false } - imageNameWithoutVersion := render.ImageNameWithoutVersion(imageName) + imageNameWithoutVersion := docker.ImageNameWithoutVersion(imageName) base.Label = imageNameWithoutVersion base.Rank = imageNameWithoutVersion base.Stack = true diff --git a/report/id.go b/report/id.go index 899ff427c..9152286dd 100644 --- a/report/id.go +++ b/report/id.go @@ -24,6 +24,9 @@ const ( // EdgeDelim separates two node IDs when they need to exist in the same key. // Concretely, it separates node IDs in keys that represent edges. EdgeDelim = "|" + + // Key added to nodes to prevent them being joined with conntracked connections + DoesNotMakeConnections = "does_not_make_connections" ) var (