func TestMergeRenderableNode(t *testing.T) { node1 := render.RenderableNode{ ID: "foo", LabelMajor: "", LabelMinor: "minor", Rank: "", Pseudo: false, Node: report.MakeNode().WithAdjacent("a1"), Origins: report.MakeIDList("o1"), } node2 := render.RenderableNode{ ID: "foo", LabelMajor: "major", LabelMinor: "", Rank: "rank", Pseudo: false, Node: report.MakeNode().WithAdjacent("a2"), Origins: report.MakeIDList("o2"), } want := render.RenderableNode{ ID: "foo", LabelMajor: "major", LabelMinor: "minor", Rank: "rank", Pseudo: false, Node: report.MakeNode().WithAdjacency(report.MakeIDList("a1", "a2")), Origins: report.MakeIDList("o1", "o2"), EdgeMetadata: report.EdgeMetadata{}, } have := node1.Merge(node2) if !reflect.DeepEqual(want, have) { t.Error(test.Diff(want, have)) } }
// Set the list of endpoints for the given hostname. func (c *multiClient) Set(hostname string, endpoints []string) { wg := sync.WaitGroup{} wg.Add(len(endpoints)) clients := make(chan clientTuple, len(endpoints)) for _, endpoint := range endpoints { go func(endpoint string) { c.sema.acquire() defer c.sema.release() defer wg.Done() client, err := c.clientFactory(hostname, endpoint) if err != nil { log.Errorf("Error creating new app client: %v", err) return } details, err := client.Details() if err != nil { log.Errorf("Error fetching app details: %v", err) return } clients <- clientTuple{details, client} }(endpoint) } wg.Wait() close(clients) c.mtx.Lock() defer c.mtx.Unlock() // Start any new apps, and replace the list of app ids for this hostname hostIDs := report.MakeIDList() for tuple := range clients { hostIDs = hostIDs.Add(tuple.ID) _, ok := c.clients[tuple.ID] if !ok { c.clients[tuple.ID] = tuple.AppClient tuple.AppClient.ControlConnection() } } c.ids[hostname] = hostIDs // Remove apps that are no longer referenced (by id) from any hostname allReferencedIDs := report.MakeIDList() for _, ids := range c.ids { allReferencedIDs = allReferencedIDs.Add(ids...) } for id, client := range c.clients { if !allReferencedIDs.Contains(id) { client.Stop() delete(c.clients, id) } } }
func assertAdjacent(t *testing.T, n report.RenderableNode, ids ...string) { want := report.MakeIDList(ids...) if have := n.Adjacency; !reflect.DeepEqual(want, have) { t.Fatalf("want adjacency list %v, have %v", want, have) } }
// MakeRenderableNodes converts a topology to a set of RenderableNodes func MakeRenderableNodes(t report.Topology) RenderableNodes { result := RenderableNodes{} for id, nmd := range t.Nodes { rn := NewRenderableNode(id).WithNode(nmd) rn.Origins = report.MakeIDList(id) if hostNodeID, ok := nmd.Metadata[report.HostNodeID]; ok { rn.Origins = rn.Origins.Add(hostNodeID) } result[id] = rn } // Push EdgeMetadata to both ends of the edges for srcID, srcNode := range result { for dstID, emd := range srcNode.Edges { srcNode.EdgeMetadata = srcNode.EdgeMetadata.Flatten(emd) dstNode := result[dstID] dstNode.EdgeMetadata = dstNode.EdgeMetadata.Flatten(emd.Reversed()) result[dstID] = dstNode } result[srcID] = srcNode } return result }
func TestFilterRender(t *testing.T) { renderer := render.FilterUnconnected( mockRenderer{RenderableNodes: render.RenderableNodes{ "foo": {ID: "foo", Adjacency: report.MakeIDList("bar"), NodeMetadata: report.MakeNodeMetadata()}, "bar": {ID: "bar", Adjacency: report.MakeIDList("foo"), NodeMetadata: report.MakeNodeMetadata()}, "baz": {ID: "baz", Adjacency: report.MakeIDList(), NodeMetadata: report.MakeNodeMetadata()}, }}) want := render.RenderableNodes{ "foo": {ID: "foo", Adjacency: report.MakeIDList("bar"), NodeMetadata: report.MakeNodeMetadata()}, "bar": {ID: "bar", Adjacency: report.MakeIDList("foo"), NodeMetadata: report.MakeNodeMetadata()}, } have := sterilize(renderer.Render(report.MakeReport()), true) if !reflect.DeepEqual(want, have) { t.Errorf("want %+v, have %+v", want, have) } }
func ids(nodes RenderableNodes) report.IDList { result := report.MakeIDList() for id := range nodes { result = result.Add(id) } return result }
func TestMapEdge(t *testing.T) { selector := func(_ report.Report) report.Topology { return report.Topology{ NodeMetadatas: report.NodeMetadatas{ "foo": report.NewNodeMetadata(map[string]string{"id": "foo"}), "bar": report.NewNodeMetadata(map[string]string{"id": "bar"}), }, Adjacency: report.Adjacency{ ">foo": report.MakeIDList("bar"), ">bar": report.MakeIDList("foo"), }, EdgeMetadatas: report.EdgeMetadatas{ "foo|bar": report.EdgeMetadata{WithBytes: true, BytesIngress: 1, BytesEgress: 2}, "bar|foo": report.EdgeMetadata{WithBytes: true, BytesIngress: 3, BytesEgress: 4}, }, } } identity := func(nmd report.NodeMetadata) (render.RenderableNode, bool) { return render.NewRenderableNode(nmd.Metadata["id"], "", "", "", nmd), true } mapper := render.Map{ MapFunc: func(nodes render.RenderableNode) (render.RenderableNode, bool) { return render.RenderableNode{ID: "_" + nodes.ID}, true }, Renderer: render.LeafMap{ Selector: selector, Mapper: identity, Pseudo: nil, }, } want := render.AggregateMetadata{ render.KeyBytesIngress: 1, render.KeyBytesEgress: 2, } have := mapper.AggregateMetadata(report.MakeReport(), "_foo", "_bar") if !reflect.DeepEqual(want, have) { t.Errorf("want %+v, have %+v", want, have) } }
func TestMapRender3(t *testing.T) { // 3. Check we can remap adjacencies mapper := render.Map{ MapFunc: func(nodes render.RenderableNode) (render.RenderableNode, bool) { return render.RenderableNode{ID: "_" + nodes.ID}, true }, Renderer: mockRenderer{RenderableNodes: render.RenderableNodes{ "foo": {ID: "foo", Adjacency: report.MakeIDList("baz")}, "baz": {ID: "baz", Adjacency: report.MakeIDList("foo")}, }}, } want := render.RenderableNodes{ "_foo": {ID: "_foo", Adjacency: report.MakeIDList("_baz")}, "_baz": {ID: "_baz", Adjacency: report.MakeIDList("_foo")}, } have := mapper.Render(report.MakeReport()) if !reflect.DeepEqual(want, have) { t.Errorf("want %+v, have %+v", want, have) } }
func TestMapEdge(t *testing.T) { selector := func(_ report.Report) report.Topology { return report.Topology{ NodeMetadatas: report.NodeMetadatas{ "foo": report.MakeNodeMetadataWith(map[string]string{"id": "foo"}), "bar": report.MakeNodeMetadataWith(map[string]string{"id": "bar"}), }, Adjacency: report.Adjacency{ ">foo": report.MakeIDList("bar"), ">bar": report.MakeIDList("foo"), }, EdgeMetadatas: report.EdgeMetadatas{ "foo|bar": report.EdgeMetadata{EgressPacketCount: newu64(1), EgressByteCount: newu64(2)}, "bar|foo": report.EdgeMetadata{EgressPacketCount: newu64(3), EgressByteCount: newu64(4)}, }, } } identity := func(nmd report.NodeMetadata) render.RenderableNodes { return render.RenderableNodes{nmd.Metadata["id"]: render.NewRenderableNode(nmd.Metadata["id"], "", "", "", nmd)} } mapper := render.Map{ MapFunc: func(nodes render.RenderableNode) render.RenderableNodes { id := "_" + nodes.ID return render.RenderableNodes{id: render.RenderableNode{ID: id}} }, Renderer: render.LeafMap{ Selector: selector, Mapper: identity, Pseudo: nil, }, } if want, have := (report.EdgeMetadata{ EgressPacketCount: newu64(1), EgressByteCount: newu64(2), }), mapper.EdgeMetadata(report.MakeReport(), "_foo", "_bar"); !reflect.DeepEqual(want, have) { t.Error(test.Diff(want, have)) } }
// NewRenderableNode makes a new RenderableNode func NewRenderableNode(id string) RenderableNode { return RenderableNode{ ID: id, LabelMajor: "", LabelMinor: "", Rank: "", Pseudo: false, Origins: report.MakeIDList(), EdgeMetadata: report.EdgeMetadata{}, Node: report.MakeNode(), } }
func TestMergeRenderableNode(t *testing.T) { node1 := render.RenderableNode{ ID: "foo", LabelMajor: "", LabelMinor: "minor", Rank: "", Pseudo: false, Adjacency: report.MakeIDList("a1"), Origins: report.MakeIDList("o1"), } node2 := render.RenderableNode{ ID: "foo", LabelMajor: "major", LabelMinor: "", Rank: "rank", Pseudo: false, Adjacency: report.MakeIDList("a2"), Origins: report.MakeIDList("o2"), } want := render.RenderableNode{ ID: "foo", LabelMajor: "major", LabelMinor: "minor", Rank: "rank", Pseudo: false, Adjacency: report.MakeIDList("a1", "a2"), Origins: report.MakeIDList("o1", "o2"), } node1.Merge(node2) if !reflect.DeepEqual(want, node1) { t.Errorf("want %+v, have %+v", want, node1) } }
func TestIDList(t *testing.T) { have := report.MakeIDList("alpha", "mu", "zeta") have = have.Add("alpha") have = have.Add("nu") have = have.Add("mu") have = have.Add("alpha") have = have.Add("alpha") have = have.Add("epsilon") have = have.Add("delta") if want := report.IDList([]string{"alpha", "delta", "epsilon", "mu", "nu", "zeta"}); !reflect.DeepEqual(want, have) { t.Errorf("want %+v, have %+v", want, have) } }
func (w Weave) tagContainer(r report.Report, containerIDPrefix, macAddress string, ips []string) { for nodeid, nmd := range r.Container.NodeMetadatas { idPrefix := nmd.Metadata[docker.ContainerID][:12] if idPrefix != containerIDPrefix { continue } existingIPs := report.MakeIDList(docker.ExtractContainerIPs(nmd)...) existingIPs = existingIPs.Add(ips...) nmd.Metadata[docker.ContainerIPs] = strings.Join(existingIPs, " ") nmd.Metadata[WeaveMACAddress] = macAddress r.Container.NodeMetadatas[nodeid] = nmd break } }
// EdgeMetadata gives the metadata of an edge from the perspective of the // srcRenderableID. Since an edgeID can have multiple edges on the address // level, it uses the supplied mapping function to translate address IDs to // renderable node (mapped) IDs. func (m LeafMap) EdgeMetadata(rpt report.Report, srcRenderableID, dstRenderableID string) report.EdgeMetadata { t := m.Selector(rpt) metadata := report.EdgeMetadata{} for edgeID, edgeMeta := range t.EdgeMetadatas { src, dst, ok := report.ParseEdgeID(edgeID) if !ok { log.Printf("bad edge ID %q", edgeID) continue } srcs, dsts := report.MakeIDList(src), report.MakeIDList(dst) if src != report.TheInternet { mapped := m.Mapper(t.NodeMetadatas[src]) srcs = ids(mapped) } if dst != report.TheInternet { mapped := m.Mapper(t.NodeMetadatas[dst]) dsts = ids(mapped) } if srcs.Contains(srcRenderableID) && dsts.Contains(dstRenderableID) { metadata = metadata.Flatten(edgeMeta) } } return metadata }
// Tag implements Tagger. func (w *Weave) Tag(r report.Report) (report.Report, error) { w.mtx.RLock() defer w.mtx.RUnlock() // Put information from weaveDNS on the container nodes for _, entry := range w.status.DNS.Entries { if entry.Tombstone > 0 { continue } nodeID := report.MakeContainerNodeID(w.hostID, entry.ContainerID) node, ok := r.Container.Nodes[nodeID] if !ok { continue } hostnames := report.IDList(strings.Fields(node.Metadata[WeaveDNSHostname])) hostnames = hostnames.Add(strings.TrimSuffix(entry.Hostname, ".")) node.Metadata[WeaveDNSHostname] = strings.Join(hostnames, " ") } // Put information from weave ps on the container nodes psEntries, err := w.ps() if err != nil { return r, nil } containersByPrefix := map[string]report.Node{} for _, node := range r.Container.Nodes { prefix := node.Metadata[docker.ContainerID][:12] containersByPrefix[prefix] = node } for _, e := range psEntries { node, ok := containersByPrefix[e.containerIDPrefix] if !ok { continue } existingIPs := report.MakeIDList(docker.ExtractContainerIPs(node)...) existingIPs = existingIPs.Add(e.ips...) node.Metadata[docker.ContainerIPs] = strings.Join(existingIPs, " ") node.Metadata[WeaveMACAddress] = e.macAddress } return r, nil }
func (m Map) render(rpt report.Report) (RenderableNodes, map[string]string) { input := m.Renderer.Render(rpt) output := RenderableNodes{} mapped := map[string]string{} // input node ID -> output node ID adjacencies := map[string]report.IDList{} // output node ID -> input node Adjacencies for _, inRenderable := range input { outRenderable, ok := m.MapFunc(inRenderable) if !ok { continue } existing, ok := output[outRenderable.ID] if ok { outRenderable.Merge(existing) } output[outRenderable.ID] = outRenderable mapped[inRenderable.ID] = outRenderable.ID adjacencies[outRenderable.ID] = adjacencies[outRenderable.ID].Add(inRenderable.Adjacency...) } // Rewrite Adjacency for new node IDs. // NB we don't do pseudo nodes here; we assume the input graph // is properly-connected, and if the map func dropped a node, // we drop links to it. for outNodeID, inAdjacency := range adjacencies { outAdjacency := report.MakeIDList() for _, inAdjacent := range inAdjacency { if outAdjacent, ok := mapped[inAdjacent]; ok { outAdjacency = outAdjacency.Add(outAdjacent) } } outNode := output[outNodeID] outNode.Adjacency = outAdjacency output[outNodeID] = outNode } return output, mapped }
func (f Filter) render(rpt report.Report) (RenderableNodes, int) { output := RenderableNodes{} inDegrees := map[string]int{} filtered := 0 for id, node := range f.Renderer.Render(rpt) { if f.FilterFunc(node) { output[id] = node inDegrees[id] = 0 } else { filtered++ } } // Deleted nodes also need to be cut as destinations in adjacency lists. for id, node := range output { newAdjacency := report.MakeIDList() for _, dstID := range node.Adjacency { if _, ok := output[dstID]; ok { newAdjacency = newAdjacency.Add(dstID) inDegrees[dstID]++ } } node.Adjacency = newAdjacency output[id] = node } // Remove unconnected pseudo nodes, see #483. for id, inDegree := range inDegrees { if inDegree > 0 { continue } node := output[id] if !node.Pseudo || len(node.Adjacency) > 0 { continue } delete(output, id) filtered++ } return output, filtered }
func (m Map) render(rpt report.Report) (RenderableNodes, map[string]report.IDList) { var ( input = m.Renderer.Render(rpt) output = RenderableNodes{} mapped = map[string]report.IDList{} // input node ID -> output node IDs adjacencies = map[string]report.IDList{} // output node ID -> input node Adjacencies localNetworks = LocalNetworks(rpt) ) // Rewrite all the nodes according to the map function for _, inRenderable := range input { for _, outRenderable := range m.MapFunc(inRenderable, localNetworks) { existing, ok := output[outRenderable.ID] if ok { outRenderable = outRenderable.Merge(existing) } output[outRenderable.ID] = outRenderable mapped[inRenderable.ID] = mapped[inRenderable.ID].Add(outRenderable.ID) adjacencies[outRenderable.ID] = adjacencies[outRenderable.ID].Merge(inRenderable.Adjacency) } } // Rewrite Adjacency for new node IDs. for outNodeID, inAdjacency := range adjacencies { outAdjacency := report.MakeIDList() for _, inAdjacent := range inAdjacency { for _, outAdjacent := range mapped[inAdjacent] { outAdjacency = outAdjacency.Add(outAdjacent) } } outNode := output[outNodeID] outNode.Adjacency = outAdjacency output[outNodeID] = outNode } return output, mapped }
Nodes: report.Nodes{ ClientAddressNodeID: report.MakeNode().WithMetadata(map[string]string{ endpoint.Addr: ClientIP, report.HostNodeID: ClientHostNodeID, }).WithEdge(ServerAddressNodeID, report.EdgeMetadata{ MaxConnCountTCP: newu64(3), }), ServerAddressNodeID: report.MakeNode().WithMetadata(map[string]string{ endpoint.Addr: ServerIP, report.HostNodeID: ServerHostNodeID, }), UnknownAddress1NodeID: report.MakeNode().WithMetadata(map[string]string{ endpoint.Addr: UnknownClient1IP, }).WithAdjacency(report.MakeIDList(ServerAddressNodeID)), UnknownAddress2NodeID: report.MakeNode().WithMetadata(map[string]string{ endpoint.Addr: UnknownClient2IP, }).WithAdjacency(report.MakeIDList(ServerAddressNodeID)), UnknownAddress3NodeID: report.MakeNode().WithMetadata(map[string]string{ endpoint.Addr: UnknownClient3IP, }).WithAdjacency(report.MakeIDList(ServerAddressNodeID)), RandomAddressNodeID: report.MakeNode().WithMetadata(map[string]string{ endpoint.Addr: RandomClientIP, }).WithAdjacency(report.MakeIDList(ServerAddressNodeID)), }, }, Host: report.Topology{
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 = 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, Origins: report.MakeIDList( test.UnknownClient1NodeID, test.UnknownClient2NodeID, ), } } 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, Origins: report.MakeIDList(
ClientContainerImageID = "imageid123" ServerContainerImageID = "imageid456" ClientContainerImageNodeID = report.MakeContainerNodeID(ClientHostID, ClientContainerImageID) ServerContainerImageNodeID = report.MakeContainerNodeID(ServerHostID, ServerContainerImageID) ClientAddressNodeID = report.MakeAddressNodeID(ClientHostID, "10.10.10.20") ServerAddressNodeID = report.MakeAddressNodeID(ServerHostID, "192.168.1.1") UnknownAddress1NodeID = report.MakeAddressNodeID(ServerHostID, "10.10.10.10") UnknownAddress2NodeID = report.MakeAddressNodeID(ServerHostID, "10.10.10.11") RandomAddressNodeID = report.MakeAddressNodeID(ServerHostID, "51.52.53.54") // this should become an internet node 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), }, NodeMetadatas: report.NodeMetadatas{ // NodeMetadata is arbitrary. We're free to put only precisely what we // care to test into the fixture. Just be sure to include the bits // that the mapping funcs extract :) Client54001NodeID: report.NodeMetadata{ "addr": ClientIP, "port": ClientPort54001, "pid": ClientPID, report.HostNodeID: ClientHostNodeID, },
serverHostNodeID: report.MakeNodeWith(map[string]string{ report.HostNodeID: serverHostNodeID, }).WithSets(report.Sets{ host.LocalNetworks: report.MakeStringSet("192.168.0.0/16"), }), }, }, } want = (render.RenderableNodes{ render.TheInternetID: { ID: render.TheInternetID, LabelMajor: render.TheInternetMajor, Pseudo: true, Node: report.MakeNode().WithAdjacent(containerID), Origins: report.MakeIDList(randomEndpointNodeID), }, containerID: { ID: containerID, LabelMajor: containerName, LabelMinor: serverHostID, Rank: "", Pseudo: false, Origins: report.MakeIDList(containerNodeID, serverEndpointNodeID, serverHostNodeID), Node: report.MakeNode(), ControlNode: containerNodeID, }, }).Prune() ) func TestShortLivedInternetNodeConnections(t *testing.T) {
// Render transforms a given Report into a set of RenderableNodes, which // the UI will render collectively as a graph. Note that a RenderableNode will // always be rendered with other nodes, and therefore contains limited detail. // // Nodes with the same mapped IDs will be merged. func (m LeafMap) Render(rpt report.Report) RenderableNodes { var ( t = m.Selector(rpt) nodes = RenderableNodes{} localNetworks = LocalNetworks(rpt) ) // Build a set of RenderableNodes for all non-pseudo probes, and an // addressID to nodeID lookup map. Multiple addressIDs can map to the same // RenderableNodes. source2mapped := map[string]report.IDList{} // source node ID -> mapped node IDs for nodeID, metadata := range t.NodeMetadatas { for _, mapped := range m.Mapper(metadata) { // mapped.ID needs not be unique over all addressIDs. If not, we merge with // the existing data, on the assumption that the MapFunc returns the same // data. existing, ok := nodes[mapped.ID] if ok { mapped.Merge(existing) } origins := mapped.Origins origins = origins.Add(nodeID) origins = origins.Add(metadata.Metadata[report.HostNodeID]) mapped.Origins = origins nodes[mapped.ID] = mapped source2mapped[nodeID] = source2mapped[nodeID].Add(mapped.ID) } } mkPseudoNode := func(srcNodeID, dstNodeID string, srcIsClient bool) report.IDList { pseudoNode, ok := m.Pseudo(srcNodeID, dstNodeID, srcIsClient, localNetworks) if !ok { return report.MakeIDList() } pseudoNode.Origins = pseudoNode.Origins.Add(srcNodeID) existing, ok := nodes[pseudoNode.ID] if ok { pseudoNode.Merge(existing) } nodes[pseudoNode.ID] = pseudoNode source2mapped[pseudoNode.ID] = source2mapped[pseudoNode.ID].Add(srcNodeID) return report.MakeIDList(pseudoNode.ID) } // Walk the graph and make connections. for src, dsts := range t.Adjacency { srcNodeID, ok := report.ParseAdjacencyID(src) if !ok { log.Printf("bad adjacency ID %q", src) continue } srcRenderableIDs, ok := source2mapped[srcNodeID] if !ok { // One of the entries in dsts must be a non-pseudo node, unless // it was dropped by the mapping function. for _, dstNodeID := range dsts { if _, ok := source2mapped[dstNodeID]; ok { srcRenderableIDs = mkPseudoNode(srcNodeID, dstNodeID, true) break } } } if len(srcRenderableIDs) == 0 { continue } for _, srcRenderableID := range srcRenderableIDs { srcRenderableNode := nodes[srcRenderableID] for _, dstNodeID := range dsts { dstRenderableIDs, ok := source2mapped[dstNodeID] if !ok { dstRenderableIDs = mkPseudoNode(dstNodeID, srcNodeID, false) } if len(dstRenderableIDs) == 0 { continue } for _, dstRenderableID := range dstRenderableIDs { dstRenderableNode := nodes[dstRenderableID] srcRenderableNode.Adjacency = srcRenderableNode.Adjacency.Add(dstRenderableID) // 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 = srcRenderableNode.EdgeMetadata.Merge(md) dstRenderableNode.EdgeMetadata = dstRenderableNode.EdgeMetadata.Merge(md) nodes[dstRenderableID] = dstRenderableNode } } } nodes[srcRenderableID] = srcRenderableNode } } return nodes }
Pseudo: true, AggregateMetadata: render.AggregateMetadata{}, } ClientProcessID = render.MakeProcessID(test.ClientHostID, test.ClientPID) ServerProcessID = render.MakeProcessID(test.ServerHostID, test.ServerPID) nonContainerProcessID = render.MakeProcessID(test.ServerHostID, test.NonContainerPID) RenderedProcesses = render.RenderableNodes{ ClientProcessID: { ID: ClientProcessID, LabelMajor: "curl", LabelMinor: fmt.Sprintf("%s (%s)", test.ClientHostID, test.ClientPID), Rank: test.ClientPID, Pseudo: false, Adjacency: report.MakeIDList(ServerProcessID), Origins: report.MakeIDList( test.Client54001NodeID, test.Client54002NodeID, test.ClientProcessNodeID, test.ClientHostNodeID, ), AggregateMetadata: render.AggregateMetadata{ render.KeyBytesIngress: 300, render.KeyBytesEgress: 30, }, }, ServerProcessID: { ID: ServerProcessID, LabelMajor: "apache", LabelMinor: fmt.Sprintf("%s (%s)", test.ServerHostID, test.ServerPID),
func TestMergeAdjacency(t *testing.T) { for name, c := range map[string]struct { a, b, want report.Adjacency }{ "Empty b": { a: report.Adjacency{ "hostA|:192.168.1.1:12345": report.MakeIDList(":192.168.1.2:80"), "hostA|:192.168.1.1:8888": report.MakeIDList(":1.2.3.4:22"), "hostB|:192.168.1.2:80": report.MakeIDList(":192.168.1.1:12345"), }, b: report.Adjacency{}, want: report.Adjacency{ "hostA|:192.168.1.1:12345": report.MakeIDList(":192.168.1.2:80"), "hostA|:192.168.1.1:8888": report.MakeIDList(":1.2.3.4:22"), "hostB|:192.168.1.2:80": report.MakeIDList(":192.168.1.1:12345"), }, }, "Empty a": { a: report.Adjacency{}, b: report.Adjacency{ "hostA|:192.168.1.1:12345": report.MakeIDList(":192.168.1.2:80"), "hostA|:192.168.1.1:8888": report.MakeIDList(":1.2.3.4:22"), "hostB|:192.168.1.2:80": report.MakeIDList(":192.168.1.1:12345"), }, want: report.Adjacency{ "hostA|:192.168.1.1:12345": report.MakeIDList(":192.168.1.2:80"), "hostA|:192.168.1.1:8888": report.MakeIDList(":1.2.3.4:22"), "hostB|:192.168.1.2:80": report.MakeIDList(":192.168.1.1:12345"), }, }, "Same address": { a: report.Adjacency{ "hostA|:192.168.1.1:12345": report.MakeIDList(":192.168.1.2:80"), }, b: report.Adjacency{ "hostA|:192.168.1.1:12345": report.MakeIDList(":192.168.1.2:8080"), }, want: report.Adjacency{ "hostA|:192.168.1.1:12345": report.MakeIDList( ":192.168.1.2:80", ":192.168.1.2:8080", ), }, }, "No duplicates": { a: report.Adjacency{ "hostA|:192.168.1.1:12345": report.MakeIDList( ":192.168.1.2:80", ":192.168.1.2:8080", ":192.168.1.2:555", ), }, b: report.Adjacency{ "hostA|:192.168.1.1:12345": report.MakeIDList( ":192.168.1.2:8080", ":192.168.1.2:80", ":192.168.1.2:444", ), }, want: report.Adjacency{ "hostA|:192.168.1.1:12345": []string{ ":192.168.1.2:444", ":192.168.1.2:555", ":192.168.1.2:80", ":192.168.1.2:8080", }, }, }, "Double keys": { a: report.Adjacency{ "key1": report.MakeIDList("a", "c", "d", "b"), "key2": report.MakeIDList("c", "a"), }, b: report.Adjacency{ "key1": report.MakeIDList("a", "b", "e"), "key3": report.MakeIDList("e", "a", "a", "a", "e"), }, want: report.Adjacency{ "key1": report.MakeIDList("a", "b", "c", "d", "e"), "key2": report.MakeIDList("a", "c"), "key3": report.MakeIDList("a", "e"), }, }, } { if have := c.a.Merge(c.b); !reflect.DeepEqual(c.want, have) { t.Errorf("%s: want\n\t%#v\nhave\n\t%#v", name, c.want, have) } } }
func TestMapEdge(t *testing.T) { selector := render.TopologySelector(func(_ report.Report) render.RenderableNodes { return render.MakeRenderableNodes(report.Topology{ Nodes: report.Nodes{ "foo": report.MakeNode().WithMetadata(map[string]string{ "id": "foo", }).WithEdge("bar", report.EdgeMetadata{ EgressPacketCount: newu64(1), EgressByteCount: newu64(2), }), "bar": report.MakeNode().WithMetadata(map[string]string{ "id": "bar", }).WithEdge("foo", report.EdgeMetadata{ EgressPacketCount: newu64(3), EgressByteCount: newu64(4), }), }, }) }) mapper := render.Map{ MapFunc: func(node render.RenderableNode, _ report.Networks) render.RenderableNodes { id := "_" + node.ID return render.RenderableNodes{id: render.NewDerivedNode(id, node)} }, Renderer: selector, } have := mapper.Render(report.MakeReport()).Prune() want := (render.RenderableNodes{ "_foo": { ID: "_foo", Origins: report.MakeIDList("foo"), Node: report.MakeNode().WithAdjacent("_bar"), EdgeMetadata: report.EdgeMetadata{ EgressPacketCount: newu64(1), EgressByteCount: newu64(2), IngressPacketCount: newu64(3), IngressByteCount: newu64(4), }, }, "_bar": { ID: "_bar", Origins: report.MakeIDList("bar"), Node: report.MakeNode().WithAdjacent("_foo"), EdgeMetadata: report.EdgeMetadata{ EgressPacketCount: newu64(3), EgressByteCount: newu64(4), IngressPacketCount: newu64(1), IngressByteCount: newu64(2), }, }, }).Prune() if !reflect.DeepEqual(want, have) { t.Error(test.Diff(want, have)) } if want, have := (report.EdgeMetadata{ EgressPacketCount: newu64(1), EgressByteCount: newu64(2), }), mapper.EdgeMetadata(report.MakeReport(), "_foo", "_bar"); !reflect.DeepEqual(want, have) { t.Error(test.Diff(want, have)) } }
ServerContainerImageID = "imageid456" ClientContainerImageNodeID = report.MakeContainerNodeID(ClientHostID, ClientContainerImageID) ServerContainerImageNodeID = report.MakeContainerNodeID(ServerHostID, ServerContainerImageID) ClientContainerImageName = "image/client" ServerContainerImageName = "image/server" ClientAddressNodeID = report.MakeAddressNodeID(ClientHostID, "10.10.10.20") ServerAddressNodeID = report.MakeAddressNodeID(ServerHostID, "192.168.1.1") UnknownAddress1NodeID = report.MakeAddressNodeID(ServerHostID, "10.10.10.10") UnknownAddress2NodeID = report.MakeAddressNodeID(ServerHostID, "10.10.10.11") RandomAddressNodeID = report.MakeAddressNodeID(ServerHostID, "51.52.53.54") // this should become an internet node Report = report.Report{ Endpoint: report.Topology{ Adjacency: report.Adjacency{ 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), report.MakeAdjacencyID(NonContainerNodeID): report.MakeIDList(GoogleEndpointNodeID), }, NodeMetadatas: report.NodeMetadatas{ // NodeMetadata is arbitrary. We're free to put only precisely what we // care to test into the fixture. Just be sure to include the bits // that the mapping funcs extract :) Client54001NodeID: report.MakeNodeMetadataWith(map[string]string{ endpoint.Addr: ClientIP, endpoint.Port: ClientPort54001, process.PID: Client1PID,
func TestMerge(t *testing.T) { var ( hostID = "xyz" src = newMockSource([]byte{}, nil) on = time.Millisecond off = time.Millisecond rpt = report.MakeReport() p = sniff.Packet{ SrcIP: "1.0.0.0", SrcPort: "1000", DstIP: "2.0.0.0", DstPort: "2000", Network: 512, Transport: 256, } _, ipnet, _ = net.ParseCIDR(p.SrcIP + "/24") // ;) localNets = report.Networks([]*net.IPNet{ipnet}) ) sniff.New(hostID, localNets, src, on, off).Merge(p, rpt) var ( srcEndpointNodeID = report.MakeEndpointNodeID(hostID, p.SrcIP, p.SrcPort) dstEndpointNodeID = report.MakeEndpointNodeID(hostID, p.DstIP, p.DstPort) ) if want, have := (report.Topology{ Adjacency: report.Adjacency{ report.MakeAdjacencyID(srcEndpointNodeID): report.MakeIDList( dstEndpointNodeID, ), }, EdgeMetadatas: report.EdgeMetadatas{ report.MakeEdgeID(srcEndpointNodeID, dstEndpointNodeID): report.EdgeMetadata{ EgressPacketCount: newu64(1), EgressByteCount: newu64(256), }, }, NodeMetadatas: report.NodeMetadatas{ srcEndpointNodeID: report.MakeNodeMetadata(), }, }), rpt.Endpoint; !reflect.DeepEqual(want, have) { t.Errorf("%s", test.Diff(want, have)) } var ( srcAddressNodeID = report.MakeAddressNodeID(hostID, p.SrcIP) dstAddressNodeID = report.MakeAddressNodeID(hostID, p.DstIP) ) if want, have := (report.Topology{ Adjacency: report.Adjacency{ report.MakeAdjacencyID(srcAddressNodeID): report.MakeIDList( dstAddressNodeID, ), }, EdgeMetadatas: report.EdgeMetadatas{ report.MakeEdgeID(srcAddressNodeID, dstAddressNodeID): report.EdgeMetadata{ EgressPacketCount: newu64(1), EgressByteCount: newu64(512), }, }, NodeMetadatas: report.NodeMetadatas{ srcAddressNodeID: report.MakeNodeMetadata(), }, }), rpt.Address; !reflect.DeepEqual(want, have) { t.Errorf("%s", test.Diff(want, have)) } }
var ( 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") unknownPseudoNode1 = func(adjacent string) render.RenderableNode { return render.RenderableNode{ ID: unknownPseudoNode1ID, LabelMajor: "10.10.10.10", Pseudo: true, Node: report.MakeNode().WithAdjacent(adjacent), EdgeMetadata: report.EdgeMetadata{ EgressPacketCount: newu64(70), EgressByteCount: newu64(700), }, Origins: report.MakeIDList( fixture.UnknownClient1NodeID, fixture.UnknownClient2NodeID, ), } } unknownPseudoNode2 = func(adjacent string) render.RenderableNode { return render.RenderableNode{ ID: unknownPseudoNode2ID, LabelMajor: "10.10.10.11", Pseudo: true, Node: report.MakeNode().WithAdjacent(adjacent), EdgeMetadata: report.EdgeMetadata{ EgressPacketCount: newu64(50), EgressByteCount: newu64(500), }, Origins: report.MakeIDList( fixture.UnknownClient3NodeID,