From 8e4dfd7987645cdd698615ed57b8b70cb5c3e596 Mon Sep 17 00:00:00 2001 From: Alfonso Acosta Date: Mon, 24 Oct 2016 15:33:30 +0000 Subject: [PATCH 1/7] Add Weave peers view --- app/api_topologies.go | 7 +++++++ common/weave/client.go | 11 +++++++++-- common/weave/client_test.go | 8 ++++++++ probe/host/tagger.go | 6 +++--- probe/overlay/weave.go | 16 +++++++++++++--- render/selectors.go | 1 + render/weave.go | 23 +++++++++++++++++++++++ test/weave/mock.go | 11 +++++++++-- 8 files changed, 73 insertions(+), 10 deletions(-) create mode 100644 render/weave.go diff --git a/app/api_topologies.go b/app/api_topologies.go index deefe81f1..600e1a667 100644 --- a/app/api_topologies.go +++ b/app/api_topologies.go @@ -147,6 +147,13 @@ func init() { Name: "Hosts", Rank: 4, }, + APITopologyDesc{ + id: "weave", + parent: "hosts", + renderer: render.WeaveRenderer, + Name: "Weave", + Rank: 3, + }, ) } diff --git a/common/weave/client.go b/common/weave/client.go index 9199e4ec3..4ec39ca78 100644 --- a/common/weave/client.go +++ b/common/weave/client.go @@ -34,8 +34,15 @@ type Status struct { type Router struct { Name string Peers []struct { - Name string - NickName string + Name string + NickName string + Connections []struct { + Name string + NickName string + Address string + Outbound bool + Established bool + } } } diff --git a/common/weave/client_test.go b/common/weave/client_test.go index 362de7c0d..c598c5524 100644 --- a/common/weave/client_test.go +++ b/common/weave/client_test.go @@ -67,6 +67,14 @@ func TestStatus(t *testing.T) { Peers: []struct { Name string NickName string + // TODO, extend + Connections []struct { + Name string + NickName string + Address string + Outbound bool + Established bool + } }{ { Name: mockWeavePeerName, diff --git a/probe/host/tagger.go b/probe/host/tagger.go index 8b0b7ec46..2896e9215 100644 --- a/probe/host/tagger.go +++ b/probe/host/tagger.go @@ -29,9 +29,9 @@ func (t Tagger) Tag(r report.Report) (report.Report, error) { parents = report.EmptySets.Add(report.Host, report.MakeStringSet(t.hostNodeID)) ) - // Explicitly don't tag Endpoints and Addresses - These topologies include pseudo nodes, - // and as such do their own host tagging - for _, topology := range []report.Topology{r.Process, r.Container, r.ContainerImage, r.Host, r.Overlay, r.Pod} { + // Explicitly don't tag Endpoints, Addresses and Overlay nodes - These topologies include pseudo nodes, + // and as such do their own host tagging. + for _, topology := range []report.Topology{r.Process, r.Container, r.ContainerImage, r.Host, r.Pod} { for _, node := range topology.Nodes { topology.AddNode(node.WithLatests(metadata).WithParents(parents)) } diff --git a/probe/overlay/weave.go b/probe/overlay/weave.go index 913117cd8..b14d4e535 100644 --- a/probe/overlay/weave.go +++ b/probe/overlay/weave.go @@ -6,6 +6,7 @@ import ( "time" "github.com/weaveworks/scope/common/backoff" + "github.com/weaveworks/scope/common/mtime" "github.com/weaveworks/scope/common/weave" "github.com/weaveworks/scope/probe/docker" "github.com/weaveworks/scope/probe/host" @@ -163,11 +164,20 @@ func (w *Weave) Report() (report.Report, error) { WeaveDNSHostname: {ID: WeaveDNSHostname, Label: "Weave DNS Name", From: report.FromLatest, Priority: 18}, }) for _, peer := range w.statusCache.Router.Peers { - r.Overlay.AddNode(report.MakeNodeWith(report.MakeOverlayNodeID(peer.Name), map[string]string{ + node := report.MakeNodeWith(report.MakeOverlayNodeID(peer.Name), map[string]string{ WeavePeerName: peer.Name, WeavePeerNickName: peer.NickName, - })) - + }) + if peer.Name == w.statusCache.Router.Name { + node = node.WithLatest(report.HostNodeID, mtime.Now(), w.hostID) + node = node.WithParents(report.EmptySets.Add(report.Host, report.MakeStringSet(w.hostID))) + } + for _, conn := range peer.Connections { + if conn.Outbound { + node = node.WithAdjacent(report.MakeOverlayNodeID(conn.Name)) + } + } + r.Overlay.AddNode(node) } if w.statusCache.IPAM.DefaultSubnet != "" { r.Overlay.AddNode( diff --git a/render/selectors.go b/render/selectors.go index fa5344749..286bc29ee 100644 --- a/render/selectors.go +++ b/render/selectors.go @@ -31,4 +31,5 @@ var ( SelectService = TopologySelector(report.Service) SelectDeployment = TopologySelector(report.Deployment) SelectReplicaSet = TopologySelector(report.ReplicaSet) + SelectOverlay = TopologySelector(report.Overlay) ) diff --git a/render/weave.go b/render/weave.go new file mode 100644 index 000000000..588729157 --- /dev/null +++ b/render/weave.go @@ -0,0 +1,23 @@ +package render + +import ( + "github.com/weaveworks/scope/probe/overlay" + "github.com/weaveworks/scope/report" +) + +// WeaveRenderer is a Renderer which produces a renderable weave topology. +var WeaveRenderer = MakeMap( + MapWeaveIdentity, + SelectOverlay, +) + +// MapWeaveIdentity maps an overlay topology node to a weave topology node. +func MapWeaveIdentity(m report.Node, _ report.Networks) report.Nodes { + var node = m + if _, ok := m.Latest.Lookup(report.HostNodeID); !ok { + nickname, _ := m.Latest.Lookup(overlay.WeavePeerNickName) + id := MakePseudoNodeID(UnmanagedID, nickname) + node = NewDerivedPseudoNode(id, m) + } + return report.Nodes{node.ID: node} +} diff --git a/test/weave/mock.go b/test/weave/mock.go index 6cd5ed0b9..ff59c9a4b 100644 --- a/test/weave/mock.go +++ b/test/weave/mock.go @@ -26,8 +26,15 @@ func (MockClient) Status() (weave.Status, error) { Router: weave.Router{ Name: MockWeavePeerName, Peers: []struct { - Name string - NickName string + Name string + NickName string + Connections []struct { + Name string + NickName string + Address string + Outbound bool + Established bool + } }{ { Name: MockWeavePeerName, From e80a01aab92a47e1c981069b766d282c97282e06 Mon Sep 17 00:00:00 2001 From: Alfonso Acosta Date: Mon, 24 Oct 2016 17:20:07 +0000 Subject: [PATCH 2/7] Filter out docker overlay peers --- probe/docker/reporter.go | 12 +++++------- probe/docker/reporter_test.go | 3 +-- probe/overlay/weave.go | 13 +++++++------ probe/overlay/weave_test.go | 2 +- render/weave.go | 12 +++++++++--- report/id.go | 29 ++++++++++++++++++++++++++--- 6 files changed, 49 insertions(+), 22 deletions(-) diff --git a/probe/docker/reporter.go b/probe/docker/reporter.go index f9bf68276..66ae36564 100644 --- a/probe/docker/reporter.go +++ b/probe/docker/reporter.go @@ -13,11 +13,10 @@ import ( // Keys for use in Node const ( - ImageID = "docker_image_id" - ImageName = "docker_image_name" - ImageLabelPrefix = "docker_image_label_" - OverlayPeerPrefix = "docker_peer_" - IsInHostNetwork = "docker_is_in_host_network" + ImageID = "docker_image_id" + ImageName = "docker_image_name" + ImageLabelPrefix = "docker_image_label_" + IsInHostNetwork = "docker_is_in_host_network" ) // Exposed for testing @@ -261,10 +260,9 @@ func (r *Reporter) overlayTopology() report.Topology { } }) - peerID := OverlayPeerPrefix + r.hostID // Add both local and global networks to the LocalNetworks Set // since we treat container IPs as local - node := report.MakeNode(report.MakeOverlayNodeID(peerID)).WithSets( + node := report.MakeNode(report.MakeOverlayNodeID(report.DockerOverlayPeerPrefix, r.hostID)).WithSets( report.MakeSets().Add(host.LocalNetworks, report.MakeStringSet(subnets...))) return report.MakeTopology().AddNode(node) } diff --git a/probe/docker/reporter_test.go b/probe/docker/reporter_test.go index 1a81bc0fc..a6d48bb72 100644 --- a/probe/docker/reporter_test.go +++ b/probe/docker/reporter_test.go @@ -134,8 +134,7 @@ func TestReporter(t *testing.T) { // Reporter should add a container network { - peerID := docker.OverlayPeerPrefix + hostID - overlayNodeID := report.MakeOverlayNodeID(peerID) + overlayNodeID := report.MakeOverlayNodeID(report.DockerOverlayPeerPrefix, hostID) node, ok := rpt.Overlay.Nodes[overlayNodeID] if !ok { t.Fatalf("Expected report to have overlay node %q, but not found", overlayNodeID) diff --git a/probe/overlay/weave.go b/probe/overlay/weave.go index b14d4e535..d4b173d68 100644 --- a/probe/overlay/weave.go +++ b/probe/overlay/weave.go @@ -164,24 +164,25 @@ func (w *Weave) Report() (report.Report, error) { WeaveDNSHostname: {ID: WeaveDNSHostname, Label: "Weave DNS Name", From: report.FromLatest, Priority: 18}, }) for _, peer := range w.statusCache.Router.Peers { - node := report.MakeNodeWith(report.MakeOverlayNodeID(peer.Name), map[string]string{ - WeavePeerName: peer.Name, - WeavePeerNickName: peer.NickName, - }) + node := report.MakeNodeWith(report.MakeOverlayNodeID(report.WeaveOverlayPeerPrefix, peer.Name), + map[string]string{ + WeavePeerName: peer.Name, + WeavePeerNickName: peer.NickName, + }) if peer.Name == w.statusCache.Router.Name { node = node.WithLatest(report.HostNodeID, mtime.Now(), w.hostID) node = node.WithParents(report.EmptySets.Add(report.Host, report.MakeStringSet(w.hostID))) } for _, conn := range peer.Connections { if conn.Outbound { - node = node.WithAdjacent(report.MakeOverlayNodeID(conn.Name)) + node = node.WithAdjacent(report.MakeOverlayNodeID(report.WeaveOverlayPeerPrefix, conn.Name)) } } r.Overlay.AddNode(node) } if w.statusCache.IPAM.DefaultSubnet != "" { r.Overlay.AddNode( - report.MakeNode(report.MakeOverlayNodeID(w.statusCache.Router.Name)).WithSets( + report.MakeNode(report.MakeOverlayNodeID(report.WeaveOverlayPeerPrefix, w.statusCache.Router.Name)).WithSets( report.MakeSets().Add(host.LocalNetworks, report.MakeStringSet(w.statusCache.IPAM.DefaultSubnet)), ), ) diff --git a/probe/overlay/weave_test.go b/probe/overlay/weave_test.go index fc7161c5b..aec56548b 100644 --- a/probe/overlay/weave_test.go +++ b/probe/overlay/weave_test.go @@ -35,7 +35,7 @@ func TestWeaveTaggerOverlayTopology(t *testing.T) { t.Fatal(err) } - nodeID := report.MakeOverlayNodeID(weave.MockWeavePeerName) + nodeID := report.MakeOverlayNodeID(report.WeaveOverlayPeerPrefix, weave.MockWeavePeerName) node, ok := have.Overlay.Nodes[nodeID] if !ok { t.Errorf("Expected overlay node %q, but not found", nodeID) diff --git a/render/weave.go b/render/weave.go index 588729157..28d708e59 100644 --- a/render/weave.go +++ b/render/weave.go @@ -13,11 +13,17 @@ var WeaveRenderer = MakeMap( // MapWeaveIdentity maps an overlay topology node to a weave topology node. func MapWeaveIdentity(m report.Node, _ report.Networks) report.Nodes { - var node = m - if _, ok := m.Latest.Lookup(report.HostNodeID); !ok { + + peerPrefix, peerName := report.ParseOverlayNodeID(m.ID) + if peerPrefix != report.WeaveOverlayPeerPrefix { + return nil + } + + var node = NewDerivedNode(peerName, m) + if _, ok := node.Latest.Lookup(report.HostNodeID); !ok { nickname, _ := m.Latest.Lookup(overlay.WeavePeerNickName) id := MakePseudoNodeID(UnmanagedID, nickname) node = NewDerivedPseudoNode(id, m) } - return report.Nodes{node.ID: node} + return report.Nodes{peerName: node} } diff --git a/report/id.go b/report/id.go index dd1c3720f..ea6a279e9 100644 --- a/report/id.go +++ b/report/id.go @@ -22,6 +22,12 @@ const ( // Key added to nodes to prevent them being joined with conntracked connections DoesNotMakeConnections = "does_not_make_connections" + + // WeaveOverlayPeerPrefix is the prefix for weave peers in the overlay network + WeaveOverlayPeerPrefix = "" + + // DockerOverlayPeerPrefix is the prefix for docker peers in the overlay network + DockerOverlayPeerPrefix = "docker_peer_" ) // MakeEndpointNodeID produces an endpoint node ID from its composite parts. @@ -134,9 +140,26 @@ func parseSingleComponentID(tag string) func(string) (string, bool) { } // MakeOverlayNodeID produces an overlay topology node ID from a router peer's -// name, which is assumed to be globally unique. -func MakeOverlayNodeID(peerName string) string { - return "#" + peerName +// prefix and name, which is assumed to be globally unique. +func MakeOverlayNodeID(peerPrefix, peerName string) string { + return "#" + peerPrefix + peerName +} + +// ParseOverlayNodeID produces the overlay type and peer name. +func ParseOverlayNodeID(id string) (overlayPrefix string, peerName string) { + + if !strings.HasPrefix(id, "#") { + // Best we can do + return "", "" + } + + id = id[1:] + + if strings.HasPrefix(id, DockerOverlayPeerPrefix) { + return DockerOverlayPeerPrefix, id[len(DockerOverlayPeerPrefix):] + } + + return WeaveOverlayPeerPrefix, peerName } // ParseNodeID produces the host ID and remainder (typically an address) from From 3023f4be80f5b4289ee07b0afa65de81707756e2 Mon Sep 17 00:00:00 2001 From: Alfonso Acosta Date: Wed, 26 Oct 2016 07:40:14 +0000 Subject: [PATCH 3/7] Add Weave summary generator and fix Weave renderer --- app/api_topology.go | 2 +- render/detailed/summary.go | 15 +++++++++++++++ render/weave.go | 13 ++++++++----- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/app/api_topology.go b/app/api_topology.go index d9d78b356..08bfe229c 100644 --- a/app/api_topology.go +++ b/app/api_topology.go @@ -84,7 +84,7 @@ func handleWebsocket( for { // just discard everything the browser sends if _, _, err := c.ReadMessage(); err != nil { if !xfer.IsExpectedWSCloseError(err) { - log.Println("err:", err) + log.Error("err:", err) } close(quit) break diff --git a/render/detailed/summary.go b/render/detailed/summary.go index 6f5f59698..caa2d0a3e 100644 --- a/render/detailed/summary.go +++ b/render/detailed/summary.go @@ -8,6 +8,7 @@ import ( "github.com/weaveworks/scope/probe/endpoint" "github.com/weaveworks/scope/probe/host" "github.com/weaveworks/scope/probe/kubernetes" + "github.com/weaveworks/scope/probe/overlay" "github.com/weaveworks/scope/probe/process" "github.com/weaveworks/scope/render" "github.com/weaveworks/scope/report" @@ -68,6 +69,7 @@ var renderers = map[string]func(NodeSummary, report.Node) (NodeSummary, bool){ report.Deployment: podGroupNodeSummary, report.ReplicaSet: podGroupNodeSummary, report.Host: hostNodeSummary, + report.Overlay: weaveNodeSummary, } var templates = map[string]struct{ Label, LabelMinor string }{ @@ -253,6 +255,18 @@ func hostNodeSummary(base NodeSummary, n report.Node) (NodeSummary, bool) { return base, true } +func weaveNodeSummary(base NodeSummary, n report.Node) (NodeSummary, bool) { + var ( + nickname, _ = n.Latest.Lookup(overlay.WeavePeerNickName) + ) + + _, peerName := report.ParseOverlayNodeID(n.ID) + + base.Label, base.LabelMinor = nickname, peerName + + return base, true +} + // groupNodeSummary renders the summary for a group node. n.Topology is // expected to be of the form: group:container:hostname func groupNodeSummary(base NodeSummary, r report.Report, n report.Node) (NodeSummary, bool) { @@ -298,6 +312,7 @@ type NodeSummaries map[string]NodeSummary // Summaries converts RenderableNodes into a set of NodeSummaries func Summaries(r report.Report, rns report.Nodes) NodeSummaries { + result := NodeSummaries{} for id, node := range rns { if summary, ok := MakeNodeSummary(r, node); ok { diff --git a/render/weave.go b/render/weave.go index 28d708e59..9855c766e 100644 --- a/render/weave.go +++ b/render/weave.go @@ -13,17 +13,20 @@ var WeaveRenderer = MakeMap( // MapWeaveIdentity maps an overlay topology node to a weave topology node. func MapWeaveIdentity(m report.Node, _ report.Networks) report.Nodes { - - peerPrefix, peerName := report.ParseOverlayNodeID(m.ID) + peerPrefix, _ := report.ParseOverlayNodeID(m.ID) if peerPrefix != report.WeaveOverlayPeerPrefix { return nil } - var node = NewDerivedNode(peerName, m) + var ( + node = m + nickname, _ = m.Latest.Lookup(overlay.WeavePeerNickName) + ) + if _, ok := node.Latest.Lookup(report.HostNodeID); !ok { - nickname, _ := m.Latest.Lookup(overlay.WeavePeerNickName) id := MakePseudoNodeID(UnmanagedID, nickname) node = NewDerivedPseudoNode(id, m) } - return report.Nodes{peerName: node} + + return report.Nodes{node.ID: node} } From 306ad68a81afa2edce1625595f9f16829443a0cc Mon Sep 17 00:00:00 2001 From: Alfonso Acosta Date: Wed, 26 Oct 2016 07:47:17 +0000 Subject: [PATCH 4/7] Fix bug when parsing peer names --- report/id.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/report/id.go b/report/id.go index ea6a279e9..0f5466e80 100644 --- a/report/id.go +++ b/report/id.go @@ -159,7 +159,7 @@ func ParseOverlayNodeID(id string) (overlayPrefix string, peerName string) { return DockerOverlayPeerPrefix, id[len(DockerOverlayPeerPrefix):] } - return WeaveOverlayPeerPrefix, peerName + return WeaveOverlayPeerPrefix, id } // ParseNodeID produces the host ID and remainder (typically an address) from From 7771625a25dc6244ae851397fa975b2f3107dcea Mon Sep 17 00:00:00 2001 From: Alfonso Acosta Date: Wed, 26 Oct 2016 08:28:45 +0000 Subject: [PATCH 5/7] Change topology title to Weave Net --- app/api_topologies.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/api_topologies.go b/app/api_topologies.go index 600e1a667..4cd08a3e6 100644 --- a/app/api_topologies.go +++ b/app/api_topologies.go @@ -151,7 +151,7 @@ func init() { id: "weave", parent: "hosts", renderer: render.WeaveRenderer, - Name: "Weave", + Name: "Weave Net", Rank: 3, }, ) From f906511deda1d0fbceb3a8eaddc7d9e3f0a08734 Mon Sep 17 00:00:00 2001 From: Alfonso Acosta Date: Wed, 26 Oct 2016 09:09:01 +0000 Subject: [PATCH 6/7] Add initial metadata in details panel and clarification comments --- common/weave/client.go | 7 ++++--- probe/overlay/weave.go | 13 +++++++++++++ render/weave.go | 3 +++ 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/common/weave/client.go b/common/weave/client.go index 4ec39ca78..8f0ed8d82 100644 --- a/common/weave/client.go +++ b/common/weave/client.go @@ -25,9 +25,10 @@ type Client interface { // Status describes whats happen in the Weave Net router. type Status struct { - Router Router - DNS DNS - IPAM IPAM + Version string + Router Router + DNS DNS + IPAM IPAM } // Router describes the status of the Weave Router diff --git a/probe/overlay/weave.go b/probe/overlay/weave.go index d4b173d68..eb0608e32 100644 --- a/probe/overlay/weave.go +++ b/probe/overlay/weave.go @@ -27,6 +27,9 @@ const ( // WeaveMACAddress is the key for the mac address of the container on the // weave network, to be found in container node metadata WeaveMACAddress = "weave_mac_address" + + // WeaveVersion is the key for the weave version running on the peer + WeaveVersion = "weave_version" ) // Weave represents a single Weave router, presumably on the same host @@ -163,14 +166,24 @@ func (w *Weave) Report() (report.Report, error) { WeaveMACAddress: {ID: WeaveMACAddress, Label: "Weave MAC", From: report.FromLatest, Priority: 17}, WeaveDNSHostname: {ID: WeaveDNSHostname, Label: "Weave DNS Name", From: report.FromLatest, Priority: 18}, }) + r.Overlay = r.Overlay.WithMetadataTemplates(report.MetadataTemplates{ + WeavePeerName: {ID: WeavePeerName, Label: "Peer Name", From: report.FromLatest, Truncate: 17, Priority: 1}, + WeaveVersion: {ID: WeaveVersion, Label: "Version", From: report.FromLatest, Priority: 2}, + }) + + // We report nodes for all peers (not just the current node) to highlight peers not monitored by Scope + // (i.e. without a running probe) + // Note: this will cause redundant information (n^2) if all peers have a running probe for _, peer := range w.statusCache.Router.Peers { node := report.MakeNodeWith(report.MakeOverlayNodeID(report.WeaveOverlayPeerPrefix, peer.Name), map[string]string{ WeavePeerName: peer.Name, WeavePeerNickName: peer.NickName, }) + // Peer corresponding to current host if peer.Name == w.statusCache.Router.Name { node = node.WithLatest(report.HostNodeID, mtime.Now(), w.hostID) + node = node.WithLatest(WeaveVersion, mtime.Now(), w.statusCache.Version) node = node.WithParents(report.EmptySets.Add(report.Host, report.MakeStringSet(w.hostID))) } for _, conn := range peer.Connections { diff --git a/render/weave.go b/render/weave.go index 9855c766e..216a0cf1c 100644 --- a/render/weave.go +++ b/render/weave.go @@ -23,6 +23,9 @@ func MapWeaveIdentity(m report.Node, _ report.Networks) report.Nodes { nickname, _ = m.Latest.Lookup(overlay.WeavePeerNickName) ) + // Nodes without a host id indicate they are not monitored by Scope + // (their info doesn't come from a probe monitoring that peer directly) + // , display them as pseudo nodes. if _, ok := node.Latest.Lookup(report.HostNodeID); !ok { id := MakePseudoNodeID(UnmanagedID, nickname) node = NewDerivedPseudoNode(id, m) From b6b343cbfde087acc02805c1647738f90558c12e Mon Sep 17 00:00:00 2001 From: Alfonso Acosta Date: Fri, 28 Oct 2016 08:58:45 +0000 Subject: [PATCH 7/7] Review feedback --- app/api_topologies.go | 1 - common/weave/client_test.go | 5 ++--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/app/api_topologies.go b/app/api_topologies.go index 4cd08a3e6..ece945363 100644 --- a/app/api_topologies.go +++ b/app/api_topologies.go @@ -152,7 +152,6 @@ func init() { parent: "hosts", renderer: render.WeaveRenderer, Name: "Weave Net", - Rank: 3, }, ) } diff --git a/common/weave/client_test.go b/common/weave/client_test.go index c598c5524..02a17e976 100644 --- a/common/weave/client_test.go +++ b/common/weave/client_test.go @@ -65,9 +65,8 @@ func TestStatus(t *testing.T) { want := weave.Status{ Router: weave.Router{ Peers: []struct { - Name string - NickName string - // TODO, extend + Name string + NickName string Connections []struct { Name string NickName string