Merge pull request #1182 from weaveworks/1132-weave-topology

Add the basics for a Weave-specific topology.
This commit is contained in:
Alfonso Acosta
2016-10-28 12:23:55 +02:00
committed by GitHub
14 changed files with 155 additions and 32 deletions

View File

@@ -147,6 +147,12 @@ func init() {
Name: "Hosts",
Rank: 4,
},
APITopologyDesc{
id: "weave",
parent: "hosts",
renderer: render.WeaveRenderer,
Name: "Weave Net",
},
)
}

View File

@@ -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

View File

@@ -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
}
}
}

View File

@@ -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,

View File

@@ -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)
}

View File

@@ -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)

View File

@@ -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))
}

View File

@@ -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"
@@ -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
@@ -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)),
),
)

View File

@@ -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)

View File

@@ -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 {

View File

@@ -31,4 +31,5 @@ var (
SelectService = TopologySelector(report.Service)
SelectDeployment = TopologySelector(report.Deployment)
SelectReplicaSet = TopologySelector(report.ReplicaSet)
SelectOverlay = TopologySelector(report.Overlay)
)

35
render/weave.go Normal file
View File

@@ -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}
}

View File

@@ -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, id
}
// ParseNodeID produces the host ID and remainder (typically an address) from

View File

@@ -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,