diff --git a/app/api_topology.go b/app/api_topology.go index a6c7c8315..81f75e892 100644 --- a/app/api_topology.go +++ b/app/api_topology.go @@ -7,6 +7,7 @@ import ( "github.com/gorilla/mux" "github.com/gorilla/websocket" + "github.com/weaveworks/scope/render" "github.com/weaveworks/scope/report" ) @@ -116,7 +117,7 @@ func handleWebsocket( ) for { newTopo := t.renderer.Render(rep.Report()) - diff := report.TopoDiff(previousTopo, newTopo) + diff := render.TopoDiff(previousTopo, newTopo) previousTopo = newTopo if err := conn.SetWriteDeadline(time.Now().Add(websocketTimeout)); err != nil { diff --git a/app/api_topology_test.go b/app/api_topology_test.go index 7a060d462..3c04c28b8 100644 --- a/app/api_topology_test.go +++ b/app/api_topology_test.go @@ -8,6 +8,7 @@ import ( "github.com/gorilla/websocket" + "github.com/weaveworks/scope/render" "github.com/weaveworks/scope/report" ) @@ -146,7 +147,7 @@ func TestAPITopologyWebsocket(t *testing.T) { _, p, err := ws.ReadMessage() ok(t, err) - var d report.Diff + var d render.Diff if err := json.Unmarshal(p, &d); err != nil { t.Fatalf("JSON parse error: %s", err) } diff --git a/render/topology_diff.go b/render/topology_diff.go new file mode 100644 index 000000000..b384f1c64 --- /dev/null +++ b/render/topology_diff.go @@ -0,0 +1,41 @@ +package render + +import ( + "reflect" + + "github.com/weaveworks/scope/report" +) + +// Diff is returned by TopoDiff. It represents the changes between two +// RenderableNode maps. +type Diff struct { + Add []report.RenderableNode `json:"add"` + Update []report.RenderableNode `json:"update"` + Remove []string `json:"remove"` +} + +// TopoDiff gives you the diff to get from A to B. +func TopoDiff(a, b report.RenderableNodes) Diff { + diff := Diff{} + + notSeen := map[string]struct{}{} + for k := range a { + notSeen[k] = struct{}{} + } + + for k, node := range b { + if _, ok := a[k]; !ok { + diff.Add = append(diff.Add, node) + } else if !reflect.DeepEqual(node, a[k]) { + diff.Update = append(diff.Update, node) + } + delete(notSeen, k) + } + + // leftover keys + for k := range notSeen { + diff.Remove = append(diff.Remove, k) + } + + return diff +} diff --git a/report/topology_test.go b/render/topology_diff_test.go similarity index 65% rename from report/topology_test.go rename to render/topology_diff_test.go index fe09c3b1d..90723a6b9 100644 --- a/report/topology_test.go +++ b/render/topology_diff_test.go @@ -1,13 +1,22 @@ -package report +package render import ( "reflect" "sort" "testing" + + "github.com/weaveworks/scope/report" ) +// ByID is a sort interface for a RenderableNode slice. +type ByID []report.RenderableNode + +func (r ByID) Len() int { return len(r) } +func (r ByID) Swap(i, j int) { r[i], r[j] = r[j], r[i] } +func (r ByID) Less(i, j int) bool { return r[i].ID < r[j].ID } + func TestTopoDiff(t *testing.T) { - nodea := RenderableNode{ + nodea := report.RenderableNode{ ID: "nodea", LabelMajor: "Node A", LabelMinor: "'ts an a", @@ -21,14 +30,14 @@ func TestTopoDiff(t *testing.T) { "nodeb", "nodeq", // not the same anymore } - nodeb := RenderableNode{ + nodeb := report.RenderableNode{ ID: "nodeb", LabelMajor: "Node B", } // Helper to make RenderableNode maps. - nodes := func(ns ...RenderableNode) RenderableNodes { - r := RenderableNodes{} + nodes := func(ns ...report.RenderableNode) report.RenderableNodes { + r := report.RenderableNodes{} for _, n := range ns { r[n.ID] = n } @@ -43,7 +52,7 @@ func TestTopoDiff(t *testing.T) { label: "basecase: empty -> something", have: TopoDiff(nodes(), nodes(nodea, nodeb)), want: Diff{ - Add: []RenderableNode{nodea, nodeb}, + Add: []report.RenderableNode{nodea, nodeb}, }, }, { @@ -57,7 +66,7 @@ func TestTopoDiff(t *testing.T) { label: "add and remove", have: TopoDiff(nodes(nodea), nodes(nodeb)), want: Diff{ - Add: []RenderableNode{nodeb}, + Add: []report.RenderableNode{nodeb}, Remove: []string{"nodea"}, }, }, @@ -70,7 +79,7 @@ func TestTopoDiff(t *testing.T) { label: "change a single node", have: TopoDiff(nodes(nodea), nodes(nodeap)), want: Diff{ - Update: []RenderableNode{nodeap}, + Update: []report.RenderableNode{nodeap}, }, }, } { @@ -78,7 +87,7 @@ func TestTopoDiff(t *testing.T) { sort.Sort(ByID(c.have.Add)) sort.Sort(ByID(c.have.Update)) if !reflect.DeepEqual(c.want, c.have) { - t.Errorf("%s - want:%s have:%s", c.label, c.want, c.have) + t.Errorf("%s - %s", c.label, diff(c.want, c.have)) } } } diff --git a/report/topology.go b/report/topology.go index 1e5381008..d5f2adcef 100644 --- a/report/topology.go +++ b/report/topology.go @@ -3,7 +3,6 @@ package report import ( "fmt" "net" - "reflect" "strings" ) @@ -119,47 +118,6 @@ func netsContain(nets []*net.IPNet, ip net.IP) bool { return false } -// Diff is returned by TopoDiff. It represents the changes between two -// RenderableNode maps. -type Diff struct { - Add []RenderableNode `json:"add"` - Update []RenderableNode `json:"update"` - Remove []string `json:"remove"` -} - -// TopoDiff gives you the diff to get from A to B. -func TopoDiff(a, b RenderableNodes) Diff { - diff := Diff{} - - notSeen := map[string]struct{}{} - for k := range a { - notSeen[k] = struct{}{} - } - - for k, node := range b { - if _, ok := a[k]; !ok { - diff.Add = append(diff.Add, node) - } else if !reflect.DeepEqual(node, a[k]) { - diff.Update = append(diff.Update, node) - } - delete(notSeen, k) - } - - // leftover keys - for k := range notSeen { - diff.Remove = append(diff.Remove, k) - } - - return diff -} - -// ByID is a sort interface for a RenderableNode slice. -type ByID []RenderableNode - -func (r ByID) Len() int { return len(r) } -func (r ByID) Swap(i, j int) { r[i], r[j] = r[j], r[i] } -func (r ByID) Less(i, j int) bool { return r[i].ID < r[j].ID } - // Validate checks the topology for various inconsistencies. func (t Topology) Validate() error { // Check all edge metadata keys must have the appropriate entries in