mirror of
https://github.com/weaveworks/scope.git
synced 2026-03-04 10:41:14 +00:00
250 lines
6.7 KiB
Go
250 lines
6.7 KiB
Go
package render
|
|
|
|
import (
|
|
"net"
|
|
|
|
"github.com/weaveworks/scope/probe/docker"
|
|
"github.com/weaveworks/scope/probe/host"
|
|
"github.com/weaveworks/scope/report"
|
|
)
|
|
|
|
// EndpointRenderer is a Renderer which produces a renderable endpoint graph.
|
|
var EndpointRenderer = FilterNonProcspied(SelectEndpoint)
|
|
|
|
// ProcessRenderer is a Renderer which produces a renderable process
|
|
// graph by merging the endpoint graph and the process topology.
|
|
var ProcessRenderer = MakeReduce(
|
|
MakeMap(
|
|
MapEndpoint2Process,
|
|
EndpointRenderer,
|
|
),
|
|
SelectProcess,
|
|
)
|
|
|
|
// processWithContainerNameRenderer is a Renderer which produces a process
|
|
// graph enriched with container names where appropriate
|
|
type processWithContainerNameRenderer struct {
|
|
Renderer
|
|
}
|
|
|
|
func (r processWithContainerNameRenderer) Render(rpt report.Report) report.Nodes {
|
|
processes := r.Renderer.Render(rpt)
|
|
containers := SelectContainer.Render(rpt)
|
|
|
|
outputs := report.Nodes{}
|
|
for id, p := range processes {
|
|
outputs[id] = p
|
|
containerID, timestamp, ok := p.Latest.LookupEntry(docker.ContainerID)
|
|
if !ok {
|
|
continue
|
|
}
|
|
container, ok := containers[report.MakeContainerNodeID(containerID)]
|
|
if !ok {
|
|
continue
|
|
}
|
|
output := p.Copy()
|
|
output.Latest = output.Latest.Set(docker.ContainerID, timestamp, containerID)
|
|
if containerName, timestamp, ok := container.Latest.LookupEntry(docker.ContainerName); ok {
|
|
output.Latest = output.Latest.Set(docker.ContainerName, timestamp, containerName)
|
|
}
|
|
outputs[id] = output
|
|
}
|
|
return outputs
|
|
}
|
|
|
|
// ProcessWithContainerNameRenderer is a Renderer which produces a process
|
|
// graph enriched with container names where appropriate
|
|
var ProcessWithContainerNameRenderer = processWithContainerNameRenderer{ProcessRenderer}
|
|
|
|
// ProcessNameRenderer is a Renderer which produces a renderable process
|
|
// name graph by munging the progess graph.
|
|
var ProcessNameRenderer = MakeMap(
|
|
MapProcess2Name,
|
|
ProcessRenderer,
|
|
)
|
|
|
|
// ContainerRenderer is a Renderer which produces a renderable container
|
|
// graph by merging the process graph and the container topology.
|
|
// NB We only want processes in container _or_ processes with network connections
|
|
// but we need to be careful to ensure we only include each edge once, by only
|
|
// including the ProcessRenderer once.
|
|
var ContainerRenderer = MakeReduce(
|
|
MakeSilentFilter(
|
|
func(n report.Node) bool {
|
|
// Drop unconnected pseudo nodes (could appear due to filtering)
|
|
_, isConnected := n.Latest.Lookup(IsConnected)
|
|
return n.Topology != Pseudo || isConnected
|
|
},
|
|
MakeMap(
|
|
MapProcess2Container,
|
|
ColorConnected(ProcessRenderer),
|
|
),
|
|
),
|
|
|
|
// This mapper brings in short lived connections by joining with container IPs.
|
|
// We need to be careful to ensure we only include each edge once. Edges brought in
|
|
// by the above renders will have a pid, so its enough to filter out any nodes with
|
|
// pids.
|
|
SilentFilterUnconnected(MakeMap(
|
|
MapIP2Container,
|
|
MakeReduce(
|
|
MakeMap(
|
|
MapContainer2IP,
|
|
SelectContainer,
|
|
),
|
|
MakeMap(
|
|
MapEndpoint2IP,
|
|
SelectEndpoint,
|
|
),
|
|
),
|
|
)),
|
|
|
|
SelectContainer,
|
|
)
|
|
|
|
type containerWithHostIPsRenderer struct {
|
|
Renderer
|
|
}
|
|
|
|
// Render produces a process graph where the ips for host network mode are set
|
|
// to the host's IPs.
|
|
func (r containerWithHostIPsRenderer) Render(rpt report.Report) report.Nodes {
|
|
containers := r.Renderer.Render(rpt)
|
|
hosts := SelectHost.Render(rpt)
|
|
|
|
outputs := report.Nodes{}
|
|
for id, c := range containers {
|
|
outputs[id] = c
|
|
networkMode, ok := c.Latest.Lookup(docker.ContainerNetworkMode)
|
|
if !ok || networkMode != docker.NetworkModeHost {
|
|
continue
|
|
}
|
|
|
|
h, ok := hosts[report.MakeHostNodeID(report.ExtractHostID(c))]
|
|
if !ok {
|
|
continue
|
|
}
|
|
|
|
newIPs := report.MakeStringSet()
|
|
hostNetworks, _ := h.Sets.Lookup(host.LocalNetworks)
|
|
for _, cidr := range hostNetworks {
|
|
if ip, _, err := net.ParseCIDR(cidr); err == nil {
|
|
newIPs = newIPs.Add(ip.String())
|
|
}
|
|
}
|
|
|
|
output := c.Copy()
|
|
output.Sets = c.Sets.Add(docker.ContainerIPs, newIPs)
|
|
outputs[id] = output
|
|
}
|
|
return outputs
|
|
}
|
|
|
|
// ContainerWithHostIPsRenderer is a Renderer which produces a container graph
|
|
// enriched with host IPs on containers where NetworkMode is Host
|
|
var ContainerWithHostIPsRenderer = containerWithHostIPsRenderer{ContainerRenderer}
|
|
|
|
type containerWithImageNameRenderer struct {
|
|
Renderer
|
|
}
|
|
|
|
// Render produces a process graph where the minor labels contain the
|
|
// container name, if found. It also merges the image node metadata into the
|
|
// container metadata.
|
|
func (r containerWithImageNameRenderer) Render(rpt report.Report) report.Nodes {
|
|
containers := r.Renderer.Render(rpt)
|
|
images := SelectContainerImage.Render(rpt)
|
|
|
|
outputs := report.Nodes{}
|
|
for id, c := range containers {
|
|
outputs[id] = c
|
|
imageID, ok := c.Latest.Lookup(docker.ImageID)
|
|
if !ok {
|
|
continue
|
|
}
|
|
image, ok := images[report.MakeContainerImageNodeID(imageID)]
|
|
if !ok {
|
|
continue
|
|
}
|
|
output := c.Copy()
|
|
output.Latest = image.Latest.Merge(c.Latest)
|
|
outputs[id] = output
|
|
}
|
|
return outputs
|
|
}
|
|
|
|
// ContainerWithImageNameRenderer is a Renderer which produces a container
|
|
// graph where the ranks are the image names, not their IDs
|
|
var ContainerWithImageNameRenderer = containerWithImageNameRenderer{ContainerWithHostIPsRenderer}
|
|
|
|
// ContainerImageRenderer is a Renderer which produces a renderable container
|
|
// image graph by merging the container graph and the container image topology.
|
|
var ContainerImageRenderer = MakeReduce(
|
|
MakeMap(
|
|
MapContainer2ContainerImage,
|
|
ContainerRenderer,
|
|
),
|
|
SelectContainerImage,
|
|
)
|
|
|
|
// ContainerHostnameRenderer is a Renderer which produces a renderable container
|
|
// by hostname graph..
|
|
var ContainerHostnameRenderer = MakeMap(
|
|
MapContainer2Hostname,
|
|
ContainerRenderer,
|
|
)
|
|
|
|
// HostRenderer is a Renderer which produces a renderable host
|
|
// graph from the host topology.
|
|
var HostRenderer = MakeReduce(
|
|
MakeMap(
|
|
MapEndpoint2Host,
|
|
EndpointRenderer,
|
|
),
|
|
MakeMap(
|
|
MapX2Host,
|
|
ColorConnected(ProcessRenderer),
|
|
),
|
|
MakeMap(
|
|
MapX2Host,
|
|
ContainerRenderer,
|
|
),
|
|
MakeMap(
|
|
MapX2Host,
|
|
ContainerImageRenderer,
|
|
),
|
|
// Pods don't have a host id - #1142
|
|
// MakeMap(
|
|
// MapX2Host,
|
|
// SelectPod,
|
|
// ),
|
|
SelectHost,
|
|
)
|
|
|
|
// PodRenderer is a Renderer which produces a renderable kubernetes
|
|
// graph by merging the container graph and the pods topology.
|
|
var PodRenderer = MakeReduce(
|
|
MakeSilentFilter(
|
|
func(n report.Node) bool {
|
|
// Drop unconnected pseudo nodes (could appear due to filtering)
|
|
_, isConnected := n.Latest.Lookup(IsConnected)
|
|
return n.Topology != Pseudo || isConnected
|
|
},
|
|
ColorConnected(MakeMap(
|
|
MapContainer2Pod,
|
|
ContainerRenderer,
|
|
)),
|
|
),
|
|
SelectPod,
|
|
)
|
|
|
|
// PodServiceRenderer is a Renderer which produces a renderable kubernetes services
|
|
// graph by merging the pods graph and the services topology.
|
|
var PodServiceRenderer = MakeReduce(
|
|
MakeMap(
|
|
MapPod2Service,
|
|
PodRenderer,
|
|
),
|
|
SelectService,
|
|
)
|