From 0c122acf06dab19fe688e2961d1d6f4a080e2c0c Mon Sep 17 00:00:00 2001 From: Matthias Radestock Date: Wed, 5 Jul 2017 07:58:29 +0100 Subject: [PATCH] correct determination of a host's container images The same container image may be in use on multiple hosts. The latest-map HostNodeID of a node in the ContainerImage topology is therefore meaningless - it gets set to whatever host reported that image last in the time window covered by the report. Hence using it as a basis for mapping to hosts, as we did, a) fails to associate images with all the right hosts (hence they are missing from the host details panel), and b) causes that association to change semi-randomly (hence the list in the details panel is unstable). By contrast, the host topology parents of container image nodes is the complete set of all hosts the image is used on. So making that the basis for mapping fixes the problem. The same technique - mapping based on host parents rather than latest-map HostNodeID - also works for the other nodes we are mapping: processes, containers and pods. So we might as well use it there too. That's also what Map2Parent does in other topology renderers. Fixes #2629. --- render/host.go | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/render/host.go b/render/host.go index be6c8b34e..1bd0ec1d4 100644 --- a/render/host.go +++ b/render/host.go @@ -35,25 +35,31 @@ var HostRenderer = MakeReduce( // If this function is given a node without a hostname // (including other pseudo nodes), it will drop the node. // -// Otherwise, this function will produce a node with the correct ID +// Otherwise, this function will produce nodes with the correct ID // format for a host, but without any Major or Minor labels. It does // not have enough info to do that, and the resulting graph must be // merged with a host graph to get that info. func MapX2Host(n report.Node, _ report.Networks) report.Nodes { - // Don't propagate all pseudo nodes - we do this in MapEndpoint2Host + // Don't propagate pseudo nodes - we do this in MapEndpoint2Host if n.Topology == Pseudo { return report.Nodes{} } - hostNodeID, timestamp, ok := n.Latest.LookupEntry(report.HostNodeID) + + hostIDs, ok := n.Parents.Lookup(report.Host) if !ok { return report.Nodes{} } - id := report.MakeHostNodeID(report.ExtractHostID(n)) - result := NewDerivedNode(id, n).WithTopology(report.Host) - result.Latest = result.Latest.Set(report.HostNodeID, timestamp, hostNodeID) - result.Counters = result.Counters.Add(n.Topology, 1) - result.Children = report.MakeNodeSet(n) - return report.Nodes{id: result} + + result := report.Nodes{} + children := report.MakeNodeSet(n) + for _, id := range hostIDs { + node := NewDerivedNode(id, n).WithTopology(report.Host) + node.Counters = node.Counters.Add(n.Topology, 1) + node.Children = children + result[id] = node + } + + return result } // MapEndpoint2Host takes nodes from the endpoint topology and produces