diff --git a/render/container.go b/render/container.go index b97d088521..71b889d854 100644 --- a/render/container.go +++ b/render/container.go @@ -82,7 +82,7 @@ func (c connectionJoin) Render(rpt report.Report) Nodes { // Nodes without a hostid may be pseudo nodes - if so, pass through to result if _, ok := m.Latest.Lookup(report.HostNodeID); !ok { if id, ok := externalNodeID(m, addr, local); ok { - ret.addChild(m, id, newPseudoNode) + ret.addChild(m, id, Pseudo) continue } } @@ -94,8 +94,9 @@ func (c connectionJoin) Render(rpt report.Report) Nodes { id, found = ipNodes[report.MakeScopedEndpointNodeID(scope, addr, port)] } if found && id != "" { // not one we blanked out earlier - // We are guaranteed to find the id, so no need to pass a node constructor. - ret.addChild(m, id, nil) + // We are guaranteed to find the id, so really this should + // never end up creating a node. + ret.addChild(m, id, report.Container) } } return ret.result(endpoints) @@ -268,9 +269,7 @@ func MapProcess2Container(n report.Node) report.Nodes { } // Otherwise, if the process is not in a container, group it into - // an per-host "Uncontained" node. If for whatever reason this - // node doesn't have a host id in their node metadata, it'll all - // get grouped into a single uncontained node. + // a per-host "Uncontained" node. var ( id string node report.Node @@ -279,10 +278,9 @@ func MapProcess2Container(n report.Node) report.Nodes { id = report.MakeContainerNodeID(containerID) node = NewDerivedNode(id, n).WithTopology(report.Container) } else { - id = MakePseudoNodeID(UncontainedID, report.ExtractHostID(n)) + hostID, _, _ := report.ParseProcessNodeID(n.ID) + id = MakePseudoNodeID(UncontainedID, hostID) node = NewDerivedPseudoNode(id, n) - node = propagateLatest(report.HostNodeID, n, node) - node = propagateLatest(IsConnectedMark, n, node) } return report.Nodes{id: node} } @@ -307,7 +305,7 @@ func MapContainer2ContainerImage(n report.Node) report.Nodes { // Otherwise, if some some reason the container doesn't have a image_id // (maybe slightly out of sync reports), just drop it - imageID, timestamp, ok := n.Latest.LookupEntry(docker.ImageID) + imageID, ok := n.Latest.Lookup(docker.ImageID) if !ok { return report.Nodes{} } @@ -316,7 +314,6 @@ func MapContainer2ContainerImage(n report.Node) report.Nodes { // counted to produce the minor label id := report.MakeContainerImageNodeID(imageID) result := NewDerivedNode(id, n).WithTopology(report.ContainerImage) - result.Latest = result.Latest.Set(docker.ImageID, timestamp, imageID) result.Counters = result.Counters.Add(n.Topology, 1) return report.Nodes{id: result} } @@ -336,13 +333,11 @@ func MapContainerImage2Name(n report.Node) report.Nodes { imageNameWithoutVersion := docker.ImageNameWithoutVersion(imageName) n.ID = report.MakeContainerImageNodeID(imageNameWithoutVersion) - if imageID, ok := report.ParseContainerImageNodeID(n.ID); ok { - n.Sets = n.Sets.Add(docker.ImageID, report.MakeStringSet(imageID)) - } - return report.Nodes{n.ID: n} } +var containerHostnameTopology = MakeGroupNodeTopology(report.Container, docker.ContainerHostname) + // MapContainer2Hostname maps container Nodes to 'hostname' renderabled nodes.. func MapContainer2Hostname(n report.Node) report.Nodes { // Propagate all pseudo nodes @@ -352,13 +347,12 @@ func MapContainer2Hostname(n report.Node) report.Nodes { // Otherwise, if some some reason the container doesn't have a hostname // (maybe slightly out of sync reports), just drop it - id, timestamp, ok := n.Latest.LookupEntry(docker.ContainerHostname) + id, ok := n.Latest.Lookup(docker.ContainerHostname) if !ok { return report.Nodes{} } - node := NewDerivedNode(id, n).WithTopology(MakeGroupNodeTopology(n.Topology, docker.ContainerHostname)) - node.Latest = node.Latest.Set(docker.ContainerHostname, timestamp, id) + node := NewDerivedNode(id, n).WithTopology(containerHostnameTopology) node.Counters = node.Counters.Add(n.Topology, 1) return report.Nodes{id: node} } diff --git a/render/host.go b/render/host.go index 1e1e0b0a9e..f368ff1810 100644 --- a/render/host.go +++ b/render/host.go @@ -16,10 +16,6 @@ var HostRenderer = MakeReduce( endpoints2Hosts{}, ) -func newHostNode(id string) report.Node { - return report.MakeNode(id).WithTopology(report.Host) -} - // nodes2Hosts maps any Nodes to host Nodes. // // If this function is given a node without a hostname @@ -45,9 +41,9 @@ func nodes2Hosts(nodes Nodes) Nodes { // hosts, and hence mapping these adjacencies to host // adjacencies would produce edges that aren't present // in reality. - ret.addUnmappedChild(n, id, newHostNode) + ret.addUnmappedChild(n, id, report.Host) } else { - ret.addChild(n, id, newHostNode) + ret.addChild(n, id, report.Host) } } } @@ -67,18 +63,12 @@ func (e endpoints2Hosts) Render(rpt report.Report) Nodes { for _, n := range endpoints.Nodes { // Nodes without a hostid are treated as pseudo nodes - if hostNodeID, timestamp, ok := n.Latest.LookupEntry(report.HostNodeID); !ok { + if hostNodeID, ok := n.Latest.Lookup(report.HostNodeID); !ok { if id, ok := pseudoNodeID(n, local); ok { - ret.addChild(n, id, newPseudoNode) + ret.addChild(n, id, Pseudo) } } else { - id := report.MakeHostNodeID(report.ExtractHostID(n)) - ret.addChild(n, id, func(id string) report.Node { - // we have a hostNodeID, but no matching host node; - // create a new one rather than dropping the data - return newHostNode(id). - WithLatest(report.HostNodeID, timestamp, hostNodeID) - }) + ret.addChild(n, hostNodeID, report.Host) } } return ret.result(endpoints) diff --git a/render/id.go b/render/id.go index 5fa34f8f24..3b8eda0a69 100644 --- a/render/id.go +++ b/render/id.go @@ -62,10 +62,6 @@ func NewDerivedPseudoNode(id string, node report.Node) report.Node { return output } -func newPseudoNode(id string) report.Node { - return report.MakeNode(id).WithTopology(Pseudo) -} - func pseudoNodeID(n report.Node, local report.Networks) (string, bool) { _, addr, _, ok := report.ParseEndpointNodeID(n.ID) if !ok { diff --git a/render/pod.go b/render/pod.go index 26b895f321..642903a8b5 100644 --- a/render/pod.go +++ b/render/pod.go @@ -137,7 +137,7 @@ func Map2Parent( return func(n report.Node) report.Nodes { // Uncontained becomes Unmanaged/whatever if noParentsPseudoID is set if noParentsPseudoID != "" && strings.HasPrefix(n.ID, UncontainedIDPrefix) { - id := MakePseudoNodeID(noParentsPseudoID, report.ExtractHostID(n)) + id := MakePseudoNodeID(noParentsPseudoID, n.ID[len(UncontainedIDPrefix):]) node := NewDerivedPseudoNode(id, n) return report.Nodes{id: node} } diff --git a/render/process.go b/render/process.go index 0d29890593..1fdd08b631 100644 --- a/render/process.go +++ b/render/process.go @@ -45,7 +45,7 @@ func (r processWithContainerNameRenderer) Render(rpt report.Report) Nodes { outputs := make(report.Nodes, len(processes.Nodes)) for id, p := range processes.Nodes { outputs[id] = p - containerID, timestamp, ok := p.Latest.LookupEntry(docker.ContainerID) + containerID, ok := p.Latest.Lookup(docker.ContainerID) if !ok { continue } @@ -53,10 +53,7 @@ func (r processWithContainerNameRenderer) Render(rpt report.Report) Nodes { if !ok { continue } - p.Latest = p.Latest.Set(docker.ContainerID, timestamp, containerID) - if containerName, timestamp, ok := container.Latest.LookupEntry(docker.ContainerName); ok { - p.Latest = p.Latest.Set(docker.ContainerName, timestamp, containerName) - } + propagateLatest(docker.ContainerName, container, p) outputs[id] = p } return Nodes{Nodes: outputs, Filtered: processes.Filtered} @@ -92,10 +89,10 @@ func (e endpoints2Processes) Render(rpt report.Report) Nodes { // Nodes without a hostid are treated as pseudo nodes if hostNodeID, ok := n.Latest.Lookup(report.HostNodeID); !ok { if id, ok := pseudoNodeID(n, local); ok { - ret.addChild(n, id, newPseudoNode) + ret.addChild(n, id, Pseudo) } } else { - pid, timestamp, ok := n.Latest.LookupEntry(process.PID) + pid, ok := n.Latest.Lookup(process.PID) if !ok { continue } @@ -105,12 +102,7 @@ func (e endpoints2Processes) Render(rpt report.Report) Nodes { hostID, _ := report.ParseHostNodeID(hostNodeID) id := report.MakeProcessNodeID(hostID, pid) - ret.addChild(n, id, func(id string) report.Node { - // we have a pid, but no matching process node; - // create a new one rather than dropping the data - return report.MakeNode(id).WithTopology(report.Process). - WithLatest(process.PID, timestamp, pid) - }) + ret.addChild(n, id, report.Process) } } return ret.result(endpoints) @@ -143,6 +135,8 @@ func hasMoreThanOneConnection(n report.Node, endpoints report.Nodes) bool { return false } +var processNameTopology = MakeGroupNodeTopology(report.Process, process.Name) + // processes2Names maps process Nodes to Nodes for each process name. func processes2Names(processes Nodes) Nodes { ret := newJoinResults(nil) @@ -150,11 +144,8 @@ func processes2Names(processes Nodes) Nodes { for _, n := range processes.Nodes { if n.Topology == Pseudo { ret.passThrough(n) - } else if name, timestamp, ok := n.Latest.LookupEntry(process.Name); ok { - ret.addChildAndChildren(n, name, func(id string) report.Node { - return report.MakeNode(id).WithTopology(MakeGroupNodeTopology(n.Topology, process.Name)). - WithLatest(process.Name, timestamp, name) - }) + } else if name, ok := n.Latest.Lookup(process.Name); ok { + ret.addChildAndChildren(n, name, processNameTopology) } } return ret.result(processes) diff --git a/render/render.go b/render/render.go index c8b80138f5..ff4e57924b 100644 --- a/render/render.go +++ b/render/render.go @@ -184,12 +184,12 @@ func (ret *joinResults) mapChild(from, to string) { } } -// Add m as a child of the node at id, creating a new result node if -// not already there. -func (ret *joinResults) addUnmappedChild(m report.Node, id string, create func(string) report.Node) { +// Add m as a child of the node at id, creating a new result node in +// the specified topology if not already there. +func (ret *joinResults) addUnmappedChild(m report.Node, id string, topology string) { result, exists := ret.nodes[id] if !exists { - result = create(id) + result = report.MakeNode(id).WithTopology(topology) } result.Children = result.Children.Add(m) if m.Topology != report.Endpoint { // optimisation: we never look at endpoint counts @@ -198,16 +198,17 @@ func (ret *joinResults) addUnmappedChild(m report.Node, id string, create func(s ret.nodes[id] = result } -// Add m as a child of the node at id, creating a new result node if -// not already there, and updating the mapping from old ID to new ID. -func (ret *joinResults) addChild(m report.Node, id string, create func(string) report.Node) { - ret.addUnmappedChild(m, id, create) +// Add m as a child of the node at id, creating a new result node in +// the specified topology if not already there, and updating the +// mapping from old ID to new ID. +func (ret *joinResults) addChild(m report.Node, id string, topology string) { + ret.addUnmappedChild(m, id, topology) ret.mapChild(m.ID, id) } // Like addChild, but also add m's children. -func (ret *joinResults) addChildAndChildren(m report.Node, id string, create func(string) report.Node) { - ret.addUnmappedChild(m, id, create) +func (ret *joinResults) addChildAndChildren(m report.Node, id string, topology string) { + ret.addUnmappedChild(m, id, topology) result := ret.nodes[id] result.Children = result.Children.Merge(m.Children) ret.nodes[id] = result