Review feedback

This commit is contained in:
Tom Wilkie
2015-06-17 17:21:10 +00:00
parent ee9ac591fd
commit 18c544701a
4 changed files with 80 additions and 82 deletions

View File

@@ -36,24 +36,24 @@ type PseudoFunc func(srcNodeID string, srcNode RenderableNode, dstNodeID string)
// MapFunc is anything which can take an arbitrary RenderableNode and
// return another RenderableNode.
//
// As with LeadMapFunc, if the final output parameter is false, the node
// As with LeafMapFunc, if the final output parameter is false, the node
// shall be omitted from the rendered topology.
type MapFunc func(RenderableNode) (RenderableNode, bool)
// MapEndpointIdentity maps a endpoint topology node to endpoint RenderableNode node.
// As it is only ever run on endpoint topology nodes, we can safely assume the
// presences of certain keys.
// MapEndpointIdentity maps a endpoint topology node to endpoint RenderableNode
// node. As it is only ever run on endpoint topology nodes, we can safely
// assume the presence of certain keys.
func MapEndpointIdentity(m report.NodeMetadata) (RenderableNode, bool) {
var (
id = fmt.Sprintf("endpoint:%s:%s:%s", getHostname(m), m["addr"], m["port"])
id = fmt.Sprintf("endpoint:%s:%s:%s", report.ExtractHostID(m), m["addr"], m["port"])
major = fmt.Sprintf("%s:%s", m["addr"], m["port"])
pid, ok = m["pid"]
minor = getHostname(m)
minor = report.ExtractHostID(m)
rank = major
)
if ok {
minor = fmt.Sprintf("%s (%s)", getHostname(m), pid)
minor = fmt.Sprintf("%s (%s)", report.ExtractHostID(m), pid)
}
return NewRenderableNode(id, major, minor, rank, m), true
@@ -61,26 +61,26 @@ func MapEndpointIdentity(m report.NodeMetadata) (RenderableNode, bool) {
// MapProcessIdentity maps a process topology node to process RenderableNode node.
// As it is only ever run on process topology nodes, we can safely assume the
// presences of certain keys.
// presence of certain keys.
func MapProcessIdentity(m report.NodeMetadata) (RenderableNode, bool) {
var (
id = fmt.Sprintf("pid:%s:%s", getHostname(m), m["pid"])
id = fmt.Sprintf("pid:%s:%s", report.ExtractHostID(m), m["pid"])
major = m["comm"]
minor = fmt.Sprintf("%s (%s)", getHostname(m), m["pid"])
minor = fmt.Sprintf("%s (%s)", report.ExtractHostID(m), m["pid"])
rank = m["pid"]
)
return NewRenderableNode(id, major, minor, rank, m), true
}
// MapContainerIdentity maps a container topology node to container
// MapContainerIdentity maps a container topology node to a container
// RenderableNode node. As it is only ever run on container topology
// nodes, we can safely assume the presences of certain keys.
func MapContainerIdentity(m report.NodeMetadata) (RenderableNode, bool) {
var (
id = m["docker_container_id"]
major = m["docker_container_name"]
minor = getHostname(m)
minor = report.ExtractHostID(m)
rank = m["docker_image_id"]
)
@@ -109,7 +109,7 @@ func MapEndpoint2Process(n RenderableNode) (RenderableNode, bool) {
return RenderableNode{}, false
}
id := fmt.Sprintf("pid:%s:%s", getHostname(n.NodeMetadata), pid)
id := fmt.Sprintf("pid:%s:%s", report.ExtractHostID(n.NodeMetadata), pid)
return newDerivedNode(id, n), true
}
@@ -156,11 +156,6 @@ func MapProcess2Name(n RenderableNode) (RenderableNode, bool) {
return node, true
}
func getHostname(m report.NodeMetadata) string {
hostname, _, _ := report.ParseNodeID(m[report.HostNodeID])
return hostname
}
// ProcessContainerImage maps topology nodes to the container images they run
// on. If no container metadata is found, nodes are grouped into the
// Uncontained node.

View File

@@ -6,25 +6,25 @@ import (
"github.com/weaveworks/scope/report"
)
// Renderer is something that can render a report to a set of RenderableNodes
// Renderer is something that can render a report to a set of RenderableNodes.
type Renderer interface {
Render(report.Report) RenderableNodes
AggregateMetadata(rpt report.Report, localID, remoteID string) report.AggregateMetadata
}
// Reduce renderer is a Renderer which merges together the output of several
// other renderers
// other renderers.
type Reduce []Renderer
// Map is a Renderer which produces a set of RendererNodes from the set of
// RendererNodes produces by another Renderer
// Map is a Renderer which produces a set of RenderableNodes from the set of
// RenderableNodes produced by another Renderer.
type Map struct {
MapFunc
Renderer
}
// LeafMap is a Renderer which produces a set of RendererNodes from a report.Topology
// by using a map functions and topology selector.
// LeafMap is a Renderer which produces a set of RenderableNodes from a report.Topology
// by using a map function and topology selector.
type LeafMap struct {
Selector report.TopologySelector
Mapper LeafMapFunc
@@ -36,12 +36,12 @@ type FilterUnconnected struct {
Renderer
}
// MakeReduce is the only sane way to produce a Reduce Renderer
// MakeReduce is the only sane way to produce a Reduce Renderer.
func MakeReduce(renderers ...Renderer) Renderer {
return Reduce(renderers)
}
// Render produces a set of RenderableNodes given a Report
// Render produces a set of RenderableNodes given a Report.
func (r Reduce) Render(rpt report.Report) RenderableNodes {
result := RenderableNodes{}
for _, renderer := range r {
@@ -50,7 +50,7 @@ func (r Reduce) Render(rpt report.Report) RenderableNodes {
return result
}
// AggregateMetadata produces an AggregateMetadata for a given edge
// AggregateMetadata produces an AggregateMetadata for a given edge.
func (r Reduce) AggregateMetadata(rpt report.Report, localID, remoteID string) report.AggregateMetadata {
metadata := report.AggregateMetadata{}
for _, renderer := range r {
@@ -59,7 +59,7 @@ func (r Reduce) AggregateMetadata(rpt report.Report, localID, remoteID string) r
return metadata
}
// Render transforms a set of RendererNodes produces by another Renderer
// Render transforms a set of RenderableNodes produces by another Renderer.
// using a map function
func (m Map) Render(rpt report.Report) RenderableNodes {
output, _ := m.render(rpt)
@@ -89,14 +89,13 @@ func (m Map) render(rpt report.Report) (RenderableNodes, map[string]string) {
}
// Rewrite Adjacency for new node IDs.
// NB we don't do pseudo nodes here; we assumer the input graph
// we properly-connected, and if the map func dropped a node,
// NB we don't do pseudo nodes here; we assume the input graph
// is properly-connected, and if the map func dropped a node,
// we drop links to it.
for outNodeID, inAdjacency := range adjacencies {
outAdjacency := report.MakeIDList()
for _, inAdjacent := range inAdjacency {
outAdjacent, ok := mapped[inAdjacent]
if ok {
if outAdjacent, ok := mapped[inAdjacent]; ok {
outAdjacency = outAdjacency.Add(outAdjacent)
}
}

View File

@@ -48,63 +48,61 @@ func TestReduceEdge(t *testing.T) {
}
}
func TestMapRender(t *testing.T) {
func TestMapRender1(t *testing.T) {
// 1. Check when we return false, the node gets filtered out
{
mapper := render.Map{
MapFunc: func(nodes render.RenderableNode) (render.RenderableNode, bool) {
return render.RenderableNode{}, false
},
Renderer: mockRenderer{RenderableNodes: render.RenderableNodes{
"foo": {ID: "foo"},
}},
}
want := render.RenderableNodes{}
have := mapper.Render(report.MakeReport())
if !reflect.DeepEqual(want, have) {
t.Errorf("want %+v, have %+v", want, have)
}
mapper := render.Map{
MapFunc: func(nodes render.RenderableNode) (render.RenderableNode, bool) {
return render.RenderableNode{}, false
},
Renderer: mockRenderer{RenderableNodes: render.RenderableNodes{
"foo": {ID: "foo"},
}},
}
want := render.RenderableNodes{}
have := mapper.Render(report.MakeReport())
if !reflect.DeepEqual(want, have) {
t.Errorf("want %+v, have %+v", want, have)
}
}
func TestMapRender2(t *testing.T) {
// 2. Check we can remap two nodes into one
{
mapper := render.Map{
MapFunc: func(nodes render.RenderableNode) (render.RenderableNode, bool) {
return render.RenderableNode{ID: "bar"}, true
},
Renderer: mockRenderer{RenderableNodes: render.RenderableNodes{
"foo": {ID: "foo"},
"baz": {ID: "baz"},
}},
}
want := render.RenderableNodes{
"bar": render.RenderableNode{ID: "bar"},
}
have := mapper.Render(report.MakeReport())
if !reflect.DeepEqual(want, have) {
t.Errorf("want %+v, have %+v", want, have)
}
mapper := render.Map{
MapFunc: func(nodes render.RenderableNode) (render.RenderableNode, bool) {
return render.RenderableNode{ID: "bar"}, true
},
Renderer: mockRenderer{RenderableNodes: render.RenderableNodes{
"foo": {ID: "foo"},
"baz": {ID: "baz"},
}},
}
want := render.RenderableNodes{
"bar": render.RenderableNode{ID: "bar"},
}
have := mapper.Render(report.MakeReport())
if !reflect.DeepEqual(want, have) {
t.Errorf("want %+v, have %+v", want, have)
}
}
func TestMapRender3(t *testing.T) {
// 3. Check we can remap adjacencies
{
mapper := render.Map{
MapFunc: func(nodes render.RenderableNode) (render.RenderableNode, bool) {
return render.RenderableNode{ID: "_" + nodes.ID}, true
},
Renderer: mockRenderer{RenderableNodes: render.RenderableNodes{
"foo": {ID: "foo", Adjacency: report.MakeIDList("baz")},
"baz": {ID: "baz", Adjacency: report.MakeIDList("foo")},
}},
}
want := render.RenderableNodes{
"_foo": {ID: "_foo", Adjacency: report.MakeIDList("_baz")},
"_baz": {ID: "_baz", Adjacency: report.MakeIDList("_foo")},
}
have := mapper.Render(report.MakeReport())
if !reflect.DeepEqual(want, have) {
t.Errorf("want %+v, have %+v", want, have)
}
mapper := render.Map{
MapFunc: func(nodes render.RenderableNode) (render.RenderableNode, bool) {
return render.RenderableNode{ID: "_" + nodes.ID}, true
},
Renderer: mockRenderer{RenderableNodes: render.RenderableNodes{
"foo": {ID: "foo", Adjacency: report.MakeIDList("baz")},
"baz": {ID: "baz", Adjacency: report.MakeIDList("foo")},
}},
}
want := render.RenderableNodes{
"_foo": {ID: "_foo", Adjacency: report.MakeIDList("_baz")},
"_baz": {ID: "_baz", Adjacency: report.MakeIDList("_foo")},
}
have := mapper.Render(report.MakeReport())
if !reflect.DeepEqual(want, have) {
t.Errorf("want %+v, have %+v", want, have)
}
}

View File

@@ -97,6 +97,12 @@ func ParseNodeID(nodeID string) (hostID string, remainder string, ok bool) {
return fields[0], fields[1], true
}
// ExtractHostID extracts the host id from NodeMetadata
func ExtractHostID(m NodeMetadata) string {
hostid, _, _ := ParseNodeID(m[HostNodeID])
return hostid
}
// MakePseudoNodeID produces a pseudo node ID from its composite parts.
func MakePseudoNodeID(parts ...string) string {
return strings.Join(append([]string{"pseudo"}, parts...), ScopeDelim)