diff --git a/render/container.go b/render/container.go index 5e78fddfa..f40ca8227 100644 --- a/render/container.go +++ b/render/container.go @@ -116,14 +116,12 @@ func HasChildren(topology string) FilterFunc { } } -type containerWithImageNameRenderer struct { - Renderer -} +type containerWithImageNameRenderer struct{} // Render produces a container graph where the the latest metadata contains the // container image name, if found. func (r containerWithImageNameRenderer) Render(ctx context.Context, rpt report.Report) Nodes { - containers := r.Renderer.Render(ctx, rpt) + containers := ContainerRenderer.Render(ctx, rpt) images := SelectContainerImage.Render(ctx, rpt) outputs := make(report.Nodes, len(containers.Nodes)) @@ -155,20 +153,14 @@ func (r containerWithImageNameRenderer) Render(ctx context.Context, rpt report.R // ContainerWithImageNameRenderer is a Renderer which produces a container // graph where the ranks are the image names, not their IDs -var ContainerWithImageNameRenderer = Memoise(containerWithImageNameRenderer{ContainerRenderer}) +var ContainerWithImageNameRenderer = Memoise(containerWithImageNameRenderer{}) -// ContainerImageRenderer is a Renderer which produces a renderable container -// image graph by merging the container graph and the container image topology. +// ContainerImageRenderer produces a graph where each node is a container image +// with the original containers as children var ContainerImageRenderer = Memoise(FilterEmpty(report.Container, MakeMap( MapContainerImage2Name, - MakeReduce( - MakeMap( - MapContainer2ContainerImage, - ContainerWithImageNameRenderer, - ), - SelectContainerImage, - ), + containerImageRenderer{}, ), )) @@ -177,20 +169,9 @@ var ContainerImageRenderer = Memoise(FilterEmpty(report.Container, // // not memoised var ContainerHostnameRenderer = FilterEmpty(report.Container, - MakeReduce( - MakeMap( - MapContainer2Hostname, - ContainerWithImageNameRenderer, - ), - // Grab *all* the hostnames, so we can count the number which were empty - // for accurate stats. - MakeMap( - MapToEmpty, - MakeMap( - MapContainer2Hostname, - ContainerRenderer, - ), - ), + MakeMap( + MapContainer2Hostname, + ContainerWithImageNameRenderer, ), ) @@ -276,37 +257,28 @@ func MapProcess2Container(n report.Node) report.Node { return node } -// MapContainer2ContainerImage maps container Nodes to container -// image Nodes. -// -// Pseudo nodes are passed straight through. -// -// If this function is given a node without a docker_image_id -// it will drop that node. -// -// Otherwise, this function will produce a node with the correct ID -// format for a container image, 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 container image graph to get that info. -func MapContainer2ContainerImage(n report.Node) report.Node { - // Propagate all pseudo nodes - if n.Topology == Pseudo { - return n - } +// containerImageRenderer produces a graph where each node is a container image +// with the original containers as children +type containerImageRenderer struct{} - // Otherwise, if some some reason the container doesn't have a image_id - // (maybe slightly out of sync reports), just drop it - imageID, ok := n.Latest.Lookup(report.DockerImageID) - if !ok { - return report.Node{} - } +func (m containerImageRenderer) Render(ctx context.Context, rpt report.Report) Nodes { + containers := ContainerWithImageNameRenderer.Render(ctx, rpt) + ret := newJoinResults(rpt.ContainerImage.Nodes) - // Add container id key to the counters, which will later be - // counted to produce the minor label - id := report.MakeContainerImageNodeID(imageID) - result := NewDerivedNode(id, n).WithTopology(report.ContainerImage) - result.Counters = result.Counters.Add(n.Topology, 1) - return result + for _, n := range containers.Nodes { + if n.Topology == Pseudo { + ret.passThrough(n) + continue + } + // If some some reason the container doesn't have a image_id, just drop it + imageID, ok := n.Latest.Lookup(report.DockerImageID) + if !ok { + continue + } + id := report.MakeContainerImageNodeID(imageID) + ret.addChildAndChildren(n, id, report.ContainerImage) + } + return ret.result(containers) } func containerImageNodeID(n report.Node) string { @@ -358,9 +330,3 @@ func MapContainer2Hostname(n report.Node) report.Node { node.Counters = node.Counters.Add(n.Topology, 1) return node } - -// MapToEmpty removes all the attributes, children, etc, of a node. Useful when -// we just want to count the presence of nodes. -func MapToEmpty(n report.Node) report.Node { - return report.MakeNode(n.ID).WithTopology(n.Topology) -}