diff --git a/app/api_topology.go b/app/api_topology.go index 204ddaa65c..03f96934e5 100644 --- a/app/api_topology.go +++ b/app/api_topology.go @@ -35,7 +35,7 @@ type APIEdge struct { // Full topology. func handleTopology(rep xfer.Reporter, t topologyView, w http.ResponseWriter, r *http.Request) { respondWith(w, http.StatusOK, APITopology{ - Nodes: t.renderer.Render(rep.Report()), + Nodes: t.renderer.Render(rep.Report()).Prune(), }) } @@ -117,7 +117,7 @@ func handleWebsocket( tick = time.Tick(loop) ) for { - newTopo := t.renderer.Render(rep.Report()) + newTopo := t.renderer.Render(rep.Report()).Prune() diff := render.TopoDiff(previousTopo, newTopo) previousTopo = newTopo diff --git a/app/api_topology_test.go b/app/api_topology_test.go index 8bd90038b0..b81f75661f 100644 --- a/app/api_topology_test.go +++ b/app/api_topology_test.go @@ -60,7 +60,7 @@ func TestAPITopologyContainers(t *testing.T) { t.Fatal(err) } - if want, have := expected.RenderedContainers, expected.Sterilize(topo.Nodes); !reflect.DeepEqual(want, have) { + if want, have := expected.RenderedContainers, topo.Nodes.Prune(); !reflect.DeepEqual(want, have) { t.Error(test.Diff(want, have)) } } @@ -108,7 +108,7 @@ func TestAPITopologyHosts(t *testing.T) { t.Fatal(err) } - if want, have := expected.RenderedHosts, expected.Sterilize(topo.Nodes); !reflect.DeepEqual(want, have) { + if want, have := expected.RenderedHosts, topo.Nodes.Prune(); !reflect.DeepEqual(want, have) { t.Error(test.Diff(want, have)) } } diff --git a/render/expected/expected.go b/render/expected/expected.go index 6966d14494..74146e17bd 100644 --- a/render/expected/expected.go +++ b/render/expected/expected.go @@ -8,21 +8,6 @@ import ( "github.com/weaveworks/scope/test" ) -// Sterilize cleans up RenderableNodes test fixtures -func Sterilize(r render.RenderableNodes) render.RenderableNodes { - // RenderableNodes contain Nodes, but generally we - // only care about the Adjacency field - the rest is internal - // state not sent to the client. So in the tests we ignore - // this state. - for id, n := range r { - n.Node.Metadata = report.Metadata{} - n.Node.Counters = report.Counters{} - n.Node.Edges = report.EdgeMetadatas{} - r[id] = n - } - return r -} - // Exported for testing. var ( uncontainedServerID = render.MakePseudoNodeID(render.UncontainedID, test.ServerHostName) @@ -80,7 +65,7 @@ var ( ServerProcessID = render.MakeProcessID(test.ServerHostID, test.ServerPID) nonContainerProcessID = render.MakeProcessID(test.ServerHostID, test.NonContainerPID) - RenderedProcesses = Sterilize(render.RenderableNodes{ + RenderedProcesses = (render.RenderableNodes{ ClientProcess1ID: { ID: ClientProcess1ID, LabelMajor: test.Client1Comm, @@ -149,9 +134,9 @@ var ( unknownPseudoNode1ID: unknownPseudoNode1(report.MakeIDList(ServerProcessID)), unknownPseudoNode2ID: unknownPseudoNode2(report.MakeIDList(ServerProcessID)), render.TheInternetID: theInternetNode(report.MakeIDList(ServerProcessID)), - }) + }).Prune() - RenderedProcessNames = Sterilize(render.RenderableNodes{ + RenderedProcessNames = (render.RenderableNodes{ "curl": { ID: "curl", LabelMajor: "curl", @@ -205,9 +190,9 @@ var ( unknownPseudoNode1ID: unknownPseudoNode1(report.MakeIDList("apache")), unknownPseudoNode2ID: unknownPseudoNode2(report.MakeIDList("apache")), render.TheInternetID: theInternetNode(report.MakeIDList("apache")), - }) + }).Prune() - RenderedContainers = Sterilize(render.RenderableNodes{ + RenderedContainers = (render.RenderableNodes{ test.ClientContainerID: { ID: test.ClientContainerID, LabelMajor: "client", @@ -263,9 +248,9 @@ var ( EdgeMetadata: report.EdgeMetadata{}, }, render.TheInternetID: theInternetNode(report.MakeIDList(test.ServerContainerID)), - }) + }).Prune() - RenderedContainerImages = Sterilize(render.RenderableNodes{ + RenderedContainerImages = (render.RenderableNodes{ test.ClientContainerImageName: { ID: test.ClientContainerImageName, LabelMajor: test.ClientContainerImageName, @@ -320,14 +305,14 @@ var ( EdgeMetadata: report.EdgeMetadata{}, }, render.TheInternetID: theInternetNode(report.MakeIDList(test.ServerContainerImageName)), - }) + }).Prune() ServerHostRenderedID = render.MakeHostID(test.ServerHostID) ClientHostRenderedID = render.MakeHostID(test.ClientHostID) pseudoHostID1 = render.MakePseudoNodeID(test.UnknownClient1IP, test.ServerIP) pseudoHostID2 = render.MakePseudoNodeID(test.UnknownClient3IP, test.ServerIP) - RenderedHosts = Sterilize(render.RenderableNodes{ + RenderedHosts = (render.RenderableNodes{ ServerHostRenderedID: { ID: ServerHostRenderedID, LabelMajor: "server", // before first . @@ -382,7 +367,7 @@ var ( EdgeMetadata: report.EdgeMetadata{}, Origins: report.MakeIDList(test.RandomAddressNodeID), }, - }) + }).Prune() ) func newu64(value uint64) *uint64 { return &value } diff --git a/render/render_test.go b/render/render_test.go index dc89f140f0..ab30ba032c 100644 --- a/render/render_test.go +++ b/render/render_test.go @@ -5,7 +5,6 @@ import ( "testing" "github.com/weaveworks/scope/render" - "github.com/weaveworks/scope/render/expected" "github.com/weaveworks/scope/report" "github.com/weaveworks/scope/test" ) @@ -141,8 +140,8 @@ func TestMapEdge(t *testing.T) { Renderer: selector, } - have := expected.Sterilize(mapper.Render(report.MakeReport())) - want := expected.Sterilize(render.RenderableNodes{ + have := mapper.Render(report.MakeReport()).Prune() + want := (render.RenderableNodes{ "_foo": { ID: "_foo", Origins: report.MakeIDList("foo"), @@ -161,7 +160,7 @@ func TestMapEdge(t *testing.T) { EgressByteCount: newu64(6), }, }, - }) + }).Prune() if !reflect.DeepEqual(want, have) { t.Error(test.Diff(want, have)) } @@ -182,10 +181,10 @@ func TestFilterRender(t *testing.T) { "baz": {ID: "baz", Node: report.MakeNode()}, }}) want := render.RenderableNodes{ - "foo": {ID: "foo", Node: report.MakeNode().WithAdjacent("bar")}, - "bar": {ID: "bar", Node: report.MakeNode().WithAdjacent("foo")}, + "foo": {ID: "foo", Origins: report.IDList{}, Node: report.MakeNode().WithAdjacent("bar")}, + "bar": {ID: "bar", Origins: report.IDList{}, Node: report.MakeNode().WithAdjacent("foo")}, } - have := expected.Sterilize(renderer.Render(report.MakeReport())) + have := renderer.Render(report.MakeReport()).Prune() if !reflect.DeepEqual(want, have) { t.Error(test.Diff(want, have)) } @@ -204,10 +203,10 @@ func TestFilterRender2(t *testing.T) { }}, } want := render.RenderableNodes{ - "foo": {ID: "foo", Node: report.MakeNode()}, - "baz": {ID: "baz", Node: report.MakeNode()}, + "foo": {ID: "foo", Origins: report.IDList{}, Node: report.MakeNode()}, + "baz": {ID: "baz", Origins: report.IDList{}, Node: report.MakeNode()}, } - have := expected.Sterilize(renderer.Render(report.MakeReport())) + have := renderer.Render(report.MakeReport()).Prune() if !reflect.DeepEqual(want, have) { t.Error(test.Diff(want, have)) } diff --git a/render/renderable_node.go b/render/renderable_node.go index cf3917fe53..591ede43db 100644 --- a/render/renderable_node.go +++ b/render/renderable_node.go @@ -122,6 +122,17 @@ func (rn RenderableNode) Copy() RenderableNode { } } +// Prune returns a copy of the RenderableNode with all information not +// strictly necessary for rendering nodes and edges stripped away. +// Specifically, that means cutting out parts of the Node. +func (rn RenderableNode) Prune() RenderableNode { + cp := rn.Copy() + cp.Node.Metadata = report.Metadata{} // snip + cp.Node.Counters = report.Counters{} // snip + cp.Node.Edges = report.EdgeMetadatas{} // snip + return cp +} + // RenderableNodes is a set of RenderableNodes type RenderableNodes map[string]RenderableNode @@ -149,3 +160,13 @@ func (rns RenderableNodes) Merge(other RenderableNodes) RenderableNodes { } return result } + +// Prune returns a copy of the RenderableNodes with all information not +// strictly necessary for rendering nodes and edges in the UI cut away. +func (rns RenderableNodes) Prune() RenderableNodes { + cp := rns.Copy() + for id, rn := range cp { + cp[id] = rn.Prune() + } + return cp +} diff --git a/render/renderable_node_test.go b/render/renderable_node_test.go index 36e7f70c32..2401a3a732 100644 --- a/render/renderable_node_test.go +++ b/render/renderable_node_test.go @@ -5,7 +5,6 @@ import ( "testing" "github.com/weaveworks/scope/render" - "github.com/weaveworks/scope/render/expected" "github.com/weaveworks/scope/report" "github.com/weaveworks/scope/test" ) @@ -19,11 +18,11 @@ func TestMergeRenderableNodes(t *testing.T) { "bar": render.NewRenderableNode("bar"), "baz": render.NewRenderableNode("baz"), } - want := expected.Sterilize(render.RenderableNodes{ + want := (render.RenderableNodes{ "foo": render.NewRenderableNode("foo"), "bar": render.NewRenderableNode("bar"), "baz": render.NewRenderableNode("baz"), - }) + }).Prune() have := nodes1.Merge(nodes2) if !reflect.DeepEqual(want, have) { t.Error(test.Diff(want, have)) diff --git a/render/topologies_test.go b/render/topologies_test.go index a161207dfa..e87e0b2296 100644 --- a/render/topologies_test.go +++ b/render/topologies_test.go @@ -11,7 +11,7 @@ import ( ) func TestProcessRenderer(t *testing.T) { - have := expected.Sterilize(render.ProcessRenderer.Render(test.Report)) + have := render.ProcessRenderer.Render(test.Report).Prune() want := expected.RenderedProcesses if !reflect.DeepEqual(want, have) { t.Error(test.Diff(want, have)) @@ -19,7 +19,7 @@ func TestProcessRenderer(t *testing.T) { } func TestProcessNameRenderer(t *testing.T) { - have := expected.Sterilize(render.ProcessNameRenderer.Render(test.Report)) + have := render.ProcessNameRenderer.Render(test.Report).Prune() want := expected.RenderedProcessNames if !reflect.DeepEqual(want, have) { t.Error(test.Diff(want, have)) @@ -27,7 +27,7 @@ func TestProcessNameRenderer(t *testing.T) { } func TestContainerRenderer(t *testing.T) { - have := expected.Sterilize(render.ContainerWithImageNameRenderer{}.Render(test.Report)) + have := (render.ContainerWithImageNameRenderer{}.Render(test.Report)).Prune() want := expected.RenderedContainers if !reflect.DeepEqual(want, have) { t.Error(test.Diff(want, have)) @@ -39,7 +39,7 @@ func TestContainerFilterRenderer(t *testing.T) { // it is filtered out correctly. input := test.Report.Copy() input.Container.Nodes[test.ClientContainerNodeID].Metadata[docker.LabelPrefix+"works.weave.role"] = "system" - have := expected.Sterilize(render.FilterSystem(render.ContainerWithImageNameRenderer{}).Render(input)) + have := render.FilterSystem(render.ContainerWithImageNameRenderer{}).Render(input).Prune() want := expected.RenderedContainers.Copy() delete(want, test.ClientContainerID) if !reflect.DeepEqual(want, have) { @@ -48,7 +48,7 @@ func TestContainerFilterRenderer(t *testing.T) { } func TestContainerImageRenderer(t *testing.T) { - have := expected.Sterilize(render.ContainerImageRenderer.Render(test.Report)) + have := render.ContainerImageRenderer.Render(test.Report).Prune() want := expected.RenderedContainerImages if !reflect.DeepEqual(want, have) { t.Error(test.Diff(want, have)) @@ -56,7 +56,7 @@ func TestContainerImageRenderer(t *testing.T) { } func TestHostRenderer(t *testing.T) { - have := expected.Sterilize(render.HostRenderer.Render(test.Report)) + have := render.HostRenderer.Render(test.Report).Prune() want := expected.RenderedHosts if !reflect.DeepEqual(want, have) { t.Error(test.Diff(want, have)) diff --git a/report/topology.go b/report/topology.go index 263cc8c1fa..033ddaed73 100644 --- a/report/topology.go +++ b/report/topology.go @@ -10,7 +10,7 @@ import ( // EdgeMetadatas and Nodes respectively. Edges are directional, and embedded // in the Node struct. type Topology struct { - Nodes + Nodes // TODO(pb): remove Nodes intermediate type } // MakeTopology gives you a Topology. @@ -48,6 +48,7 @@ func (t Topology) Merge(other Topology) Topology { } // Nodes is a collection of nodes in a topology. Keys are node IDs. +// TODO(pb): type Topology map[string]Node type Nodes map[string]Node // Copy returns a value copy of the Nodes. @@ -75,10 +76,10 @@ func (n Nodes) Merge(other Nodes) Nodes { // given node in a given topology, along with the edges emanating from the // node and metadata about those edges. type Node struct { - Metadata `json:"-"` - Counters `json:"-"` + Metadata `json:"metadata,omitempty"` + Counters `json:"counters,omitempty"` Adjacency IDList `json:"adjacency"` - Edges EdgeMetadatas `json:"-"` + Edges EdgeMetadatas `json:"edges,omitempty"` } // MakeNode creates a new Node with no initial metadata.