Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add the basics for a Weave-specific topology. #1182

Merged
merged 7 commits into from
Oct 28, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions app/api_topologies.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,12 @@ func init() {
Name: "Hosts",
Rank: 4,
},
APITopologyDesc{
id: "weave",
parent: "hosts",
renderer: render.WeaveRenderer,
Name: "Weave Net",
},
)
}

Expand Down
2 changes: 1 addition & 1 deletion app/api_topology.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
18 changes: 13 additions & 5 deletions common/weave/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,25 @@ 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
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
}
}
}

Expand Down
11 changes: 9 additions & 2 deletions common/weave/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,15 @@ func TestStatus(t *testing.T) {
want := weave.Status{
Router: weave.Router{
Peers: []struct {
Name string
NickName string
Name string
NickName string
Connections []struct {
Name string
NickName string
Address string
Outbound bool
Established bool
}
}{
{
Name: mockWeavePeerName,
Expand Down
12 changes: 5 additions & 7 deletions probe/docker/reporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
}
Expand Down
3 changes: 1 addition & 2 deletions probe/docker/reporter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
6 changes: 3 additions & 3 deletions probe/host/tagger.go
Original file line number Diff line number Diff line change
Expand Up @@ -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))
}
Expand Down
36 changes: 30 additions & 6 deletions probe/overlay/weave.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -26,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
Expand Down Expand Up @@ -162,16 +166,36 @@ 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},
})
for _, peer := range w.statusCache.Router.Peers {
r.Overlay.AddNode(report.MakeNodeWith(report.MakeOverlayNodeID(peer.Name), map[string]string{
WeavePeerName: peer.Name,
WeavePeerNickName: peer.NickName,
}))
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 {
if conn.Outbound {
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)),
),
)
Expand Down
2 changes: 1 addition & 1 deletion probe/overlay/weave_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
15 changes: 15 additions & 0 deletions render/detailed/summary.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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 }{
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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 {
Expand Down
1 change: 1 addition & 0 deletions render/selectors.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,5 @@ var (
SelectService = TopologySelector(report.Service)
SelectDeployment = TopologySelector(report.Deployment)
SelectReplicaSet = TopologySelector(report.ReplicaSet)
SelectOverlay = TopologySelector(report.Overlay)
)
35 changes: 35 additions & 0 deletions render/weave.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
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 {
peerPrefix, _ := report.ParseOverlayNodeID(m.ID)
if peerPrefix != report.WeaveOverlayPeerPrefix {
return nil
}

var (
node = m
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)
}

return report.Nodes{node.ID: node}
}
29 changes: 26 additions & 3 deletions report/id.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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, id
}

// ParseNodeID produces the host ID and remainder (typically an address) from
Expand Down
11 changes: 9 additions & 2 deletions test/weave/mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down