From 0fc7917561e9ca7273d14064151225f3f95e2103 Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Fri, 25 Oct 2019 08:14:04 +0000 Subject: [PATCH] refactor: change process-to-container from a Map to a Renderer --- render/container.go | 62 +++++++++++++++++----------------------- render/container_test.go | 31 +++++++++----------- 2 files changed, 41 insertions(+), 52 deletions(-) diff --git a/render/container.go b/render/container.go index 2d95fd21c..8ec46f1fe 100644 --- a/render/container.go +++ b/render/container.go @@ -32,14 +32,13 @@ var ContainerRenderer = Memoise(MakeFilter( return !ok || state != report.StateDeleted }, MakeReduce( - MakeMap( - MapProcess2Container, - ProcessRenderer, - ), + process2ContainerRenderer{}, ConnectionJoin(MapContainer2IP, report.Container), ), )) +var Process2ContainerRenderer = process2ContainerRenderer{} // just for testing + const originalNodeID = "original_node_id" // ConnectionJoin joins the given topology with connections from the @@ -241,39 +240,32 @@ func MapContainer2IP(m report.Node) []string { return result } -// MapProcess2Container 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 -// 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 - } +type process2ContainerRenderer struct{} - // 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) +func (m process2ContainerRenderer) 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 containerID, ok := n.Latest.Lookup(report.DockerContainerID); !ok { + // If the process is not in a container, group it into a per-host "Uncontained" node. + hostID, _, _ := report.ParseProcessNodeID(n.ID) + id := MakePseudoNodeID(UncontainedID, hostID) + ret.addChildAndChildren(n, id, Pseudo) + } else { + // Otherwise, this function will produce a node 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. + id := report.MakeContainerNodeID(containerID) + ret.addChildAndChildren(n, id, report.Container) + } } - return node + return ret.result(processes.Nodes) } // MapContainer2ContainerImage maps container Nodes to container diff --git a/render/container_test.go b/render/container_test.go index 5bb3d1171..62c701658 100644 --- a/render/container_test.go +++ b/render/container_test.go @@ -26,28 +26,25 @@ var ( ) func TestMapProcess2Container(t *testing.T) { - for _, input := range []testcase{ + for _, input := range []struct { + name string + n report.Node + ok bool + }{ {"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) + rpt := report.MakeReport() + rpt.Process.AddNode(input.n) + p := render.Process2ContainerRenderer + if have := p.Render(context.Background(), rpt); input.ok != (len(have.Nodes) != 0) { + name := input.name + if name == "" { + name = fmt.Sprintf("%v", input.n) + } + t.Errorf("%s: want %v, have %v", name, input.ok, have) } - t.Errorf("%s: want %v, have %v", name, input.ok, have) } }