Backend for node shapes

This commit is contained in:
Tom Wilkie
2016-02-01 17:12:17 -08:00
committed by Simon Howe
parent a34d9c97b8
commit 3f7f55e87e
4 changed files with 112 additions and 15 deletions

View File

@@ -10,6 +10,12 @@ import (
// Exported for testing.
var (
circle = "circle"
square = "square"
pentagon = "pentagon"
hexagon = "hexagon"
cloud = "cloud"
uncontainedServerID = render.MakePseudoNodeID(render.UncontainedID, fixture.ServerHostName)
unknownPseudoNode1ID = render.MakePseudoNodeID("10.10.10.10", fixture.ServerIP, "80")
unknownPseudoNode2ID = render.MakePseudoNodeID("10.10.10.11", fixture.ServerIP, "80")
@@ -18,6 +24,7 @@ var (
ID: unknownPseudoNode1ID,
LabelMajor: "10.10.10.10",
Pseudo: true,
Shape: circle,
Node: report.MakeNode().WithAdjacent(adjacent),
EdgeMetadata: report.EdgeMetadata{
EgressPacketCount: newu64(70),
@@ -30,6 +37,7 @@ var (
ID: unknownPseudoNode2ID,
LabelMajor: "10.10.10.11",
Pseudo: true,
Shape: circle,
Node: report.MakeNode().WithAdjacent(adjacent),
EdgeMetadata: report.EdgeMetadata{
EgressPacketCount: newu64(50),
@@ -42,6 +50,7 @@ var (
ID: render.TheInternetID,
LabelMajor: render.TheInternetMajor,
Pseudo: true,
Shape: cloud,
Node: report.MakeNode().WithAdjacent(adjacent),
EdgeMetadata: report.EdgeMetadata{
EgressPacketCount: newu64(60),
@@ -61,6 +70,7 @@ var (
LabelMinor: fmt.Sprintf("%s (%s)", fixture.ClientHostID, fixture.Client1PID),
Rank: fixture.Client1Name,
Pseudo: false,
Shape: square,
Node: report.MakeNode().WithAdjacent(ServerProcessID),
EdgeMetadata: report.EdgeMetadata{
EgressPacketCount: newu64(10),
@@ -73,6 +83,7 @@ var (
LabelMinor: fmt.Sprintf("%s (%s)", fixture.ClientHostID, fixture.Client2PID),
Rank: fixture.Client2Name,
Pseudo: false,
Shape: square,
Node: report.MakeNode().WithAdjacent(ServerProcessID),
EdgeMetadata: report.EdgeMetadata{
EgressPacketCount: newu64(20),
@@ -85,6 +96,7 @@ var (
LabelMinor: fmt.Sprintf("%s (%s)", fixture.ServerHostID, fixture.ServerPID),
Rank: fixture.ServerName,
Pseudo: false,
Shape: square,
Node: report.MakeNode(),
EdgeMetadata: report.EdgeMetadata{
IngressPacketCount: newu64(210),
@@ -97,6 +109,7 @@ var (
LabelMinor: fmt.Sprintf("%s (%s)", fixture.ServerHostID, fixture.NonContainerPID),
Rank: fixture.NonContainerName,
Pseudo: false,
Shape: square,
Node: report.MakeNode().WithAdjacent(render.TheInternetID),
EdgeMetadata: report.EdgeMetadata{},
},
@@ -116,6 +129,8 @@ var (
LabelMinor: "2 processes",
Rank: fixture.Client1Name,
Pseudo: false,
Shape: square,
Stack: true,
Children: report.MakeNodeSet(
fixture.Report.Process.Nodes[fixture.ClientProcess1NodeID],
fixture.Report.Process.Nodes[fixture.ClientProcess2NodeID],
@@ -132,6 +147,8 @@ var (
LabelMinor: "1 process",
Rank: fixture.ServerName,
Pseudo: false,
Shape: square,
Stack: true,
Children: report.MakeNodeSet(
fixture.Report.Process.Nodes[fixture.ServerProcessNodeID],
),
@@ -147,6 +164,8 @@ var (
LabelMinor: "1 process",
Rank: fixture.NonContainerName,
Pseudo: false,
Shape: square,
Stack: true,
Children: report.MakeNodeSet(
fixture.Report.Process.Nodes[fixture.NonContainerProcessNodeID],
),
@@ -168,6 +187,7 @@ var (
LabelMinor: fixture.ClientHostName,
Rank: fixture.ClientContainerImageName,
Pseudo: false,
Shape: hexagon,
Children: report.MakeNodeSet(
fixture.Report.Process.Nodes[fixture.ClientProcess1NodeID],
fixture.Report.Process.Nodes[fixture.ClientProcess2NodeID],
@@ -185,6 +205,7 @@ var (
LabelMinor: fixture.ServerHostName,
Rank: fixture.ServerContainerImageName,
Pseudo: false,
Shape: hexagon,
Children: report.MakeNodeSet(
fixture.Report.Process.Nodes[fixture.ServerProcessNodeID],
),
@@ -201,6 +222,8 @@ var (
LabelMinor: fixture.ServerHostName,
Rank: "",
Pseudo: true,
Shape: square,
Stack: true,
Children: report.MakeNodeSet(
fixture.Report.Process.Nodes[fixture.NonContainerProcessNodeID],
),
@@ -220,6 +243,8 @@ var (
LabelMinor: "1 container",
Rank: fixture.ClientContainerImageName,
Pseudo: false,
Shape: hexagon,
Stack: true,
Children: report.MakeNodeSet(
fixture.Report.Process.Nodes[fixture.ClientProcess1NodeID],
fixture.Report.Process.Nodes[fixture.ClientProcess2NodeID],
@@ -237,6 +262,8 @@ var (
LabelMinor: "1 container",
Rank: fixture.ServerContainerImageName,
Pseudo: false,
Shape: hexagon,
Stack: true,
Children: report.MakeNodeSet(
fixture.Report.Process.Nodes[fixture.ServerProcessNodeID],
fixture.Report.Container.Nodes[fixture.ServerContainerNodeID],
@@ -253,6 +280,8 @@ var (
LabelMinor: fixture.ServerHostName,
Rank: "",
Pseudo: true,
Shape: square,
Stack: true,
Children: report.MakeNodeSet(
fixture.Report.Process.Nodes[fixture.NonContainerProcessNodeID],
),
@@ -274,6 +303,7 @@ var (
LabelMinor: "hostname.com", // after first .
Rank: "hostname.com",
Pseudo: false,
Shape: circle,
Children: report.MakeNodeSet(
fixture.Report.Container.Nodes[fixture.ServerContainerNodeID],
fixture.Report.Container.Nodes[fixture.ServerProcessNodeID],
@@ -291,6 +321,7 @@ var (
LabelMinor: "hostname.com", // after first .
Rank: "hostname.com",
Pseudo: false,
Shape: circle,
Children: report.MakeNodeSet(
fixture.Report.Container.Nodes[fixture.ClientContainerNodeID],
fixture.Report.Process.Nodes[fixture.ClientProcess1NodeID],
@@ -307,6 +338,7 @@ var (
ID: pseudoHostID1,
LabelMajor: fixture.UnknownClient1IP,
Pseudo: true,
Shape: circle,
Node: report.MakeNode().WithAdjacent(ServerHostRenderedID),
EdgeMetadata: report.EdgeMetadata{},
Children: report.MakeNodeSet(
@@ -318,6 +350,7 @@ var (
ID: pseudoHostID2,
LabelMajor: fixture.UnknownClient3IP,
Pseudo: true,
Shape: circle,
Node: report.MakeNode().WithAdjacent(ServerHostRenderedID),
EdgeMetadata: report.EdgeMetadata{},
},
@@ -325,6 +358,7 @@ var (
ID: render.TheInternetID,
LabelMajor: render.TheInternetMajor,
Pseudo: true,
Shape: cloud,
Node: report.MakeNode().WithAdjacent(ServerHostRenderedID),
EdgeMetadata: report.EdgeMetadata{},
},
@@ -340,6 +374,7 @@ var (
LabelMinor: "1 container",
Rank: "ping/pong-a",
Pseudo: false,
Shape: pentagon,
Children: report.MakeNodeSet(
fixture.Report.Process.Nodes[fixture.ClientProcess1NodeID],
fixture.Report.Process.Nodes[fixture.ClientProcess2NodeID],
@@ -359,6 +394,7 @@ var (
LabelMinor: "1 container",
Rank: "ping/pong-b",
Pseudo: false,
Shape: pentagon,
Children: report.MakeNodeSet(
fixture.Report.Process.Nodes[fixture.ServerProcessNodeID],
fixture.Report.Container.Nodes[fixture.ServerContainerNodeID],
@@ -377,6 +413,8 @@ var (
LabelMinor: fixture.ServerHostName,
Rank: "",
Pseudo: true,
Shape: square,
Stack: true,
Children: report.MakeNodeSet(
fixture.Report.Process.Nodes[fixture.NonContainerProcessNodeID],
),
@@ -387,6 +425,7 @@ var (
ID: render.TheInternetID,
LabelMajor: render.TheInternetMajor,
Pseudo: true,
Shape: cloud,
Node: report.MakeNode().WithAdjacent(ServerPodRenderedID),
EdgeMetadata: report.EdgeMetadata{
EgressPacketCount: newu64(60),
@@ -404,6 +443,8 @@ var (
LabelMinor: "2 pods",
Rank: fixture.ServiceID,
Pseudo: false,
Shape: pentagon,
Stack: true,
Children: report.MakeNodeSet(
fixture.Report.Process.Nodes[fixture.ClientProcess1NodeID],
fixture.Report.Process.Nodes[fixture.ClientProcess2NodeID],
@@ -429,6 +470,8 @@ var (
LabelMinor: fixture.ServerHostName,
Rank: "",
Pseudo: true,
Shape: square,
Stack: true,
Children: report.MakeNodeSet(
fixture.Report.Process.Nodes[fixture.NonContainerProcessNodeID],
),
@@ -439,6 +482,7 @@ var (
ID: render.TheInternetID,
LabelMajor: render.TheInternetMajor,
Pseudo: true,
Shape: cloud,
Node: report.MakeNode().WithAdjacent(ServiceRenderedID),
EdgeMetadata: report.EdgeMetadata{
EgressPacketCount: newu64(60),

View File

@@ -39,6 +39,12 @@ const (
// If the output is empty, the node shall be omitted from the rendered topology.
type MapFunc func(RenderableNode, report.Networks) RenderableNodes
func theInternetNode(m RenderableNode) RenderableNode {
r := newDerivedPseudoNode(TheInternetID, TheInternetMajor, m)
r.Shape = Cloud
return r
}
// MapEndpointIdentity maps an endpoint topology node to a single endpoint
// renderable node. As it is only ever run on endpoint topology nodes, we
// expect that certain keys are present.
@@ -64,7 +70,7 @@ func MapEndpointIdentity(m RenderableNode, local report.Networks) RenderableNode
// If the dstNodeAddr is not in a network local to this report, we emit an
// internet node
if ip := net.ParseIP(addr); ip != nil && !local.Contains(ip) {
return RenderableNodes{TheInternetID: newDerivedPseudoNode(TheInternetID, TheInternetMajor, m)}
return RenderableNodes{TheInternetID: theInternetNode(m)}
}
// We are a 'client' pseudo node if the port is in the ephemeral port range.
@@ -117,7 +123,9 @@ func MapProcessIdentity(m RenderableNode, _ report.Networks) RenderableNodes {
rank, _ = m.Latest.Lookup(process.Name)
)
return RenderableNodes{id: NewRenderableNodeWith(id, major, minor, rank, m)}
node := NewRenderableNodeWith(id, major, minor, rank, m)
node.Shape = Square
return RenderableNodes{id: node}
}
// MapContainerIdentity maps a container topology node to a container
@@ -138,6 +146,7 @@ func MapContainerIdentity(m RenderableNode, _ report.Networks) RenderableNodes {
node := NewRenderableNodeWith(id, major, minor, rank, m)
node.ControlNode = m.ID
node.Shape = Hexagon
return RenderableNodes{id: node}
}
@@ -180,7 +189,10 @@ func MapContainerImageIdentity(m RenderableNode, _ report.Networks) RenderableNo
rank = imageID
)
return RenderableNodes{id: NewRenderableNodeWith(id, major, "", rank, m)}
node := NewRenderableNodeWith(id, major, "", rank, m)
node.Shape = Hexagon
node.Stack = true
return RenderableNodes{id: node}
}
// MapPodIdentity maps a pod topology node to pod renderable node. As it is
@@ -198,7 +210,9 @@ func MapPodIdentity(m RenderableNode, _ report.Networks) RenderableNodes {
rank, _ = m.Latest.Lookup(kubernetes.PodID)
)
return RenderableNodes{id: NewRenderableNodeWith(id, major, "", rank, m)}
node := NewRenderableNodeWith(id, major, "", rank, m)
node.Shape = Pentagon
return RenderableNodes{id: node}
}
// MapServiceIdentity maps a service topology node to service renderable node. As it is
@@ -216,7 +230,10 @@ func MapServiceIdentity(m RenderableNode, _ report.Networks) RenderableNodes {
rank, _ = m.Latest.Lookup(kubernetes.ServiceID)
)
return RenderableNodes{id: NewRenderableNodeWith(id, major, "", rank, m)}
node := NewRenderableNodeWith(id, major, "", rank, m)
node.Shape = Pentagon
node.Stack = true
return RenderableNodes{id: node}
}
// MapAddressIdentity maps an address topology node to an address renderable
@@ -242,7 +259,7 @@ func MapAddressIdentity(m RenderableNode, local report.Networks) RenderableNodes
// If the addr is not in a network local to this report, we emit an
// internet node
if !local.Contains(net.ParseIP(addr)) {
return RenderableNodes{TheInternetID: newDerivedPseudoNode(TheInternetID, TheInternetMajor, m)}
return RenderableNodes{TheInternetID: theInternetNode(m)}
}
// Otherwise generate a pseudo node for every
@@ -281,7 +298,9 @@ func MapHostIdentity(m RenderableNode, _ report.Networks) RenderableNodes {
major = hostname
}
return RenderableNodes{id: NewRenderableNodeWith(id, major, minor, rank, m)}
node := NewRenderableNodeWith(id, major, minor, rank, m)
node.Shape = Circle
return RenderableNodes{id: node}
}
// MapEndpoint2IP maps endpoint nodes to their IP address, for joining
@@ -299,7 +318,7 @@ func MapEndpoint2IP(m RenderableNode, local report.Networks) RenderableNodes {
return RenderableNodes{}
}
if ip := net.ParseIP(addr); ip != nil && !local.Contains(ip) {
return RenderableNodes{TheInternetID: newDerivedPseudoNode(TheInternetID, TheInternetMajor, m)}
return RenderableNodes{TheInternetID: theInternetNode(m)}
}
// We don't always know what port a container is listening on, and
@@ -376,8 +395,9 @@ func MapIP2Container(n RenderableNode, _ report.Networks) RenderableNodes {
}
id := MakeContainerID(containerID)
return RenderableNodes{id: NewDerivedNode(id, n.WithParents(report.EmptySets))}
node := NewDerivedNode(id, n.WithParents(report.EmptySets))
node.Shape = Hexagon
return RenderableNodes{id: node}
}
// MapEndpoint2Process maps endpoint RenderableNodes to process
@@ -402,7 +422,9 @@ func MapEndpoint2Process(n RenderableNode, _ report.Networks) RenderableNodes {
}
id := MakeProcessID(report.ExtractHostID(n.Node), pid)
return RenderableNodes{id: NewDerivedNode(id, n.WithParents(report.EmptySets))}
node := NewDerivedNode(id, n.WithParents(report.EmptySets))
node.Shape = Square
return RenderableNodes{id: node}
}
// MapProcess2Container maps process RenderableNodes to container
@@ -440,12 +462,15 @@ func MapProcess2Container(n RenderableNode, _ report.Networks) RenderableNodes {
if containerID, ok := n.Node.Latest.Lookup(docker.ContainerID); ok {
id = MakeContainerID(containerID)
node = NewDerivedNode(id, n)
node.Shape = Hexagon
} else {
nCopy := n.Copy()
nCopy.Node = nCopy.Node.WithID("").WithTopology("") // Wipe the ID so it cannot be rendered.
id = MakePseudoNodeID(UncontainedID, hostID)
node = newDerivedPseudoNode(id, UncontainedMajor, nCopy)
node.LabelMinor = hostID
node.Shape = Square
node.Stack = true
}
node.Children = node.Children.Add(n.Node)
@@ -475,6 +500,8 @@ func MapProcess2Name(n RenderableNode, _ report.Networks) RenderableNodes {
node.Node.Topology = "process_name"
node.Node.ID = name
node.Children = node.Children.Add(n.Node)
node.Shape = Square
node.Stack = true
return RenderableNodes{name: node}
}
@@ -529,6 +556,8 @@ func MapContainer2ContainerImage(n RenderableNode, _ report.Networks) Renderable
result.Node.Topology = "container_image"
result.Node.ID = report.MakeContainerImageNodeID(imageID)
result.Shape = Hexagon
result.Stack = true
return RenderableNodes{id: result}
}
@@ -561,6 +590,8 @@ func MapPod2Service(n RenderableNode, _ report.Networks) RenderableNodes {
n := NewDerivedNode(id, n.WithParents(report.EmptySets))
n.Node.Counters = n.Node.Counters.Add(podsKey, 1)
n.Children = n.Children.Add(n.Node)
n.Shape = Pentagon
n.Stack = true
result[id] = n
}
return result
@@ -600,6 +631,8 @@ func MapContainerImage2Name(n RenderableNode, _ report.Networks) RenderableNodes
node.LabelMajor = name
node.Rank = name
node.Node = n.Node.Copy() // Propagate NMD for container counting.
node.Shape = Hexagon
node.Stack = true
return RenderableNodes{id: node}
}
@@ -624,6 +657,7 @@ func MapX2Host(n RenderableNode, _ report.Networks) RenderableNodes {
id := MakeHostID(report.ExtractHostID(n.Node))
result := NewDerivedNode(id, n.WithParents(report.EmptySets))
result.Children = result.Children.Add(n.Node)
result.Shape = Circle
return RenderableNodes{id: result}
}
@@ -669,7 +703,7 @@ func MapContainer2Pod(n RenderableNode, _ report.Networks) RenderableNodes {
}
result.Children = result.Children.Add(n.Node)
result.Shape = Pentagon
return RenderableNodes{id: result}
}
@@ -693,12 +727,11 @@ func MapContainer2Hostname(n RenderableNode, _ report.Networks) RenderableNodes
// Add container id key to the counters, which will later be counted to produce the minor label
result.Counters = result.Counters.Add(ContainersKey, 1)
result.Node.Topology = "container_hostname"
result.Node.ID = id
result.Children = result.Children.Add(n.Node)
result.Shape = Hexagon
result.Stack = true
return RenderableNodes{id: result}
}

View File

@@ -15,11 +15,22 @@ type RenderableNode struct {
Pseudo bool `json:"pseudo,omitempty"` // sort-of a placeholder node, for rendering purposes
Children report.NodeSet `json:"children,omitempty"` // Nodes which have been grouped into this one
ControlNode string `json:"-"` // ID of node from which to show the controls in the UI
Shape string `json:"shape"` // Shape node should be rendered as
Stack bool `json:"stack"` // Should UI render this node as a stack?
report.EdgeMetadata `json:"metadata"` // Numeric sums
report.Node
}
// Shapes that are allowed
const (
Circle = "circle"
Square = "square"
Pentagon = "pentagon"
Hexagon = "hexagon"
Cloud = "cloud"
)
// NewRenderableNode makes a new RenderableNode
func NewRenderableNode(id string) RenderableNode {
return RenderableNode{
@@ -30,6 +41,7 @@ func NewRenderableNode(id string) RenderableNode {
Pseudo: false,
EdgeMetadata: report.EdgeMetadata{},
Node: report.MakeNode(),
Shape: Circle,
}
}
@@ -44,6 +56,7 @@ func NewRenderableNodeWith(id, major, minor, rank string, node RenderableNode) R
Children: node.Children.Copy(),
EdgeMetadata: node.EdgeMetadata.Copy(),
Node: node.Node.Copy(),
Shape: Circle,
}
}
@@ -59,6 +72,7 @@ func NewDerivedNode(id string, node RenderableNode) RenderableNode {
EdgeMetadata: node.EdgeMetadata.Copy(),
Node: node.Node.Copy(),
ControlNode: "", // Do not propagate ControlNode when making a derived node!
Shape: Circle,
}
}
@@ -72,6 +86,7 @@ func newDerivedPseudoNode(id, major string, node RenderableNode) RenderableNode
Children: node.Children.Copy(),
EdgeMetadata: node.EdgeMetadata.Copy(),
Node: node.Node.Copy(),
Shape: Circle,
}
}
@@ -113,6 +128,7 @@ func (rn RenderableNode) Merge(other RenderableNode) RenderableNode {
panic(result.ID)
}
result.Stack = result.Stack || rn.Stack
result.Children = rn.Children.Merge(other.Children)
result.EdgeMetadata = rn.EdgeMetadata.Merge(other.EdgeMetadata)
result.Node = rn.Node.Merge(other.Node)
@@ -132,6 +148,8 @@ func (rn RenderableNode) Copy() RenderableNode {
EdgeMetadata: rn.EdgeMetadata.Copy(),
Node: rn.Node.Copy(),
ControlNode: rn.ControlNode,
Shape: rn.Shape,
Stack: rn.Stack,
}
}

View File

@@ -74,6 +74,7 @@ var (
ID: render.TheInternetID,
LabelMajor: render.TheInternetMajor,
Pseudo: true,
Shape: "cloud",
Node: report.MakeNode().WithAdjacent(render.MakeContainerID(containerID)),
},
render.MakeContainerID(containerID): {
@@ -82,6 +83,7 @@ var (
LabelMinor: serverHostID,
Rank: "",
Pseudo: false,
Shape: "hexagon",
Node: report.MakeNode(),
ControlNode: containerNodeID,
},