func TestTagger(t *testing.T) { oldProcessTree := docker.NewProcessTreeStub defer func() { docker.NewProcessTreeStub = oldProcessTree }() docker.NewProcessTreeStub = func(_ process.Walker) (process.Tree, error) { return &mockProcessTree{map[int]int{2: 1}}, nil } var ( pid1NodeID = report.MakeProcessNodeID("somehost.com", "1") pid2NodeID = report.MakeProcessNodeID("somehost.com", "2") wantNodeMetadata = report.MakeNodeMetadataWith(map[string]string{docker.ContainerID: "ping"}) ) input := report.MakeReport() input.Process.NodeMetadatas[pid1NodeID] = report.MakeNodeMetadataWith(map[string]string{"pid": "1"}) input.Process.NodeMetadatas[pid2NodeID] = report.MakeNodeMetadataWith(map[string]string{"pid": "2"}) want := report.MakeReport() want.Process.NodeMetadatas[pid1NodeID] = report.MakeNodeMetadataWith(map[string]string{"pid": "1"}).Merge(wantNodeMetadata) want.Process.NodeMetadatas[pid2NodeID] = report.MakeNodeMetadataWith(map[string]string{"pid": "2"}).Merge(wantNodeMetadata) tagger := docker.NewTagger(mockRegistryInstance, nil) have, err := tagger.Tag(input) if err != nil { t.Errorf("%v", err) } if !reflect.DeepEqual(want, have) { t.Errorf("%s", test.Diff(want, have)) } }
func TestReporter(t *testing.T) { want := report.MakeReport() want.Container = report.Topology{ Adjacency: report.Adjacency{}, EdgeMetadatas: report.EdgeMetadatas{}, NodeMetadatas: report.NodeMetadatas{ report.MakeContainerNodeID("", "ping"): report.MakeNodeMetadataWith(map[string]string{ docker.ContainerID: "ping", docker.ContainerName: "pong", docker.ImageID: "baz", }), }, } want.ContainerImage = report.Topology{ Adjacency: report.Adjacency{}, EdgeMetadatas: report.EdgeMetadatas{}, NodeMetadatas: report.NodeMetadatas{ report.MakeContainerNodeID("", "baz"): report.MakeNodeMetadataWith(map[string]string{ docker.ImageID: "baz", docker.ImageName: "bang", }), }, } reporter := docker.NewReporter(mockRegistryInstance, "") have, _ := reporter.Report() if !reflect.DeepEqual(want, have) { t.Errorf("%s", test.Diff(want, have)) } }
func TestApply(t *testing.T) { var ( endpointNodeID = "c" addressNodeID = "d" endpointNodeMetadata = report.MakeNodeMetadataWith(map[string]string{"5": "6"}) addressNodeMetadata = report.MakeNodeMetadataWith(map[string]string{"7": "8"}) ) r := report.MakeReport() r.Endpoint.NodeMetadatas[endpointNodeID] = endpointNodeMetadata r.Address.NodeMetadatas[addressNodeID] = addressNodeMetadata r = Apply(r, []Tagger{newTopologyTagger()}) for _, tuple := range []struct { want report.NodeMetadata from report.Topology via string }{ {endpointNodeMetadata.Merge(report.MakeNodeMetadataWith(map[string]string{"topology": "endpoint"})), r.Endpoint, endpointNodeID}, {addressNodeMetadata.Merge(report.MakeNodeMetadataWith(map[string]string{"topology": "address"})), r.Address, addressNodeID}, } { if want, have := tuple.want, tuple.from.NodeMetadatas[tuple.via]; !reflect.DeepEqual(want, have) { t.Errorf("want %+v, have %+v", want, have) } } }
func TestReporter(t *testing.T) { walker := &mockWalker{ processes: []process.Process{ {PID: 1, PPID: 0, Comm: "init"}, {PID: 2, PPID: 1, Comm: "bash"}, {PID: 3, PPID: 1, Comm: "apache", Threads: 2}, {PID: 4, PPID: 2, Comm: "ping", Cmdline: "ping foo.bar.local"}, {PID: 5, PPID: 1, Cmdline: "tail -f /var/log/syslog"}, }, } reporter := process.NewReporter(walker, "") want := report.MakeReport() want.Process = report.Topology{ Adjacency: report.Adjacency{}, EdgeMetadatas: report.EdgeMetadatas{}, NodeMetadatas: report.NodeMetadatas{ report.MakeProcessNodeID("", "1"): report.MakeNodeMetadataWith(map[string]string{ process.PID: "1", process.Comm: "init", process.Threads: "0", }), report.MakeProcessNodeID("", "2"): report.MakeNodeMetadataWith(map[string]string{ process.PID: "2", process.Comm: "bash", process.PPID: "1", process.Threads: "0", }), report.MakeProcessNodeID("", "3"): report.MakeNodeMetadataWith(map[string]string{ process.PID: "3", process.Comm: "apache", process.PPID: "1", process.Threads: "2", }), report.MakeProcessNodeID("", "4"): report.MakeNodeMetadataWith(map[string]string{ process.PID: "4", process.Comm: "ping", process.PPID: "2", process.Cmdline: "ping foo.bar.local", process.Threads: "0", }), report.MakeProcessNodeID("", "5"): report.MakeNodeMetadataWith(map[string]string{ process.PID: "5", process.PPID: "1", process.Cmdline: "tail -f /var/log/syslog", process.Threads: "0", }), }, } have, err := reporter.Report() if err != nil || !reflect.DeepEqual(want, have) { t.Errorf("%s (%v)", test.Diff(want, have), err) } }
func TestMapEndpointIdentity(t *testing.T) { for _, input := range []testcase{ {report.MakeNodeMetadata(), false}, {report.MakeNodeMetadataWith(map[string]string{endpoint.Addr: "1.2.3.4"}), false}, {report.MakeNodeMetadataWith(map[string]string{endpoint.Port: "1234"}), false}, {report.MakeNodeMetadataWith(map[string]string{endpoint.Addr: "1.2.3.4", endpoint.Port: "1234"}), true}, {report.MakeNodeMetadataWith(map[string]string{report.HostNodeID: report.MakeHostNodeID("foo"), endpoint.Addr: "10.0.0.1", endpoint.Port: "20001"}), true}, } { testMap(t, render.MapEndpointIdentity, input) } }
// Report implements Reporter. func (w Weave) Report() (report.Report, error) { r := report.MakeReport() resp, err := http.Get(w.url) if err != nil { log.Printf("Weave Tagger: %v", err) return r, err } defer resp.Body.Close() var status struct { Peers []struct { Name string `json:"Name"` NickName string `json:"NickName"` } `json:"Peers"` } if err := json.NewDecoder(resp.Body).Decode(&status); err != nil { log.Printf("Weave Tagger: %v", err) return r, err } for _, peer := range status.Peers { r.Overlay.NodeMetadatas[report.MakeOverlayNodeID(peer.Name)] = report.MakeNodeMetadataWith(map[string]string{ WeavePeerName: peer.Name, WeavePeerNickName: peer.NickName, }) } return r, nil }
// Report implements Reporter. func (r *Reporter) Report() (report.Report, error) { var ( rep = report.MakeReport() localCIDRs []string ) for _, localNet := range r.localNets { localCIDRs = append(localCIDRs, localNet.String()) } uptime, err := GetUptime() if err != nil { return rep, err } kernel, err := GetKernelVersion() if err != nil { return rep, err } rep.Host.NodeMetadatas[report.MakeHostNodeID(r.hostID)] = report.MakeNodeMetadataWith(map[string]string{ Timestamp: Now(), HostName: r.hostName, LocalNetworks: strings.Join(localCIDRs, " "), OS: runtime.GOOS, Load: GetLoad(), KernelVersion: kernel, Uptime: uptime.String(), }) return rep, nil }
func (c *mockContainer) GetNodeMetadata() report.NodeMetadata { return report.MakeNodeMetadataWith(map[string]string{ docker.ContainerID: c.c.ID, docker.ContainerName: c.c.Name, docker.ImageID: c.c.Image, }) }
func TestWeaveTaggerOverlayTopology(t *testing.T) { s := httptest.NewServer(http.HandlerFunc(mockWeaveRouter)) defer s.Close() w, err := overlay.NewWeave(s.URL) if err != nil { t.Fatal(err) } have, err := w.Report() if err != nil { t.Fatal(err) } if want, have := (report.Topology{ Adjacency: report.Adjacency{}, EdgeMetadatas: report.EdgeMetadatas{}, NodeMetadatas: report.NodeMetadatas{ report.MakeOverlayNodeID(mockWeavePeerName): report.MakeNodeMetadataWith(map[string]string{ overlay.WeavePeerName: mockWeavePeerName, overlay.WeavePeerNickName: mockWeavePeerNickName, }), }, }), have.Overlay; !reflect.DeepEqual(want, have) { t.Error(test.Diff(want, have)) } }
func TestMapContainerImageIdentity(t *testing.T) { for _, input := range []testcase{ {report.MakeNodeMetadata(), false}, {report.MakeNodeMetadataWith(map[string]string{docker.ImageID: "a1b2c3"}), true}, } { testMap(t, render.MapContainerImageIdentity, input) } }
func TestMapAddressIdentity(t *testing.T) { for _, input := range []testcase{ {report.MakeNodeMetadata(), false}, {report.MakeNodeMetadataWith(map[string]string{endpoint.Addr: "192.168.1.1"}), true}, } { testMap(t, render.MapAddressIdentity, input) } }
func TestMapProcessIdentity(t *testing.T) { for _, input := range []testcase{ {report.MakeNodeMetadata(), false}, {report.MakeNodeMetadataWith(map[string]string{process.PID: "201"}), true}, } { testMap(t, render.MapProcessIdentity, input) } }
// Tag implements Tagger. func (t Tagger) Tag(r report.Report) (report.Report, error) { other := report.MakeNodeMetadataWith(map[string]string{report.HostNodeID: t.hostNodeID}) for _, topology := range r.Topologies() { for id, md := range topology.NodeMetadatas { topology.NodeMetadatas[id] = md.Merge(other) } } return r, nil }
func TestTagger(t *testing.T) { var ( hostID = "foo" endpointNodeID = report.MakeEndpointNodeID(hostID, "1.2.3.4", "56789") // hostID ignored nodeMetadata = report.MakeNodeMetadataWith(map[string]string{"foo": "bar"}) ) r := report.MakeReport() r.Endpoint.NodeMetadatas[endpointNodeID] = nodeMetadata want := nodeMetadata.Merge(report.MakeNodeMetadataWith(map[string]string{ report.HostNodeID: report.MakeHostNodeID(hostID), })) rpt, _ := host.NewTagger(hostID).Tag(r) have := rpt.Endpoint.NodeMetadatas[endpointNodeID].Copy() if !reflect.DeepEqual(want, have) { t.Error(test.Diff(want, have)) } }
func (r *Reporter) addConnection(rpt *report.Report, c *procspy.Connection) { var ( 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) ) rpt.Address.Adjacency[adjecencyID] = rpt.Address.Adjacency[adjecencyID].Add(remoteAddressNodeID) if _, ok := rpt.Address.NodeMetadatas[localAddressNodeID]; !ok { rpt.Address.NodeMetadatas[localAddressNodeID] = report.MakeNodeMetadataWith(map[string]string{ "name": r.hostName, Addr: c.LocalAddress.String(), }) } countTCPConnection(rpt.Address.EdgeMetadatas, edgeID) if c.Proc.PID > 0 { 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) ) rpt.Endpoint.Adjacency[adjecencyID] = rpt.Endpoint.Adjacency[adjecencyID].Add(remoteEndpointNodeID) if _, ok := rpt.Endpoint.NodeMetadatas[localEndpointNodeID]; !ok { // First hit establishes NodeMetadata for scoped local address + port md := report.MakeNodeMetadataWith(map[string]string{ Addr: c.LocalAddress.String(), Port: strconv.Itoa(int(c.LocalPort)), process.PID: fmt.Sprint(c.Proc.PID), }) rpt.Endpoint.NodeMetadatas[localEndpointNodeID] = md } countTCPConnection(rpt.Endpoint.EdgeMetadatas, edgeID) } }
func (c *container) GetNodeMetadata() report.NodeMetadata { c.RLock() defer c.RUnlock() result := report.MakeNodeMetadataWith(map[string]string{ ContainerID: c.ID(), ContainerName: strings.TrimPrefix(c.container.Name, "/"), ContainerPorts: c.ports(), ContainerCreated: c.container.Created.Format(time.RFC822), ContainerCommand: c.container.Path + " " + strings.Join(c.container.Args, " "), ImageID: c.container.Image, ContainerIPs: strings.Join(append(c.container.NetworkSettings.SecondaryIPAddresses, c.container.NetworkSettings.IPAddress), " "), }) AddLabels(result, c.container.Config.Labels) if c.latestStats == nil { return result } result = result.Merge(report.MakeNodeMetadataWith(map[string]string{ NetworkRxDropped: strconv.FormatUint(c.latestStats.Network.RxDropped, 10), NetworkRxBytes: strconv.FormatUint(c.latestStats.Network.RxBytes, 10), NetworkRxErrors: strconv.FormatUint(c.latestStats.Network.RxErrors, 10), NetworkTxPackets: strconv.FormatUint(c.latestStats.Network.TxPackets, 10), NetworkTxDropped: strconv.FormatUint(c.latestStats.Network.TxDropped, 10), NetworkRxPackets: strconv.FormatUint(c.latestStats.Network.RxPackets, 10), NetworkTxErrors: strconv.FormatUint(c.latestStats.Network.TxErrors, 10), NetworkTxBytes: strconv.FormatUint(c.latestStats.Network.TxBytes, 10), MemoryMaxUsage: strconv.FormatUint(c.latestStats.MemoryStats.MaxUsage, 10), MemoryUsage: strconv.FormatUint(c.latestStats.MemoryStats.Usage, 10), MemoryFailcnt: strconv.FormatUint(c.latestStats.MemoryStats.Failcnt, 10), MemoryLimit: strconv.FormatUint(c.latestStats.MemoryStats.Limit, 10), // CPUPercpuUsage: strconv.FormatUint(stats.CPUStats.CPUUsage.PercpuUsage, 10), CPUUsageInUsermode: strconv.FormatUint(c.latestStats.CPUStats.CPUUsage.UsageInUsermode, 10), CPUTotalUsage: strconv.FormatUint(c.latestStats.CPUStats.CPUUsage.TotalUsage, 10), CPUUsageInKernelmode: strconv.FormatUint(c.latestStats.CPUStats.CPUUsage.UsageInKernelmode, 10), CPUSystemCPUUsage: strconv.FormatUint(c.latestStats.CPUStats.SystemCPUUsage, 10), })) return result }
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)) } }
// Report implements Reporter. func (w Weave) Report() (report.Report, error) { r := report.MakeReport() status, err := w.update() if err != nil { return r, err } for _, peer := range status.Router.Peers { r.Overlay.NodeMetadatas[report.MakeOverlayNodeID(peer.Name)] = report.MakeNodeMetadataWith(map[string]string{ WeavePeerName: peer.Name, WeavePeerNickName: peer.NickName, }) } return r, nil }
func TestReportLocalNetworks(t *testing.T) { r := report.MakeReport() r.Merge(report.Report{Host: report.Topology{NodeMetadatas: report.NodeMetadatas{ "nonets": report.MakeNodeMetadata(), "foo": report.MakeNodeMetadataWith(map[string]string{host.LocalNetworks: "10.0.0.1/8 192.168.1.1/24 10.0.0.1/8 badnet/33"}), }}}) want := report.Networks([]*net.IPNet{ mustParseCIDR("10.0.0.1/8"), mustParseCIDR("192.168.1.1/24"), }) have := render.LocalNetworks(r) if !reflect.DeepEqual(want, have) { t.Errorf("%s", test.Diff(want, have)) } }
func TestReporter(t *testing.T) { var ( release = "release" version = "version" network = "192.168.0.0/16" hostID = "hostid" now = "now" hostname = "hostname" load = "0.59 0.36 0.29" uptime = "278h55m43s" kernel = "release version" _, ipnet, _ = net.ParseCIDR(network) localNets = report.Networks([]*net.IPNet{ipnet}) ) var ( oldGetKernelVersion = host.GetKernelVersion oldGetLoad = host.GetLoad oldGetUptime = host.GetUptime oldNow = host.Now ) defer func() { host.GetKernelVersion = oldGetKernelVersion host.GetLoad = oldGetLoad host.GetUptime = oldGetUptime host.Now = oldNow }() host.GetKernelVersion = func() (string, error) { return release + " " + version, nil } host.GetLoad = func() string { return load } host.GetUptime = func() (time.Duration, error) { return time.ParseDuration(uptime) } host.Now = func() string { return now } want := report.MakeReport() want.Host.NodeMetadatas[report.MakeHostNodeID(hostID)] = report.MakeNodeMetadataWith(map[string]string{ host.Timestamp: now, host.HostName: hostname, host.LocalNetworks: network, host.OS: runtime.GOOS, host.Load: load, host.Uptime: uptime, host.KernelVersion: kernel, }) have, _ := host.NewReporter(hostID, hostname, localNets).Report() if !reflect.DeepEqual(want, have) { t.Errorf("%s", test.Diff(want, have)) } }
// Tag implements Tagger func (topologyTagger) Tag(r report.Report) (report.Report, error) { for val, topology := range map[string]*report.Topology{ "endpoint": &(r.Endpoint), "address": &(r.Address), "process": &(r.Process), "container": &(r.Container), "container_image": &(r.ContainerImage), "host": &(r.Host), "overlay": &(r.Overlay), } { other := report.MakeNodeMetadataWith(map[string]string{Topology: val}) for id, md := range topology.NodeMetadatas { topology.NodeMetadatas[id] = md.Merge(other) } } return r, nil }
func (r *Reporter) processTopology() (report.Topology, error) { t := report.NewTopology() err := r.walker.Walk(func(p Process) { pidstr := strconv.Itoa(p.PID) nodeID := report.MakeProcessNodeID(r.scope, pidstr) t.NodeMetadatas[nodeID] = report.MakeNodeMetadataWith(map[string]string{ PID: pidstr, Comm: p.Comm, Cmdline: p.Cmdline, Threads: strconv.Itoa(p.Threads), }) if p.PPID > 0 { t.NodeMetadatas[nodeID].Metadata[PPID] = strconv.Itoa(p.PPID) } }) return t, err }
func (r *Reporter) containerImageTopology() report.Topology { result := report.NewTopology() r.registry.WalkImages(func(image *docker_client.APIImages) { nmd := report.MakeNodeMetadataWith(map[string]string{ ImageID: image.ID, }) if len(image.RepoTags) > 0 { nmd.Metadata[ImageName] = image.RepoTags[0] } nodeID := report.MakeContainerNodeID(r.scope, image.ID) result.NodeMetadatas[nodeID] = nmd }) return result }
func (t *Tagger) tag(tree process.Tree, topology *report.Topology) { for nodeID, nodeMetadata := range topology.NodeMetadatas { pidStr, ok := nodeMetadata.Metadata[process.PID] if !ok { continue } pid, err := strconv.ParseUint(pidStr, 10, 64) if err != nil { continue } var ( c Container candidate = int(pid) ) t.registry.LockedPIDLookup(func(lookup func(int) Container) { for { c = lookup(candidate) if c != nil { break } candidate, err = tree.GetParent(candidate) if err != nil { break } } }) if c == nil { continue } md := report.MakeNodeMetadataWith(map[string]string{ ContainerID: c.ID(), }) topology.NodeMetadatas[nodeID] = nodeMetadata.Merge(md) } }
func TestWeaveTaggerOverlayTopology(t *testing.T) { oldExecCmd := exec.Command defer func() { exec.Command = oldExecCmd }() exec.Command = func(name string, args ...string) exec.Cmd { return testExec.NewMockCmdString(fmt.Sprintf("%s %s %s/24\n", mockContainerID, mockContainerMAC, mockContainerIP)) } s := httptest.NewServer(http.HandlerFunc(mockWeaveRouter)) defer s.Close() w, err := overlay.NewWeave(mockHostID, s.URL) if err != nil { t.Fatal(err) } { have, err := w.Report() if err != nil { t.Fatal(err) } if want, have := (report.Topology{ Adjacency: report.Adjacency{}, EdgeMetadatas: report.EdgeMetadatas{}, NodeMetadatas: report.NodeMetadatas{ report.MakeOverlayNodeID(mockWeavePeerName): report.MakeNodeMetadataWith(map[string]string{ overlay.WeavePeerName: mockWeavePeerName, overlay.WeavePeerNickName: mockWeavePeerNickName, }), }, }), have.Overlay; !reflect.DeepEqual(want, have) { t.Error(test.Diff(want, have)) } } { nodeID := report.MakeContainerNodeID(mockHostID, mockContainerID) want := report.Report{ Container: report.Topology{ NodeMetadatas: report.NodeMetadatas{ nodeID: report.MakeNodeMetadataWith(map[string]string{ docker.ContainerID: mockContainerID, overlay.WeaveDNSHostname: mockHostname, overlay.WeaveMACAddress: mockContainerMAC, docker.ContainerIPs: mockContainerIP, }), }, }, } have, err := w.Tag(report.Report{ Container: report.Topology{ NodeMetadatas: report.NodeMetadatas{ nodeID: report.MakeNodeMetadataWith(map[string]string{ docker.ContainerID: mockContainerID, }), }, }, }) if err != nil { t.Fatal(err) } if !reflect.DeepEqual(want, have) { t.Error(test.Diff(want, have)) } } }
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, report.HostNodeID: ClientHostNodeID, }), Client54002NodeID: report.MakeNodeMetadataWith(map[string]string{ endpoint.Addr: ClientIP, endpoint.Port: ClientPort54002, process.PID: Client2PID, report.HostNodeID: ClientHostNodeID, }), Server80NodeID: report.MakeNodeMetadataWith(map[string]string{ endpoint.Addr: ServerIP, endpoint.Port: ServerPort, process.PID: ServerPID, report.HostNodeID: ServerHostNodeID, }), NonContainerNodeID: report.MakeNodeMetadataWith(map[string]string{
func demoReport(nodeCount int) report.Report { r := report.MakeReport() // Make up some plausible IPv4 numbers. hosts := []string{} ip := [4]int{192, 168, 1, 1} for range make([]struct{}, nodeCount) { hosts = append(hosts, fmt.Sprintf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3])) ip[3]++ if ip[3] > 200 { ip[2]++ ip[3] = 1 } } hosts = append(hosts, []string{"1.2.3.4", "2.3.4.5"}...) // Some non-local ones, too. _, localNet, err := net.ParseCIDR("192.168.0.0/16") if err != nil { panic(err) } type conn struct { srcProc, dstProc string dstPort int } procPool := []conn{ {srcProc: "curl", dstPort: 80, dstProc: "apache"}, {srcProc: "wget", dstPort: 80, dstProc: "apache"}, {srcProc: "curl", dstPort: 80, dstProc: "nginx"}, {srcProc: "curl", dstPort: 8080, dstProc: "app1"}, {srcProc: "nginx", dstPort: 8080, dstProc: "app1"}, {srcProc: "nginx", dstPort: 8080, dstProc: "app2"}, {srcProc: "nginx", dstPort: 8080, dstProc: "app3"}, } connectionCount := nodeCount * 2 for i := 0; i < connectionCount; i++ { var ( c = procPool[rand.Intn(len(procPool))] src = hosts[rand.Intn(len(hosts))] dst = hosts[rand.Intn(len(hosts))] srcPort = rand.Intn(50000) + 10000 srcPortID = report.MakeEndpointNodeID("", src, strconv.Itoa(srcPort)) dstPortID = report.MakeEndpointNodeID("", dst, strconv.Itoa(c.dstPort)) srcID = report.MakeAdjacencyID(srcPortID) dstID = report.MakeAdjacencyID(dstPortID) srcAddressID = report.MakeAddressNodeID("", src) dstAddressID = report.MakeAddressNodeID("", dst) nodeSrcAddressID = report.MakeAdjacencyID(srcAddressID) nodeDstAddressID = report.MakeAdjacencyID(dstAddressID) ) // Endpoint topology if _, ok := r.Endpoint.NodeMetadatas[srcPortID]; !ok { r.Endpoint.NodeMetadatas[srcPortID] = report.MakeNodeMetadataWith(map[string]string{ process.PID: "4000", "name": c.srcProc, "domain": "node-" + src, }) } r.Endpoint.Adjacency[srcID] = r.Endpoint.Adjacency[srcID].Add(dstPortID) if _, ok := r.Endpoint.NodeMetadatas[dstPortID]; !ok { r.Endpoint.NodeMetadatas[dstPortID] = report.MakeNodeMetadataWith(map[string]string{ process.PID: "4000", "name": c.dstProc, "domain": "node-" + dst, }) } r.Endpoint.Adjacency[dstID] = r.Endpoint.Adjacency[dstID].Add(srcPortID) var ( edgeKeyEgress = report.MakeEdgeID(srcPortID, dstPortID) edgeKeyIngress = report.MakeEdgeID(dstPortID, srcPortID) ) r.Endpoint.EdgeMetadatas[edgeKeyEgress] = report.EdgeMetadata{ MaxConnCountTCP: newu64(uint64(rand.Intn(100) + 10)), } r.Endpoint.EdgeMetadatas[edgeKeyIngress] = report.EdgeMetadata{ MaxConnCountTCP: newu64(uint64(rand.Intn(100) + 10)), } // Address topology if _, ok := r.Address.NodeMetadatas[srcAddressID]; !ok { r.Address.NodeMetadatas[srcAddressID] = report.MakeNodeMetadataWith(map[string]string{ docker.Name: src, }) } r.Address.Adjacency[nodeSrcAddressID] = r.Address.Adjacency[nodeSrcAddressID].Add(dstAddressID) if _, ok := r.Address.NodeMetadatas[dstAddressID]; !ok { r.Address.NodeMetadatas[dstAddressID] = report.MakeNodeMetadataWith(map[string]string{ docker.Name: dst, }) } r.Address.Adjacency[nodeDstAddressID] = r.Address.Adjacency[nodeDstAddressID].Add(srcAddressID) // Host data r.Host.NodeMetadatas["hostX"] = report.MakeNodeMetadataWith(map[string]string{ "ts": time.Now().UTC().Format(time.RFC3339Nano), "host_name": "host-x", "local_networks": localNet.String(), "os": "linux", }) } return r }
func TestMergeNodeMetadatas(t *testing.T) { for name, c := range map[string]struct { a, b, want report.NodeMetadatas }{ "Empty a": { a: report.NodeMetadatas{}, b: report.NodeMetadatas{ ":192.168.1.1:12345": report.MakeNodeMetadataWith(map[string]string{ PID: "23128", Name: "curl", Domain: "node-a.local", }), }, want: report.NodeMetadatas{ ":192.168.1.1:12345": report.MakeNodeMetadataWith(map[string]string{ PID: "23128", Name: "curl", Domain: "node-a.local", }), }, }, "Empty b": { a: report.NodeMetadatas{ ":192.168.1.1:12345": report.MakeNodeMetadataWith(map[string]string{ PID: "23128", Name: "curl", Domain: "node-a.local", }), }, b: report.NodeMetadatas{}, want: report.NodeMetadatas{ ":192.168.1.1:12345": report.MakeNodeMetadataWith(map[string]string{ PID: "23128", Name: "curl", Domain: "node-a.local", }), }, }, "Simple merge": { a: report.NodeMetadatas{ ":192.168.1.1:12345": report.MakeNodeMetadataWith(map[string]string{ PID: "23128", Name: "curl", Domain: "node-a.local", }), }, b: report.NodeMetadatas{ ":192.168.1.2:12345": report.MakeNodeMetadataWith(map[string]string{ PID: "42", Name: "curl", Domain: "node-a.local", }), }, want: report.NodeMetadatas{ ":192.168.1.1:12345": report.MakeNodeMetadataWith(map[string]string{ PID: "23128", Name: "curl", Domain: "node-a.local", }), ":192.168.1.2:12345": report.MakeNodeMetadataWith(map[string]string{ PID: "42", Name: "curl", Domain: "node-a.local", }), }, }, "Merge conflict": { a: report.NodeMetadatas{ ":192.168.1.1:12345": report.MakeNodeMetadataWith(map[string]string{ PID: "23128", Name: "curl", Domain: "node-a.local", }), }, b: report.NodeMetadatas{ ":192.168.1.1:12345": report.MakeNodeMetadataWith(map[string]string{ // <-- same ID PID: "0", Name: "curl", Domain: "node-a.local", }), }, want: report.NodeMetadatas{ ":192.168.1.1:12345": report.MakeNodeMetadataWith(map[string]string{ PID: "23128", Name: "curl", Domain: "node-a.local", }), }, }, } { if have := c.a.Merge(c.b); !reflect.DeepEqual(c.want, have) { t.Errorf("%s: want\n\t%#v, have\n\t%#v", name, c.want, have) } } }
func (r *Reporter) addConnection(rpt *report.Report, localAddr, remoteAddr string, localPort, remotePort uint16, proc *procspy.Proc) { localIsClient := int(localPort) > int(remotePort) // Update address topology { var ( localAddressNodeID = report.MakeAddressNodeID(r.hostID, localAddr) remoteAddressNodeID = report.MakeAddressNodeID(r.hostID, remoteAddr) adjacencyID = "" edgeID = "" ) 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) } countTCPConnection(rpt.Address.EdgeMetadatas, edgeID) if _, ok := rpt.Address.NodeMetadatas[localAddressNodeID]; !ok { rpt.Address.NodeMetadatas[localAddressNodeID] = report.MakeNodeMetadataWith(map[string]string{ "name": r.hostName, Addr: localAddr, }) } } // Update endpoint topology if r.includeProcesses { var ( localEndpointNodeID = report.MakeEndpointNodeID(r.hostID, localAddr, strconv.Itoa(int(localPort))) remoteEndpointNodeID = report.MakeEndpointNodeID(r.hostID, remoteAddr, strconv.Itoa(int(remotePort))) adjacencyID = "" edgeID = "" ) 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) } countTCPConnection(rpt.Endpoint.EdgeMetadatas, edgeID) md, ok := rpt.Endpoint.NodeMetadatas[localEndpointNodeID] updated := !ok if !ok { md = report.MakeNodeMetadataWith(map[string]string{ Addr: localAddr, Port: strconv.Itoa(int(localPort)), }) } if proc != nil && proc.PID > 0 { pid := strconv.FormatUint(uint64(proc.PID), 10) updated = updated || md.Metadata[process.PID] != pid md.Metadata[process.PID] = pid } if updated { rpt.Endpoint.NodeMetadatas[localEndpointNodeID] = md } } }