mirror of
https://github.com/weaveworks/scope.git
synced 2026-03-03 18:20:27 +00:00
Merge pull request #355 from weaveworks/directionality
Make edge direction flow from client->server.
This commit is contained in:
@@ -136,7 +136,7 @@ func TestAPITopologyHosts(t *testing.T) {
|
||||
// Let's not unit-test the specific content of the detail tables
|
||||
}
|
||||
{
|
||||
body := getRawJSON(t, ts, fmt.Sprintf("/api/topology/hosts/%s/%s", expected.ServerHostRenderedID, expected.ClientHostRenderedID))
|
||||
body := getRawJSON(t, ts, fmt.Sprintf("/api/topology/hosts/%s/%s", expected.ClientHostRenderedID, expected.ServerHostRenderedID))
|
||||
var edge APIEdge
|
||||
if err := json.Unmarshal(body, &edge); err != nil {
|
||||
t.Fatalf("JSON parse error: %s", err)
|
||||
|
||||
@@ -77,13 +77,24 @@ func (r *Reporter) Report() (report.Report, error) {
|
||||
|
||||
func (r *Reporter) addConnection(rpt *report.Report, c *procspy.Connection) {
|
||||
var (
|
||||
localIsClient = int(c.LocalPort) > int(c.RemotePort)
|
||||
localAddressNodeID = report.MakeAddressNodeID(r.hostID, c.LocalAddress.String())
|
||||
remoteAddressNodeID = report.MakeAddressNodeID(r.hostID, c.RemoteAddress.String())
|
||||
adjecencyID = report.MakeAdjacencyID(localAddressNodeID)
|
||||
edgeID = report.MakeEdgeID(localAddressNodeID, remoteAddressNodeID)
|
||||
adjacencyID = ""
|
||||
edgeID = ""
|
||||
)
|
||||
|
||||
rpt.Address.Adjacency[adjecencyID] = rpt.Address.Adjacency[adjecencyID].Add(remoteAddressNodeID)
|
||||
if localIsClient {
|
||||
adjacencyID = report.MakeAdjacencyID(localAddressNodeID)
|
||||
rpt.Address.Adjacency[adjacencyID] = rpt.Address.Adjacency[adjacencyID].Add(remoteAddressNodeID)
|
||||
|
||||
edgeID = report.MakeEdgeID(localAddressNodeID, remoteAddressNodeID)
|
||||
} else {
|
||||
adjacencyID = report.MakeAdjacencyID(remoteAddressNodeID)
|
||||
rpt.Address.Adjacency[adjacencyID] = rpt.Address.Adjacency[adjacencyID].Add(localAddressNodeID)
|
||||
|
||||
edgeID = report.MakeEdgeID(remoteAddressNodeID, localAddressNodeID)
|
||||
}
|
||||
|
||||
if _, ok := rpt.Address.NodeMetadatas[localAddressNodeID]; !ok {
|
||||
rpt.Address.NodeMetadatas[localAddressNodeID] = report.MakeNodeMetadataWith(map[string]string{
|
||||
@@ -98,11 +109,21 @@ func (r *Reporter) addConnection(rpt *report.Report, c *procspy.Connection) {
|
||||
var (
|
||||
localEndpointNodeID = report.MakeEndpointNodeID(r.hostID, c.LocalAddress.String(), strconv.Itoa(int(c.LocalPort)))
|
||||
remoteEndpointNodeID = report.MakeEndpointNodeID(r.hostID, c.RemoteAddress.String(), strconv.Itoa(int(c.RemotePort)))
|
||||
adjecencyID = report.MakeAdjacencyID(localEndpointNodeID)
|
||||
edgeID = report.MakeEdgeID(localEndpointNodeID, remoteEndpointNodeID)
|
||||
adjacencyID = ""
|
||||
edgeID = ""
|
||||
)
|
||||
|
||||
rpt.Endpoint.Adjacency[adjecencyID] = rpt.Endpoint.Adjacency[adjecencyID].Add(remoteEndpointNodeID)
|
||||
if localIsClient {
|
||||
adjacencyID = report.MakeAdjacencyID(localEndpointNodeID)
|
||||
rpt.Endpoint.Adjacency[adjacencyID] = rpt.Endpoint.Adjacency[adjacencyID].Add(remoteEndpointNodeID)
|
||||
|
||||
edgeID = report.MakeEdgeID(localEndpointNodeID, remoteEndpointNodeID)
|
||||
} else {
|
||||
adjacencyID = report.MakeAdjacencyID(remoteEndpointNodeID)
|
||||
rpt.Endpoint.Adjacency[adjacencyID] = rpt.Endpoint.Adjacency[adjacencyID].Add(localEndpointNodeID)
|
||||
|
||||
edgeID = report.MakeEdgeID(remoteEndpointNodeID, localEndpointNodeID)
|
||||
}
|
||||
|
||||
if _, ok := rpt.Endpoint.NodeMetadatas[localEndpointNodeID]; !ok {
|
||||
// First hit establishes NodeMetadata for scoped local address + port
|
||||
|
||||
@@ -85,14 +85,14 @@ func TestSpyNoProcesses(t *testing.T) {
|
||||
var (
|
||||
scopedLocal = report.MakeAddressNodeID(nodeID, fixLocalAddress.String())
|
||||
scopedRemote = report.MakeAddressNodeID(nodeID, fixRemoteAddress.String())
|
||||
localKey = report.MakeAdjacencyID(scopedLocal)
|
||||
remoteKey = report.MakeAdjacencyID(scopedRemote)
|
||||
)
|
||||
|
||||
if want, have := 1, len(r.Address.Adjacency[localKey]); want != have {
|
||||
if want, have := 1, len(r.Address.Adjacency[remoteKey]); want != have {
|
||||
t.Fatalf("want %d, have %d", want, have)
|
||||
}
|
||||
|
||||
if want, have := scopedRemote, r.Address.Adjacency[localKey][0]; want != have {
|
||||
if want, have := scopedLocal, r.Address.Adjacency[remoteKey][0]; want != have {
|
||||
t.Fatalf("want %q, have %q", want, have)
|
||||
}
|
||||
|
||||
@@ -116,14 +116,14 @@ func TestSpyWithProcesses(t *testing.T) {
|
||||
var (
|
||||
scopedLocal = report.MakeEndpointNodeID(nodeID, fixLocalAddress.String(), strconv.Itoa(int(fixLocalPort)))
|
||||
scopedRemote = report.MakeEndpointNodeID(nodeID, fixRemoteAddress.String(), strconv.Itoa(int(fixRemotePort)))
|
||||
localKey = report.MakeAdjacencyID(scopedLocal)
|
||||
remoteKey = report.MakeAdjacencyID(scopedRemote)
|
||||
)
|
||||
|
||||
if want, have := 1, len(r.Endpoint.Adjacency[localKey]); want != have {
|
||||
if want, have := 1, len(r.Endpoint.Adjacency[remoteKey]); want != have {
|
||||
t.Fatalf("want %d, have %d", want, have)
|
||||
}
|
||||
|
||||
if want, have := scopedRemote, r.Endpoint.Adjacency[localKey][0]; want != have {
|
||||
if want, have := scopedLocal, r.Endpoint.Adjacency[remoteKey][0]; want != have {
|
||||
t.Fatalf("want %q, have %q", want, have)
|
||||
}
|
||||
|
||||
|
||||
@@ -48,6 +48,23 @@ type Row struct {
|
||||
ValueMinor string `json:"value_minor,omitempty"` // e.g. KB/s
|
||||
}
|
||||
|
||||
type rows []Row
|
||||
|
||||
func (r rows) Len() int { return len(r) }
|
||||
func (r rows) Swap(i, j int) { r[i], r[j] = r[j], r[i] }
|
||||
func (r rows) Less(i, j int) bool {
|
||||
switch {
|
||||
case r[i].Key != r[j].Key:
|
||||
return r[i].Key < r[j].Key
|
||||
|
||||
case r[i].ValueMajor != r[j].ValueMajor:
|
||||
return r[i].ValueMajor < r[j].ValueMajor
|
||||
|
||||
default:
|
||||
return r[i].ValueMinor < r[j].ValueMinor
|
||||
}
|
||||
}
|
||||
|
||||
type tables []Table
|
||||
|
||||
func (t tables) Len() int { return len(t) }
|
||||
@@ -118,6 +135,7 @@ func MakeDetailedNode(r report.Report, n RenderableNode) DetailedNode {
|
||||
}
|
||||
}
|
||||
if len(connections) > 0 {
|
||||
sort.Sort(rows(connections))
|
||||
tables = append(tables, connectionDetailsTable(connections))
|
||||
}
|
||||
|
||||
@@ -166,15 +184,38 @@ func connectionDetailsRows(topology report.Topology, originID string) []Row {
|
||||
if !ok {
|
||||
return rows
|
||||
}
|
||||
adjacencies := topology.Adjacency[report.MakeAdjacencyID(originID)]
|
||||
sort.Strings(adjacencies)
|
||||
for _, nodeID := range adjacencies {
|
||||
if remote, ok := labeler(nodeID); ok {
|
||||
rows = append(rows, Row{
|
||||
Key: local,
|
||||
ValueMajor: remote,
|
||||
})
|
||||
// Firstly, collection outgoing connections from this node.
|
||||
originAdjID := report.MakeAdjacencyID(originID)
|
||||
for _, serverNodeID := range topology.Adjacency[originAdjID] {
|
||||
remote, ok := labeler(serverNodeID)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
rows = append(rows, Row{
|
||||
Key: local,
|
||||
ValueMajor: remote,
|
||||
})
|
||||
}
|
||||
// Next, scan the topology for incoming connections to this node.
|
||||
for clientAdjID, serverNodeIDs := range topology.Adjacency {
|
||||
if clientAdjID == originAdjID {
|
||||
continue
|
||||
}
|
||||
if !serverNodeIDs.Contains(originID) {
|
||||
continue
|
||||
}
|
||||
clientNodeID, ok := report.ParseAdjacencyID(clientAdjID)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
remote, ok := labeler(clientNodeID)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
rows = append(rows, Row{
|
||||
Key: remote,
|
||||
ValueMajor: local,
|
||||
})
|
||||
}
|
||||
return rows
|
||||
}
|
||||
@@ -183,7 +224,7 @@ func connectionDetailsTable(connectionRows []Row) Table {
|
||||
return Table{
|
||||
Title: "Connection Details",
|
||||
Numeric: false,
|
||||
Rows: append([]Row{{Key: "Local", ValueMajor: "Remote"}}, connectionRows...),
|
||||
Rows: append([]Row{{Key: "Client", ValueMajor: "Server"}}, connectionRows...),
|
||||
Rank: endpointRank,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,8 +94,8 @@ func TestMakeDetailedHostNode(t *testing.T) {
|
||||
Rank: 0,
|
||||
Rows: []render.Row{
|
||||
{
|
||||
Key: "Local",
|
||||
ValueMajor: "Remote",
|
||||
Key: "Client",
|
||||
ValueMajor: "Server",
|
||||
ValueMinor: "",
|
||||
},
|
||||
{
|
||||
@@ -126,8 +126,8 @@ func TestMakeDetailedContainerNode(t *testing.T) {
|
||||
Numeric: true,
|
||||
Rank: 100,
|
||||
Rows: []render.Row{
|
||||
{"Egress packet rate", "75", "packets/sec"},
|
||||
{"Egress byte rate", "750", "Bps"},
|
||||
{"Egress packet rate", "105", "packets/sec"},
|
||||
{"Egress byte rate", "1.0", "KBps"},
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -163,35 +163,35 @@ func TestMakeDetailedContainerNode(t *testing.T) {
|
||||
Title: "Connection Details",
|
||||
Numeric: false,
|
||||
Rows: []render.Row{
|
||||
{"Local", "Remote", ""},
|
||||
{"Client", "Server", ""},
|
||||
{
|
||||
fmt.Sprintf("%s:%s", test.ServerIP, test.ServerPort),
|
||||
fmt.Sprintf("%s:%s", test.UnknownClient1IP, test.ClientPort54010),
|
||||
fmt.Sprintf("%s:%s", test.ServerIP, test.ServerPort),
|
||||
"",
|
||||
},
|
||||
{
|
||||
fmt.Sprintf("%s:%s", test.ServerIP, test.ServerPort),
|
||||
fmt.Sprintf("%s:%s", test.UnknownClient1IP, test.ClientPort54020),
|
||||
fmt.Sprintf("%s:%s", test.ServerIP, test.ServerPort),
|
||||
"",
|
||||
},
|
||||
{
|
||||
fmt.Sprintf("%s:%s", test.ServerIP, test.ServerPort),
|
||||
fmt.Sprintf("%s:%s", test.UnknownClient3IP, test.ClientPort54020),
|
||||
fmt.Sprintf("%s:%s", test.ServerIP, test.ServerPort),
|
||||
"",
|
||||
},
|
||||
{
|
||||
fmt.Sprintf("%s:%s", test.ServerIP, test.ServerPort),
|
||||
fmt.Sprintf("%s:%s", test.ClientIP, test.ClientPort54001),
|
||||
fmt.Sprintf("%s:%s", test.ServerIP, test.ServerPort),
|
||||
"",
|
||||
},
|
||||
{
|
||||
fmt.Sprintf("%s:%s", test.ServerIP, test.ServerPort),
|
||||
fmt.Sprintf("%s:%s", test.ClientIP, test.ClientPort54002),
|
||||
fmt.Sprintf("%s:%s", test.ServerIP, test.ServerPort),
|
||||
"",
|
||||
},
|
||||
{
|
||||
fmt.Sprintf("%s:%s", test.ServerIP, test.ServerPort),
|
||||
fmt.Sprintf("%s:%s", test.RandomClientIP, test.ClientPort12345),
|
||||
fmt.Sprintf("%s:%s", test.ServerIP, test.ServerPort),
|
||||
"",
|
||||
},
|
||||
},
|
||||
|
||||
@@ -13,28 +13,45 @@ var (
|
||||
uncontainedServerID = render.MakePseudoNodeID(render.UncontainedID, test.ServerHostName)
|
||||
unknownPseudoNode1ID = render.MakePseudoNodeID("10.10.10.10", test.ServerIP, "80")
|
||||
unknownPseudoNode2ID = render.MakePseudoNodeID("10.10.10.11", test.ServerIP, "80")
|
||||
unknownPseudoNode1 = render.RenderableNode{
|
||||
ID: unknownPseudoNode1ID,
|
||||
LabelMajor: "10.10.10.10",
|
||||
Pseudo: true,
|
||||
NodeMetadata: report.MakeNodeMetadata(),
|
||||
EdgeMetadata: report.EdgeMetadata{},
|
||||
unknownPseudoNode1 = func(adjacency report.IDList) render.RenderableNode {
|
||||
return render.RenderableNode{
|
||||
ID: unknownPseudoNode1ID,
|
||||
LabelMajor: "10.10.10.10",
|
||||
Pseudo: true,
|
||||
NodeMetadata: report.MakeNodeMetadata(),
|
||||
EdgeMetadata: report.EdgeMetadata{
|
||||
EgressPacketCount: newu64(70),
|
||||
EgressByteCount: newu64(700),
|
||||
},
|
||||
Adjacency: adjacency,
|
||||
}
|
||||
}
|
||||
unknownPseudoNode2 = render.RenderableNode{
|
||||
ID: unknownPseudoNode2ID,
|
||||
LabelMajor: "10.10.10.11",
|
||||
Pseudo: true,
|
||||
NodeMetadata: report.MakeNodeMetadata(),
|
||||
EdgeMetadata: report.EdgeMetadata{},
|
||||
unknownPseudoNode2 = func(adjacency report.IDList) render.RenderableNode {
|
||||
return render.RenderableNode{
|
||||
ID: unknownPseudoNode2ID,
|
||||
LabelMajor: "10.10.10.11",
|
||||
Pseudo: true,
|
||||
NodeMetadata: report.MakeNodeMetadata(),
|
||||
EdgeMetadata: report.EdgeMetadata{
|
||||
EgressPacketCount: newu64(50),
|
||||
EgressByteCount: newu64(500),
|
||||
},
|
||||
Adjacency: adjacency,
|
||||
}
|
||||
}
|
||||
theInternetNode = render.RenderableNode{
|
||||
ID: render.TheInternetID,
|
||||
LabelMajor: render.TheInternetMajor,
|
||||
Pseudo: true,
|
||||
NodeMetadata: report.MakeNodeMetadata(),
|
||||
EdgeMetadata: report.EdgeMetadata{},
|
||||
theInternetNode = func(adjacency report.IDList) render.RenderableNode {
|
||||
return render.RenderableNode{
|
||||
ID: render.TheInternetID,
|
||||
LabelMajor: render.TheInternetMajor,
|
||||
Pseudo: true,
|
||||
NodeMetadata: report.MakeNodeMetadata(),
|
||||
EdgeMetadata: report.EdgeMetadata{
|
||||
EgressPacketCount: newu64(60),
|
||||
EgressByteCount: newu64(600),
|
||||
},
|
||||
Adjacency: adjacency,
|
||||
}
|
||||
}
|
||||
|
||||
ClientProcess1ID = render.MakeProcessID(test.ClientHostID, test.Client1PID)
|
||||
ClientProcess2ID = render.MakeProcessID(test.ClientHostID, test.Client2PID)
|
||||
ServerProcessID = render.MakeProcessID(test.ServerHostID, test.ServerPID)
|
||||
@@ -83,13 +100,7 @@ var (
|
||||
LabelMinor: fmt.Sprintf("%s (%s)", test.ServerHostID, test.ServerPID),
|
||||
Rank: test.ServerComm,
|
||||
Pseudo: false,
|
||||
Adjacency: report.MakeIDList(
|
||||
ClientProcess1ID,
|
||||
ClientProcess2ID,
|
||||
unknownPseudoNode1ID,
|
||||
unknownPseudoNode2ID,
|
||||
render.TheInternetID,
|
||||
),
|
||||
Adjacency: report.MakeIDList(),
|
||||
Origins: report.MakeIDList(
|
||||
test.Server80NodeID,
|
||||
test.ServerProcessNodeID,
|
||||
@@ -97,8 +108,8 @@ var (
|
||||
),
|
||||
NodeMetadata: report.MakeNodeMetadata(),
|
||||
EdgeMetadata: report.EdgeMetadata{
|
||||
EgressPacketCount: newu64(150),
|
||||
EgressByteCount: newu64(1500),
|
||||
EgressPacketCount: newu64(210),
|
||||
EgressByteCount: newu64(2100),
|
||||
},
|
||||
},
|
||||
nonContainerProcessID: {
|
||||
@@ -115,9 +126,9 @@ var (
|
||||
NodeMetadata: report.MakeNodeMetadata(),
|
||||
EdgeMetadata: report.EdgeMetadata{},
|
||||
},
|
||||
unknownPseudoNode1ID: unknownPseudoNode1,
|
||||
unknownPseudoNode2ID: unknownPseudoNode2,
|
||||
render.TheInternetID: theInternetNode,
|
||||
unknownPseudoNode1ID: unknownPseudoNode1(report.MakeIDList(ServerProcessID)),
|
||||
unknownPseudoNode2ID: unknownPseudoNode2(report.MakeIDList(ServerProcessID)),
|
||||
render.TheInternetID: theInternetNode(report.MakeIDList(ServerProcessID)),
|
||||
}
|
||||
|
||||
RenderedProcessNames = render.RenderableNodes{
|
||||
@@ -147,12 +158,7 @@ var (
|
||||
LabelMinor: "",
|
||||
Rank: "apache",
|
||||
Pseudo: false,
|
||||
Adjacency: report.MakeIDList(
|
||||
"curl",
|
||||
unknownPseudoNode1ID,
|
||||
unknownPseudoNode2ID,
|
||||
render.TheInternetID,
|
||||
),
|
||||
Adjacency: report.MakeIDList(),
|
||||
Origins: report.MakeIDList(
|
||||
test.Server80NodeID,
|
||||
test.ServerProcessNodeID,
|
||||
@@ -160,8 +166,8 @@ var (
|
||||
),
|
||||
NodeMetadata: report.MakeNodeMetadata(),
|
||||
EdgeMetadata: report.EdgeMetadata{
|
||||
EgressPacketCount: newu64(150),
|
||||
EgressByteCount: newu64(1500),
|
||||
EgressPacketCount: newu64(210),
|
||||
EgressByteCount: newu64(2100),
|
||||
},
|
||||
},
|
||||
"bash": {
|
||||
@@ -177,9 +183,9 @@ var (
|
||||
NodeMetadata: report.MakeNodeMetadata(),
|
||||
EdgeMetadata: report.EdgeMetadata{},
|
||||
},
|
||||
unknownPseudoNode1ID: unknownPseudoNode1,
|
||||
unknownPseudoNode2ID: unknownPseudoNode2,
|
||||
render.TheInternetID: theInternetNode,
|
||||
unknownPseudoNode1ID: unknownPseudoNode1(report.MakeIDList("apache")),
|
||||
unknownPseudoNode2ID: unknownPseudoNode2(report.MakeIDList("apache")),
|
||||
render.TheInternetID: theInternetNode(report.MakeIDList("apache")),
|
||||
}
|
||||
|
||||
RenderedContainers = render.RenderableNodes{
|
||||
@@ -210,7 +216,7 @@ var (
|
||||
LabelMinor: test.ServerHostName,
|
||||
Rank: test.ServerContainerImageID,
|
||||
Pseudo: false,
|
||||
Adjacency: report.MakeIDList(test.ClientContainerID, render.TheInternetID),
|
||||
Adjacency: report.MakeIDList(),
|
||||
Origins: report.MakeIDList(
|
||||
test.ServerContainerNodeID,
|
||||
test.Server80NodeID,
|
||||
@@ -219,8 +225,8 @@ var (
|
||||
),
|
||||
NodeMetadata: report.MakeNodeMetadata(),
|
||||
EdgeMetadata: report.EdgeMetadata{
|
||||
EgressPacketCount: newu64(150),
|
||||
EgressByteCount: newu64(1500),
|
||||
EgressPacketCount: newu64(210),
|
||||
EgressByteCount: newu64(2100),
|
||||
},
|
||||
},
|
||||
uncontainedServerID: {
|
||||
@@ -236,7 +242,7 @@ var (
|
||||
NodeMetadata: report.MakeNodeMetadata(),
|
||||
EdgeMetadata: report.EdgeMetadata{},
|
||||
},
|
||||
render.TheInternetID: theInternetNode,
|
||||
render.TheInternetID: theInternetNode(report.MakeIDList(test.ServerContainerID)),
|
||||
}
|
||||
|
||||
RenderedContainerImages = render.RenderableNodes{
|
||||
@@ -268,7 +274,7 @@ var (
|
||||
LabelMinor: "",
|
||||
Rank: test.ServerContainerImageName,
|
||||
Pseudo: false,
|
||||
Adjacency: report.MakeIDList(test.ClientContainerImageName, render.TheInternetID),
|
||||
Adjacency: report.MakeIDList(),
|
||||
Origins: report.MakeIDList(
|
||||
test.ServerContainerImageNodeID,
|
||||
test.ServerContainerNodeID,
|
||||
@@ -277,8 +283,8 @@ var (
|
||||
test.ServerHostNodeID),
|
||||
NodeMetadata: report.MakeNodeMetadata(),
|
||||
EdgeMetadata: report.EdgeMetadata{
|
||||
EgressPacketCount: newu64(150),
|
||||
EgressByteCount: newu64(1500),
|
||||
EgressPacketCount: newu64(210),
|
||||
EgressByteCount: newu64(2100),
|
||||
},
|
||||
},
|
||||
uncontainedServerID: {
|
||||
@@ -294,7 +300,7 @@ var (
|
||||
NodeMetadata: report.MakeNodeMetadata(),
|
||||
EdgeMetadata: report.EdgeMetadata{},
|
||||
},
|
||||
render.TheInternetID: theInternetNode,
|
||||
render.TheInternetID: theInternetNode(report.MakeIDList(test.ServerContainerImageName)),
|
||||
}
|
||||
|
||||
ServerHostRenderedID = render.MakeHostID(test.ServerHostID)
|
||||
@@ -309,7 +315,7 @@ var (
|
||||
LabelMinor: "hostname.com", // after first .
|
||||
Rank: "hostname.com",
|
||||
Pseudo: false,
|
||||
Adjacency: report.MakeIDList(ClientHostRenderedID, render.TheInternetID, pseudoHostID1, pseudoHostID2),
|
||||
Adjacency: report.MakeIDList(),
|
||||
Origins: report.MakeIDList(
|
||||
test.ServerHostNodeID,
|
||||
test.ServerAddressNodeID,
|
||||
@@ -339,6 +345,7 @@ var (
|
||||
ID: pseudoHostID1,
|
||||
LabelMajor: "10.10.10.10",
|
||||
Pseudo: true,
|
||||
Adjacency: report.MakeIDList(ServerHostRenderedID),
|
||||
NodeMetadata: report.MakeNodeMetadata(),
|
||||
EdgeMetadata: report.EdgeMetadata{},
|
||||
},
|
||||
@@ -346,10 +353,18 @@ var (
|
||||
ID: pseudoHostID2,
|
||||
LabelMajor: "10.10.10.11",
|
||||
Pseudo: true,
|
||||
Adjacency: report.MakeIDList(ServerHostRenderedID),
|
||||
NodeMetadata: report.MakeNodeMetadata(),
|
||||
EdgeMetadata: report.EdgeMetadata{},
|
||||
},
|
||||
render.TheInternetID: {
|
||||
ID: render.TheInternetID,
|
||||
LabelMajor: render.TheInternetMajor,
|
||||
Pseudo: true,
|
||||
Adjacency: report.MakeIDList(ServerHostRenderedID),
|
||||
NodeMetadata: report.MakeNodeMetadata(),
|
||||
EdgeMetadata: report.EdgeMetadata{},
|
||||
},
|
||||
render.TheInternetID: theInternetNode,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -33,11 +33,12 @@ const (
|
||||
// rendered topology.
|
||||
type LeafMapFunc func(report.NodeMetadata) (RenderableNode, bool)
|
||||
|
||||
// PseudoFunc creates RenderableNode representing pseudo nodes given the dstNodeID.
|
||||
// The srcNode renderable node is essentially from MapFunc, representing one of
|
||||
// the rendered nodes this pseudo node refers to. srcNodeID and dstNodeID are
|
||||
// node IDs prior to mapping.
|
||||
type PseudoFunc func(srcNodeID string, srcNode RenderableNode, dstNodeID string, local report.Networks) (RenderableNode, bool)
|
||||
// PseudoFunc creates RenderableNode representing pseudo nodes given the
|
||||
// srcNodeID. dstNodeID is the node id of one of the nodes this node has an
|
||||
// edge to. srcNodeID and dstNodeID are node IDs prior to mapping. srcIsClient
|
||||
// indicates the direction of the edge to dstNodeID - true indicates srcNodeID
|
||||
// is the client, false indicates dstNodeID is the server.
|
||||
type PseudoFunc func(srcNodeID, dstNodeID string, srcIsClient bool, local report.Networks) (RenderableNode, bool)
|
||||
|
||||
// MapFunc is anything which can take an arbitrary RenderableNode and
|
||||
// return another RenderableNode.
|
||||
@@ -323,29 +324,36 @@ func MapAddress2Host(n RenderableNode) (RenderableNode, bool) {
|
||||
// the report's local networks. Otherwise, the returned function will
|
||||
// produce a single pseudo node per (dst address, src address, src port).
|
||||
func GenericPseudoNode(addresser func(id string) net.IP) PseudoFunc {
|
||||
return func(src string, srcMapped RenderableNode, dst string, local report.Networks) (RenderableNode, bool) {
|
||||
// Use the addresser to extract the destination IP
|
||||
dstNodeAddr := addresser(dst)
|
||||
|
||||
return func(srcNodeID, dstNodeID string, srcIsClient bool, local report.Networks) (RenderableNode, bool) {
|
||||
// Use the addresser to extract the IP of the missing node
|
||||
srcNodeAddr := addresser(srcNodeID)
|
||||
// If the dstNodeAddr is not in a network local to this report, we emit an
|
||||
// internet node
|
||||
if !local.Contains(dstNodeAddr) {
|
||||
if !local.Contains(srcNodeAddr) {
|
||||
return newPseudoNode(TheInternetID, TheInternetMajor, ""), true
|
||||
}
|
||||
|
||||
// Otherwise, the rule for non-internet psuedo nodes; emit 1 new node for each
|
||||
// dstNodeAddr, srcNodeAddr, srcNodePort.
|
||||
srcNodeAddr, srcNodePort := trySplitAddr(src)
|
||||
if srcIsClient {
|
||||
// If the client node is missing, generate a single pseudo node for every (client ip, server ip, server port)
|
||||
serverIP, serverPort := trySplitAddr(dstNodeID)
|
||||
outputID := MakePseudoNodeID(srcNodeAddr.String(), serverIP, serverPort)
|
||||
major := srcNodeAddr.String()
|
||||
return newPseudoNode(outputID, major, ""), true
|
||||
}
|
||||
|
||||
outputID := MakePseudoNodeID(dstNodeAddr.String(), srcNodeAddr, srcNodePort)
|
||||
major := dstNodeAddr.String()
|
||||
return newPseudoNode(outputID, major, ""), true
|
||||
// Otherwise (the server node is missing), generate a pseudo node for every (server ip, server port)
|
||||
serverIP, serverPort := trySplitAddr(srcNodeID)
|
||||
outputID := MakePseudoNodeID(serverIP, serverPort)
|
||||
if serverPort != "" {
|
||||
return newPseudoNode(outputID, serverIP+":"+serverPort, ""), true
|
||||
}
|
||||
return newPseudoNode(outputID, serverIP, ""), true
|
||||
}
|
||||
}
|
||||
|
||||
// PanicPseudoNode just panics; it is for Topologies without edges
|
||||
func PanicPseudoNode(src string, srcMapped RenderableNode, dst string, local report.Networks) (RenderableNode, bool) {
|
||||
panic(dst)
|
||||
func PanicPseudoNode(src, dst string, isClient bool, local report.Networks) (RenderableNode, bool) {
|
||||
panic(src)
|
||||
}
|
||||
|
||||
// trySplitAddr is basically ParseArbitraryNodeID, since its callsites
|
||||
|
||||
@@ -177,37 +177,69 @@ func (m LeafMap) Render(rpt report.Report) RenderableNodes {
|
||||
source2mapped[nodeID] = mapped.ID
|
||||
}
|
||||
|
||||
mkPseudoNode := func(srcNodeID, dstNodeID string, srcIsClient bool) (string, bool) {
|
||||
pseudoNode, ok := m.Pseudo(srcNodeID, dstNodeID, srcIsClient, localNetworks)
|
||||
if !ok {
|
||||
return "", false
|
||||
}
|
||||
// TODO(tomwilkie): we should propagate origin nodes for pseudo nodes.
|
||||
// Not worth doing until they are selectable in the UI
|
||||
// pseudoNode.Origins = pseudoNode.Origins.Add(srcID)
|
||||
existing, ok := nodes[pseudoNode.ID]
|
||||
if ok {
|
||||
pseudoNode.Merge(existing)
|
||||
}
|
||||
|
||||
nodes[pseudoNode.ID] = pseudoNode
|
||||
source2mapped[pseudoNode.ID] = srcNodeID
|
||||
return pseudoNode.ID, true
|
||||
}
|
||||
|
||||
// Walk the graph and make connections.
|
||||
for src, dsts := range t.Adjacency {
|
||||
var (
|
||||
srcNodeID, ok = report.ParseAdjacencyID(src)
|
||||
srcRenderableID = source2mapped[srcNodeID] // must exist
|
||||
srcRenderableNode = nodes[srcRenderableID] // must exist
|
||||
)
|
||||
srcNodeID, ok := report.ParseAdjacencyID(src)
|
||||
if !ok {
|
||||
log.Printf("bad adjacency ID %q", src)
|
||||
continue
|
||||
}
|
||||
|
||||
srcRenderableID, ok := source2mapped[srcNodeID]
|
||||
if !ok {
|
||||
// One of the entries in dsts must be a non-pseudo node
|
||||
var existingDstNodeID string
|
||||
for _, dstNodeID := range dsts {
|
||||
if _, ok := source2mapped[dstNodeID]; ok {
|
||||
existingDstNodeID = dstNodeID
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
srcRenderableID, ok = mkPseudoNode(srcNodeID, existingDstNodeID, true)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
}
|
||||
srcRenderableNode := nodes[srcRenderableID]
|
||||
|
||||
for _, dstNodeID := range dsts {
|
||||
dstRenderableID, ok := source2mapped[dstNodeID]
|
||||
if !ok {
|
||||
pseudoNode, ok := m.Pseudo(srcNodeID, srcRenderableNode, dstNodeID, localNetworks)
|
||||
dstRenderableID, ok = mkPseudoNode(dstNodeID, srcNodeID, false)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
dstRenderableID = pseudoNode.ID
|
||||
nodes[dstRenderableID] = pseudoNode
|
||||
source2mapped[dstNodeID] = dstRenderableID
|
||||
}
|
||||
dstRenderableNode := nodes[dstRenderableID]
|
||||
|
||||
srcRenderableNode.Adjacency = srcRenderableNode.Adjacency.Add(dstRenderableID)
|
||||
srcRenderableNode.Origins = srcRenderableNode.Origins.Add(srcNodeID)
|
||||
edgeID := report.MakeEdgeID(srcNodeID, dstNodeID)
|
||||
if md, ok := t.EdgeMetadatas[edgeID]; ok {
|
||||
srcRenderableNode.EdgeMetadata.Merge(md)
|
||||
}
|
||||
|
||||
// We propagate edge metadata to nodes on both ends of the edges.
|
||||
// TODO we should 'reverse' one end of the edge meta data - ingress -> egress etc.
|
||||
if md, ok := t.EdgeMetadatas[report.MakeEdgeID(srcNodeID, dstNodeID)]; ok {
|
||||
srcRenderableNode.EdgeMetadata.Merge(md)
|
||||
dstRenderableNode.EdgeMetadata.Merge(md)
|
||||
nodes[dstRenderableID] = dstRenderableNode
|
||||
}
|
||||
}
|
||||
|
||||
nodes[srcRenderableID] = srcRenderableNode
|
||||
|
||||
@@ -85,8 +85,11 @@ func (t Topology) Validate() error {
|
||||
errs = append(errs, fmt.Sprintf("invalid edge ID %q", edgeID))
|
||||
continue
|
||||
}
|
||||
// For each edge, at least one of the ends must exist in nodemetadata
|
||||
if _, ok := t.NodeMetadatas[srcNodeID]; !ok {
|
||||
errs = append(errs, fmt.Sprintf("node metadata missing for source node ID %q (from edge %q)", srcNodeID, edgeID))
|
||||
if _, ok := t.NodeMetadatas[dstNodeID]; !ok {
|
||||
errs = append(errs, fmt.Sprintf("node metadatas missing for edge %q", edgeID))
|
||||
}
|
||||
}
|
||||
dstNodeIDs, ok := t.Adjacency[MakeAdjacencyID(srcNodeID)]
|
||||
if !ok {
|
||||
@@ -99,14 +102,19 @@ func (t Topology) Validate() error {
|
||||
}
|
||||
|
||||
// Check all adjancency keys has entries in NodeMetadata.
|
||||
for adjacencyID := range t.Adjacency {
|
||||
nodeID, ok := ParseAdjacencyID(adjacencyID)
|
||||
for adjacencyID, dsts := range t.Adjacency {
|
||||
srcNodeID, ok := ParseAdjacencyID(adjacencyID)
|
||||
if !ok {
|
||||
errs = append(errs, fmt.Sprintf("invalid adjacency ID %q", adjacencyID))
|
||||
continue
|
||||
}
|
||||
if _, ok := t.NodeMetadatas[nodeID]; !ok {
|
||||
errs = append(errs, fmt.Sprintf("node metadata missing for source node %q (from adjacency %q)", nodeID, adjacencyID))
|
||||
for _, dstNodeID := range dsts {
|
||||
// For each edge, at least one of the ends must exist in nodemetadata
|
||||
if _, ok := t.NodeMetadatas[srcNodeID]; !ok {
|
||||
if _, ok := t.NodeMetadatas[dstNodeID]; !ok {
|
||||
errs = append(errs, fmt.Sprintf("node metadata missing from adjacency %q -> %q", srcNodeID, dstNodeID))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -79,11 +79,12 @@ var (
|
||||
Report = report.Report{
|
||||
Endpoint: report.Topology{
|
||||
Adjacency: report.Adjacency{
|
||||
report.MakeAdjacencyID(Client54001NodeID): report.MakeIDList(Server80NodeID),
|
||||
report.MakeAdjacencyID(Client54002NodeID): report.MakeIDList(Server80NodeID),
|
||||
report.MakeAdjacencyID(Server80NodeID): report.MakeIDList(
|
||||
Client54001NodeID, Client54002NodeID, UnknownClient1NodeID, UnknownClient2NodeID,
|
||||
UnknownClient3NodeID, RandomClientNodeID),
|
||||
report.MakeAdjacencyID(Client54001NodeID): report.MakeIDList(Server80NodeID),
|
||||
report.MakeAdjacencyID(Client54002NodeID): report.MakeIDList(Server80NodeID),
|
||||
report.MakeAdjacencyID(UnknownClient1NodeID): report.MakeIDList(Server80NodeID),
|
||||
report.MakeAdjacencyID(UnknownClient2NodeID): report.MakeIDList(Server80NodeID),
|
||||
report.MakeAdjacencyID(UnknownClient3NodeID): report.MakeIDList(Server80NodeID),
|
||||
report.MakeAdjacencyID(RandomClientNodeID): report.MakeIDList(Server80NodeID),
|
||||
},
|
||||
NodeMetadatas: report.NodeMetadatas{
|
||||
// NodeMetadata is arbitrary. We're free to put only precisely what we
|
||||
@@ -117,27 +118,22 @@ var (
|
||||
EgressPacketCount: newu64(20),
|
||||
EgressByteCount: newu64(200),
|
||||
},
|
||||
|
||||
report.MakeEdgeID(Server80NodeID, Client54001NodeID): report.EdgeMetadata{
|
||||
EgressPacketCount: newu64(10),
|
||||
EgressByteCount: newu64(100),
|
||||
},
|
||||
report.MakeEdgeID(Server80NodeID, Client54002NodeID): report.EdgeMetadata{
|
||||
EgressPacketCount: newu64(20),
|
||||
EgressByteCount: newu64(200),
|
||||
},
|
||||
report.MakeEdgeID(Server80NodeID, UnknownClient1NodeID): report.EdgeMetadata{
|
||||
report.MakeEdgeID(UnknownClient1NodeID, Server80NodeID): report.EdgeMetadata{
|
||||
EgressPacketCount: newu64(30),
|
||||
EgressByteCount: newu64(300),
|
||||
},
|
||||
report.MakeEdgeID(Server80NodeID, UnknownClient2NodeID): report.EdgeMetadata{
|
||||
report.MakeEdgeID(UnknownClient2NodeID, Server80NodeID): report.EdgeMetadata{
|
||||
EgressPacketCount: newu64(40),
|
||||
EgressByteCount: newu64(400),
|
||||
},
|
||||
report.MakeEdgeID(Server80NodeID, UnknownClient3NodeID): report.EdgeMetadata{
|
||||
report.MakeEdgeID(UnknownClient3NodeID, Server80NodeID): report.EdgeMetadata{
|
||||
EgressPacketCount: newu64(50),
|
||||
EgressByteCount: newu64(500),
|
||||
},
|
||||
report.MakeEdgeID(RandomClientNodeID, Server80NodeID): report.EdgeMetadata{
|
||||
EgressPacketCount: newu64(60),
|
||||
EgressByteCount: newu64(600),
|
||||
},
|
||||
},
|
||||
},
|
||||
Process: report.Topology{
|
||||
@@ -201,9 +197,10 @@ var (
|
||||
},
|
||||
Address: report.Topology{
|
||||
Adjacency: report.Adjacency{
|
||||
report.MakeAdjacencyID(ClientAddressNodeID): report.MakeIDList(ServerAddressNodeID),
|
||||
report.MakeAdjacencyID(ServerAddressNodeID): report.MakeIDList(
|
||||
ClientAddressNodeID, UnknownAddress1NodeID, UnknownAddress2NodeID, RandomAddressNodeID), // no backlinks to unknown/random
|
||||
report.MakeAdjacencyID(ClientAddressNodeID): report.MakeIDList(ServerAddressNodeID),
|
||||
report.MakeAdjacencyID(UnknownAddress1NodeID): report.MakeIDList(ServerAddressNodeID),
|
||||
report.MakeAdjacencyID(UnknownAddress2NodeID): report.MakeIDList(ServerAddressNodeID),
|
||||
report.MakeAdjacencyID(RandomAddressNodeID): report.MakeIDList(ServerAddressNodeID),
|
||||
},
|
||||
NodeMetadatas: report.NodeMetadatas{
|
||||
ClientAddressNodeID: report.MakeNodeMetadataWith(map[string]string{
|
||||
@@ -219,9 +216,6 @@ var (
|
||||
report.MakeEdgeID(ClientAddressNodeID, ServerAddressNodeID): report.EdgeMetadata{
|
||||
MaxConnCountTCP: newu64(3),
|
||||
},
|
||||
report.MakeEdgeID(ServerAddressNodeID, ClientAddressNodeID): report.EdgeMetadata{
|
||||
MaxConnCountTCP: newu64(3),
|
||||
},
|
||||
},
|
||||
},
|
||||
Host: report.Topology{
|
||||
|
||||
Reference in New Issue
Block a user