Change process-to-container from Map to Renderer

This allows us to be more efficient when collating the data.
This commit is contained in:
Bryan Boreham
2020-06-07 11:12:02 +00:00
parent 7163f42170
commit 7c54093bf7
2 changed files with 25 additions and 58 deletions

View File

@@ -32,10 +32,7 @@ var ContainerRenderer = Memoise(MakeFilter(
return !ok || state != report.StateDeleted
},
MakeReduce(
MakeMap(
MapProcess2Container,
ProcessRenderer,
),
process2Container{},
ConnectionJoin(MapContainer2IP, report.Container),
),
))
@@ -219,39 +216,36 @@ func MapContainer2IP(m report.Node) []string {
return result
}
// MapProcess2Container maps process Nodes to container
// Nodes.
// process2Container maps process Nodes to container Nodes.
//
// Pseudo nodes are passed straight through.
//
// If this function is given a node without a docker_container_id, it
// will produce an "Uncontained" pseudo node.
//
// Otherwise, this function will produce a node with the correct ID
// This function will produce nodes with the correct ID
// format for a container, but without any Major or Minor labels.
// It does not have enough info to do that, and the resulting graph
// must be merged with a container graph to get that info.
func MapProcess2Container(n report.Node) report.Node {
// Propagate pseudo nodes
if n.Topology == Pseudo {
return n
}
// Otherwise, if the process is not in a container, group it into
// a per-host "Uncontained" node.
var (
id string
node report.Node
)
if containerID, ok := n.Latest.Lookup(report.DockerContainerID); ok {
id = report.MakeContainerNodeID(containerID)
node = NewDerivedNode(id, n).WithTopology(report.Container)
} else {
hostID, _, _ := report.ParseProcessNodeID(n.ID)
id = MakePseudoNodeID(UncontainedID, hostID)
node = NewDerivedPseudoNode(id, n)
type process2Container struct{}
func (m process2Container) Render(ctx context.Context, rpt report.Report) Nodes {
processes := ProcessRenderer.Render(ctx, rpt)
ret := newJoinResults(nil)
for _, n := range processes.Nodes {
if n.Topology == Pseudo {
ret.passThrough(n)
continue
}
// If the process is not in a container, group it into
// a per-host "Uncontained" node.
if containerID, ok := n.Latest.Lookup(report.DockerContainerID); ok {
id := report.MakeContainerNodeID(containerID)
ret.addChildAndChildren(n, id, report.Container)
} else {
hostID, _, _ := report.ParseProcessNodeID(n.ID)
id := MakePseudoNodeID(UncontainedID, hostID)
ret.addChildAndChildren(n, id, Pseudo)
}
}
return node
return ret.result(processes)
}
// containerImageRenderer produces a graph where each node is a container image

View File

@@ -2,7 +2,6 @@ package render_test
import (
"context"
"fmt"
"testing"
"github.com/weaveworks/common/test"
@@ -25,32 +24,6 @@ var (
})
)
func TestMapProcess2Container(t *testing.T) {
for _, input := range []testcase{
{"empty", report.MakeNode("empty"), true},
{"basic process", report.MakeNodeWith("basic", map[string]string{report.PID: "201", report.DockerContainerID: "a1b2c3"}), true},
{"uncontained", report.MakeNodeWith("uncontained", map[string]string{report.PID: "201", report.HostNodeID: report.MakeHostNodeID("foo")}), true},
} {
testMap(t, render.MapProcess2Container, input)
}
}
type testcase struct {
name string
n report.Node
ok bool
}
func testMap(t *testing.T, f render.MapFunc, input testcase) {
if have := f(input.n); input.ok != (have.ID != "") {
name := input.name
if name == "" {
name = fmt.Sprintf("%v", input.n)
}
t.Errorf("%s: want %v, have %v", name, input.ok, have)
}
}
func TestContainerRenderer(t *testing.T) {
have := utils.Prune(render.ContainerWithImageNameRenderer.Render(context.Background(), fixture.Report).Nodes)
want := utils.Prune(expected.RenderedContainers)