From 23707995ea917a51cf647501caac1dcff9d06d02 Mon Sep 17 00:00:00 2001 From: Tom Wilkie Date: Fri, 16 Oct 2015 16:26:15 +0000 Subject: [PATCH] Split the internet node for incoming vs outgoing connections. --- app/api_topology_test.go | 2 +- integration/300_internet_edge_test.sh | 4 +- .../310_container_to_container_edge_test.sh | 2 +- .../320_container_edge_cross_host_2_test.sh | 2 +- integration/config.sh | 13 ++- render/expected/expected.go | 86 +++++++++---------- render/mapping.go | 35 ++++++-- render/short_lived_connections_test.go | 5 +- 8 files changed, 82 insertions(+), 67 deletions(-) diff --git a/app/api_topology_test.go b/app/api_topology_test.go index c4db880d84..4da42cd27b 100644 --- a/app/api_topology_test.go +++ b/app/api_topology_test.go @@ -173,7 +173,7 @@ func TestAPITopologyWebsocket(t *testing.T) { if err := json.Unmarshal(p, &d); err != nil { t.Fatalf("JSON parse error: %s", err) } - equals(t, 7, len(d.Add)) + equals(t, 8, len(d.Add)) equals(t, 0, len(d.Update)) equals(t, 0, len(d.Remove)) } diff --git a/integration/300_internet_edge_test.sh b/integration/300_internet_edge_test.sh index 3e5b07a1b9..0181ff8ac8 100755 --- a/integration/300_internet_edge_test.sh +++ b/integration/300_internet_edge_test.sh @@ -25,8 +25,8 @@ do_connections& wait_for_containers $HOST1 60 nginx "The Internet" has_container $HOST1 nginx -has_container $HOST1 "The Internet" -has_connection $HOST1 "The Internet" nginx +has_container_id $HOST1 'in-theinternet' +has_connection $HOST1 'in-theinternet' $(container_id $1 nginx) kill %do_connections diff --git a/integration/310_container_to_container_edge_test.sh b/integration/310_container_to_container_edge_test.sh index 1ff072a744..5dacd4be05 100755 --- a/integration/310_container_to_container_edge_test.sh +++ b/integration/310_container_to_container_edge_test.sh @@ -16,6 +16,6 @@ wait_for_containers $HOST1 60 nginx client has_container $HOST1 nginx has_container $HOST1 client -has_connection $HOST1 client nginx +has_connection $HOST1 $(container_id $HOST1 client) $(container_id $HOST1 nginx) scope_end_suite diff --git a/integration/320_container_edge_cross_host_2_test.sh b/integration/320_container_edge_cross_host_2_test.sh index b424d21e59..f153117c02 100755 --- a/integration/320_container_edge_cross_host_2_test.sh +++ b/integration/320_container_edge_cross_host_2_test.sh @@ -21,7 +21,7 @@ sleep 30 # need to allow the scopes to poll dns, resolve the other app ids, and check() { has_container $1 nginx has_container $1 client - has_connection $1 client nginx + has_connection $1 $(container_id $1 client) $(container_id $1 nginx) } check $HOST1 diff --git a/integration/config.sh b/integration/config.sh index ed083c5d75..feaa900d57 100644 --- a/integration/config.sh +++ b/integration/config.sh @@ -37,6 +37,13 @@ has_container() { assert "curl -s http://$host:4040/api/topology/containers?system=show | jq -r '[.nodes[] | select(.label_major == \"$name\")] | length'" $count } +has_container_id() { + local host=$1 + local id=$2 + local count=${3:-1} + assert "curl -s http://$host:4040/api/topology/containers?system=show | jq -r '[.nodes[] | select(.id == \"$id\")] | length'" $count +} + scope_end_suite() { end_suite for host in $HOSTS; do @@ -53,11 +60,9 @@ container_id() { # this checks we have an edge from container 1 to container 2 has_connection() { local host="$1" - local from="$2" - local to="$3" + local from_id="$2" + local to_id="$3" local timeout="${4:-60}" - local from_id=$(container_id "$host" "$from") - local to_id=$(container_id "$host" "$to") for i in $(seq $timeout); do local containers="$(curl -s http://$host:4040/api/topology/containers?system=show)" diff --git a/render/expected/expected.go b/render/expected/expected.go index fd2df18708..f598e5cab5 100644 --- a/render/expected/expected.go +++ b/render/expected/expected.go @@ -44,10 +44,11 @@ var ( ), } } - theInternetNode = func(adjacent string) render.RenderableNode { + theIncomingInternetNode = func(adjacent string) render.RenderableNode { return render.RenderableNode{ - ID: render.TheInternetID, + ID: render.IncomingInternetID, LabelMajor: render.TheInternetMajor, + LabelMinor: render.Incoming, Pseudo: true, Node: report.MakeNode().WithAdjacent(adjacent), EdgeMetadata: report.EdgeMetadata{ @@ -56,10 +57,20 @@ var ( }, Origins: report.MakeIDList( fixture.RandomClientNodeID, - fixture.GoogleEndpointNodeID, ), } } + theOutgoingInternetNode = render.RenderableNode{ + ID: render.OutgoingInternetID, + LabelMajor: render.TheInternetMajor, + LabelMinor: render.Outgoing, + Pseudo: true, + Node: report.MakeNode(), + EdgeMetadata: report.EdgeMetadata{}, + Origins: report.MakeIDList( + fixture.GoogleEndpointNodeID, + ), + } ClientProcess1ID = render.MakeProcessID(fixture.ClientHostID, fixture.Client1PID) ClientProcess2ID = render.MakeProcessID(fixture.ClientHostID, fixture.Client2PID) ServerProcessID = render.MakeProcessID(fixture.ServerHostID, fixture.ServerPID) @@ -128,12 +139,13 @@ var ( fixture.ServerHostNodeID, fixture.NonContainerNodeID, ), - Node: report.MakeNode().WithAdjacent(render.TheInternetID), + Node: report.MakeNode().WithAdjacent(render.OutgoingInternetID), EdgeMetadata: report.EdgeMetadata{}, }, - unknownPseudoNode1ID: unknownPseudoNode1(ServerProcessID), - unknownPseudoNode2ID: unknownPseudoNode2(ServerProcessID), - render.TheInternetID: theInternetNode(ServerProcessID), + unknownPseudoNode1ID: unknownPseudoNode1(ServerProcessID), + unknownPseudoNode2ID: unknownPseudoNode2(ServerProcessID), + render.IncomingInternetID: theIncomingInternetNode(ServerProcessID), + render.OutgoingInternetID: theOutgoingInternetNode, }).Prune() RenderedProcessNames = (render.RenderableNodes{ @@ -184,12 +196,13 @@ var ( fixture.ServerHostNodeID, fixture.NonContainerNodeID, ), - Node: report.MakeNode().WithAdjacent(render.TheInternetID), + Node: report.MakeNode().WithAdjacent(render.OutgoingInternetID), EdgeMetadata: report.EdgeMetadata{}, }, - unknownPseudoNode1ID: unknownPseudoNode1("apache"), - unknownPseudoNode2ID: unknownPseudoNode2("apache"), - render.TheInternetID: theInternetNode("apache"), + unknownPseudoNode1ID: unknownPseudoNode1("apache"), + unknownPseudoNode2ID: unknownPseudoNode2("apache"), + render.IncomingInternetID: theIncomingInternetNode("apache"), + render.OutgoingInternetID: theOutgoingInternetNode, }).Prune() RenderedContainers = (render.RenderableNodes{ @@ -246,10 +259,11 @@ var ( fixture.ServerHostNodeID, fixture.NonContainerNodeID, ), - Node: report.MakeNode().WithAdjacent(render.TheInternetID), + Node: report.MakeNode().WithAdjacent(render.OutgoingInternetID), EdgeMetadata: report.EdgeMetadata{}, }, - render.TheInternetID: theInternetNode(fixture.ServerContainerID), + render.IncomingInternetID: theIncomingInternetNode(fixture.ServerContainerID), + render.OutgoingInternetID: theOutgoingInternetNode, }).Prune() RenderedContainerImages = (render.RenderableNodes{ @@ -303,10 +317,11 @@ var ( fixture.NonContainerProcessNodeID, fixture.ServerHostNodeID, ), - Node: report.MakeNode().WithAdjacent(render.TheInternetID), + Node: report.MakeNode().WithAdjacent(render.OutgoingInternetID), EdgeMetadata: report.EdgeMetadata{}, }, - render.TheInternetID: theInternetNode(fixture.ServerContainerImageName), + render.IncomingInternetID: theIncomingInternetNode(fixture.ServerContainerImageName), + render.OutgoingInternetID: theOutgoingInternetNode, }).Prune() ServerHostRenderedID = render.MakeHostID(fixture.ServerHostID) @@ -361,9 +376,10 @@ var ( EdgeMetadata: report.EdgeMetadata{}, Origins: report.MakeIDList(fixture.UnknownAddress3NodeID), }, - render.TheInternetID: { - ID: render.TheInternetID, + render.IncomingInternetID: { + ID: render.IncomingInternetID, LabelMajor: render.TheInternetMajor, + LabelMinor: render.Incoming, Pseudo: true, Node: report.MakeNode().WithAdjacent(ServerHostRenderedID), EdgeMetadata: report.EdgeMetadata{}, @@ -425,23 +441,11 @@ var ( fixture.NonContainerProcessNodeID, fixture.NonContainerNodeID, ), - Node: report.MakeNode().WithAdjacent(render.TheInternetID), + Node: report.MakeNode().WithAdjacent(render.OutgoingInternetID), EdgeMetadata: report.EdgeMetadata{}, }, - render.TheInternetID: { - ID: render.TheInternetID, - LabelMajor: render.TheInternetMajor, - Pseudo: true, - Node: report.MakeNode().WithAdjacent("ping/pong-b"), - EdgeMetadata: report.EdgeMetadata{ - EgressPacketCount: newu64(60), - EgressByteCount: newu64(600), - }, - Origins: report.MakeIDList( - fixture.RandomClientNodeID, - fixture.GoogleEndpointNodeID, - ), - }, + render.IncomingInternetID: theIncomingInternetNode("ping/pong-b"), + render.OutgoingInternetID: theOutgoingInternetNode, }).Prune() RenderedPodServices = (render.RenderableNodes{ @@ -487,23 +491,11 @@ var ( fixture.NonContainerProcessNodeID, fixture.NonContainerNodeID, ), - Node: report.MakeNode().WithAdjacent(render.TheInternetID), + Node: report.MakeNode().WithAdjacent(render.OutgoingInternetID), EdgeMetadata: report.EdgeMetadata{}, }, - render.TheInternetID: { - ID: render.TheInternetID, - LabelMajor: render.TheInternetMajor, - Pseudo: true, - Node: report.MakeNode().WithAdjacent(fixture.ServiceID), - EdgeMetadata: report.EdgeMetadata{ - EgressPacketCount: newu64(60), - EgressByteCount: newu64(600), - }, - Origins: report.MakeIDList( - fixture.RandomClientNodeID, - fixture.GoogleEndpointNodeID, - ), - }, + render.IncomingInternetID: theIncomingInternetNode(fixture.ServiceID), + render.OutgoingInternetID: theOutgoingInternetNode, }).Prune() ) diff --git a/render/mapping.go b/render/mapping.go index 53a07d2c93..8cc143d907 100644 --- a/render/mapping.go +++ b/render/mapping.go @@ -20,8 +20,12 @@ const ( UncontainedID = "uncontained" UncontainedMajor = "Uncontained" - TheInternetID = "theinternet" - TheInternetMajor = "The Internet" + TheInternetID = "theinternet" + IncomingInternetID = "in-" + TheInternetID + OutgoingInternetID = "out-" + TheInternetID + TheInternetMajor = "The Internet" + Incoming = "Incoming" + Outgoing = "Outgoing" containersKey = "containers" podsKey = "pods" @@ -37,6 +41,19 @@ const ( // If the output is empty, the node shall be omitted from the rendered topology. type MapFunc func(RenderableNode, report.Networks) RenderableNodes +func generateInternetNodeFor(m RenderableNode) RenderableNodes { + node := newDerivedPseudoNode("", TheInternetMajor, m) + // emit one internet node for incoming, one for outgoing + if len(m.Adjacency) > 0 { + node.ID = IncomingInternetID + node.LabelMinor = Incoming + } else { + node.ID = OutgoingInternetID + node.LabelMinor = Outgoing + } + return RenderableNodes{node.ID: node} +} + // 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. @@ -62,7 +79,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 generateInternetNodeFor(m) } // We are a 'client' pseudo node if the port is in the ephemeral port range. @@ -231,8 +248,8 @@ func MapAddressIdentity(m RenderableNode, local report.Networks) RenderableNodes if !hasHostID { // 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)} + if ip := net.ParseIP(addr); ip != nil && !local.Contains(ip) { + return generateInternetNodeFor(m) } // Otherwise generate a pseudo node for every @@ -289,7 +306,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 generateInternetNodeFor(m) } // We don't always know what port a container is listening on, and @@ -350,8 +367,8 @@ func MapIP2Container(n RenderableNode, _ report.Networks) RenderableNodes { return RenderableNodes{} } - // Propogate the internet pseudo node. - if n.ID == TheInternetID { + // Propogate the internet pseudo node + if strings.HasSuffix(n.ID, TheInternetID) { return RenderableNodes{n.ID: n} } @@ -404,7 +421,7 @@ func MapEndpoint2Process(n RenderableNode, _ report.Networks) RenderableNodes { // must be merged with a container graph to get that info. func MapProcess2Container(n RenderableNode, _ report.Networks) RenderableNodes { // Propogate the internet pseudo node - if n.ID == TheInternetID { + if strings.HasSuffix(n.ID, TheInternetID) { return RenderableNodes{n.ID: n} } diff --git a/render/short_lived_connections_test.go b/render/short_lived_connections_test.go index 0b98b4f5fa..5f645f38c0 100644 --- a/render/short_lived_connections_test.go +++ b/render/short_lived_connections_test.go @@ -70,9 +70,10 @@ var ( } want = (render.RenderableNodes{ - render.TheInternetID: { - ID: render.TheInternetID, + render.IncomingInternetID: { + ID: render.IncomingInternetID, LabelMajor: render.TheInternetMajor, + LabelMinor: render.Incoming, Pseudo: true, Node: report.MakeNode().WithAdjacent(containerID), Origins: report.MakeIDList(randomEndpointNodeID),