mirror of
https://github.com/weaveworks/scope.git
synced 2026-07-28 01:31:17 +00:00
refactor: change process-to-container from a Map to a Renderer
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user