mirror of
https://github.com/weaveworks/scope.git
synced 2026-08-19 04:16:21 +00:00
Refactor Map2Parent and family into one function
This greatly improves code reuse while keeping the behaviour flexible
This commit is contained in:
+6
-48
@@ -1,9 +1,6 @@
|
||||
package render
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/weaveworks/scope/probe/docker"
|
||||
"github.com/weaveworks/scope/report"
|
||||
)
|
||||
|
||||
@@ -13,8 +10,11 @@ var ECSTaskRenderer = ConditionalRenderer(renderECSTopologies,
|
||||
PropagateSingleMetrics(report.Container),
|
||||
MakeReduce(
|
||||
MakeMap(
|
||||
MapContainer2ECSTask,
|
||||
ContainerWithImageNameRenderer,
|
||||
Map2Parent(report.ECSTask, UnmanagedID, nil),
|
||||
MakeFilter(
|
||||
IsRunning,
|
||||
ContainerWithImageNameRenderer,
|
||||
),
|
||||
),
|
||||
SelectECSTask,
|
||||
),
|
||||
@@ -27,7 +27,7 @@ var ECSServiceRenderer = ConditionalRenderer(renderECSTopologies,
|
||||
PropagateSingleMetrics(report.ECSTask),
|
||||
MakeReduce(
|
||||
MakeMap(
|
||||
Map2Parent(report.ECSService),
|
||||
Map2Parent(report.ECSService, "", nil),
|
||||
ECSTaskRenderer,
|
||||
),
|
||||
SelectECSService,
|
||||
@@ -35,48 +35,6 @@ var ECSServiceRenderer = ConditionalRenderer(renderECSTopologies,
|
||||
),
|
||||
)
|
||||
|
||||
// MapContainer2ECSTask maps container Nodes to ECS Task
|
||||
// Nodes.
|
||||
//
|
||||
// If this function is given a node without an ECS Task parent
|
||||
// (including other pseudo nodes), it will produce an "Unmanaged"
|
||||
// pseudo node.
|
||||
//
|
||||
// TODO: worth merging with MapContainer2Pod?
|
||||
func MapContainer2ECSTask(n report.Node, _ report.Networks) report.Nodes {
|
||||
// Uncontained becomes unmanaged in the tasks view
|
||||
if strings.HasPrefix(n.ID, MakePseudoNodeID(UncontainedID)) {
|
||||
id := MakePseudoNodeID(UnmanagedID, report.ExtractHostID(n))
|
||||
node := NewDerivedPseudoNode(id, n)
|
||||
return report.Nodes{id: node}
|
||||
}
|
||||
|
||||
// Propagate all pseudo nodes
|
||||
if n.Topology == Pseudo {
|
||||
return report.Nodes{n.ID: n}
|
||||
}
|
||||
|
||||
// Ignore non-running containers
|
||||
if state, ok := n.Latest.Lookup(docker.ContainerState); ok && state != docker.StateRunning {
|
||||
return report.Nodes{}
|
||||
}
|
||||
|
||||
taskIDSet, ok := n.Parents.Lookup(report.ECSTask)
|
||||
if !ok || len(taskIDSet) == 0 {
|
||||
id := MakePseudoNodeID(UnmanagedID, report.ExtractHostID(n))
|
||||
node := NewDerivedPseudoNode(id, n)
|
||||
return report.Nodes{id: node}
|
||||
}
|
||||
nodeID := taskIDSet[0]
|
||||
node := NewDerivedNode(nodeID, n).WithTopology(report.ECSTask)
|
||||
// Propagate parent service
|
||||
if serviceIDSet, ok := n.Parents.Lookup(report.ECSService); ok {
|
||||
node = node.WithParents(report.MakeSets().Add(report.ECSService, serviceIDSet))
|
||||
}
|
||||
node.Counters = node.Counters.Add(n.Topology, 1)
|
||||
return report.Nodes{nodeID: node}
|
||||
}
|
||||
|
||||
func renderECSTopologies(rpt report.Report) bool {
|
||||
return len(rpt.ECSTask.Nodes)+len(rpt.ECSService.Nodes) >= 1
|
||||
}
|
||||
|
||||
+51
-74
@@ -18,6 +18,11 @@ func renderKubernetesTopologies(rpt report.Report) bool {
|
||||
return len(rpt.Pod.Nodes)+len(rpt.Service.Nodes)+len(rpt.Deployment.Nodes)+len(rpt.ReplicaSet.Nodes) >= 1
|
||||
}
|
||||
|
||||
func isPauseContainer(n report.Node) bool {
|
||||
image, ok := n.Latest.Lookup(docker.ImageName)
|
||||
return ok && kubernetes.IsPauseImageName(image)
|
||||
}
|
||||
|
||||
// PodRenderer is a Renderer which produces a renderable kubernetes
|
||||
// graph by merging the container graph and the pods topology.
|
||||
var PodRenderer = ConditionalRenderer(renderKubernetesTopologies,
|
||||
@@ -30,8 +35,14 @@ var PodRenderer = ConditionalRenderer(renderKubernetesTopologies,
|
||||
PropagateSingleMetrics(report.Container),
|
||||
MakeReduce(
|
||||
MakeMap(
|
||||
MapContainer2Pod,
|
||||
ContainerWithImageNameRenderer,
|
||||
Map2Parent(report.Pod, UnmanagedID, nil),
|
||||
MakeFilter(
|
||||
ComposeFilterFuncs(
|
||||
IsRunning,
|
||||
Complement(isPauseContainer),
|
||||
),
|
||||
ContainerWithImageNameRenderer,
|
||||
),
|
||||
),
|
||||
ShortLivedConnectionJoin(SelectPod, MapPod2IP),
|
||||
SelectPod,
|
||||
@@ -47,7 +58,7 @@ var PodServiceRenderer = ConditionalRenderer(renderKubernetesTopologies,
|
||||
PropagateSingleMetrics(report.Pod),
|
||||
MakeReduce(
|
||||
MakeMap(
|
||||
Map2Service,
|
||||
Map2Parent(report.Service, "", nil),
|
||||
PodRenderer,
|
||||
),
|
||||
SelectService,
|
||||
@@ -62,7 +73,7 @@ var DeploymentRenderer = ConditionalRenderer(renderKubernetesTopologies,
|
||||
PropagateSingleMetrics(report.ReplicaSet),
|
||||
MakeReduce(
|
||||
MakeMap(
|
||||
Map2Deployment,
|
||||
Map2Parent(report.Deployment, "", mapPodCounts),
|
||||
ReplicaSetRenderer,
|
||||
),
|
||||
SelectDeployment,
|
||||
@@ -77,7 +88,7 @@ var ReplicaSetRenderer = ConditionalRenderer(renderKubernetesTopologies,
|
||||
PropagateSingleMetrics(report.Pod),
|
||||
MakeReduce(
|
||||
MakeMap(
|
||||
Map2ReplicaSet,
|
||||
Map2Parent(report.ReplicaSet, "", nil),
|
||||
PodRenderer,
|
||||
),
|
||||
SelectReplicaSet,
|
||||
@@ -85,54 +96,12 @@ var ReplicaSetRenderer = ConditionalRenderer(renderKubernetesTopologies,
|
||||
),
|
||||
)
|
||||
|
||||
// MapContainer2Pod maps container Nodes to pod
|
||||
// Nodes.
|
||||
//
|
||||
// If this function is given a node without a kubernetes_pod_id
|
||||
// (including other pseudo nodes), it will produce an "Unmanaged"
|
||||
// pseudo node.
|
||||
//
|
||||
// Otherwise, this function will produce a node with the correct ID
|
||||
// format for a container, 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 graph to get that info.
|
||||
func MapContainer2Pod(n report.Node, _ report.Networks) report.Nodes {
|
||||
// Uncontained becomes unmanaged in the pods view
|
||||
if strings.HasPrefix(n.ID, MakePseudoNodeID(UncontainedID)) {
|
||||
id := MakePseudoNodeID(UnmanagedID, report.ExtractHostID(n))
|
||||
node := NewDerivedPseudoNode(id, n)
|
||||
return report.Nodes{id: node}
|
||||
func mapPodCounts(parent, original report.Node) report.Node {
|
||||
// When mapping ReplicaSets to Deployments, we want to propagate the Pods counter
|
||||
if count, ok := original.Counters.Lookup(report.Pod); ok {
|
||||
parent.Counters = parent.Counters.Add(report.Pod, count)
|
||||
}
|
||||
|
||||
// Propagate all pseudo nodes
|
||||
if n.Topology == Pseudo {
|
||||
return report.Nodes{n.ID: n}
|
||||
}
|
||||
|
||||
// Ignore non-running containers
|
||||
if state, ok := n.Latest.Lookup(docker.ContainerState); ok && state != docker.StateRunning {
|
||||
return report.Nodes{}
|
||||
}
|
||||
|
||||
// Ignore pause containers
|
||||
if image, ok := n.Latest.Lookup(docker.ImageName); ok && kubernetes.IsPauseImageName(image) {
|
||||
return report.Nodes{}
|
||||
}
|
||||
|
||||
// Otherwise, if some some reason the container doesn't have a pod uid (maybe
|
||||
// slightly out of sync reports, or its not in a pod), make it part of unmanaged.
|
||||
uid, ok := n.Latest.Lookup(docker.LabelPrefix + "io.kubernetes.pod.uid")
|
||||
if !ok {
|
||||
id := MakePseudoNodeID(UnmanagedID, report.ExtractHostID(n))
|
||||
node := NewDerivedPseudoNode(id, n)
|
||||
return report.Nodes{id: node}
|
||||
}
|
||||
|
||||
id := report.MakePodNodeID(uid)
|
||||
node := NewDerivedNode(id, n).
|
||||
WithTopology(report.Pod)
|
||||
node.Counters = node.Counters.Add(n.Topology, 1)
|
||||
return report.Nodes{id: node}
|
||||
return parent
|
||||
}
|
||||
|
||||
// MapPod2IP maps pod nodes to their IP address. This allows pods to
|
||||
@@ -152,42 +121,50 @@ func MapPod2IP(m report.Node) []string {
|
||||
return []string{report.MakeScopedEndpointNodeID("", ip, "")}
|
||||
}
|
||||
|
||||
// The various ways of grouping pods
|
||||
var (
|
||||
Map2Service = Map2Parent(report.Service)
|
||||
Map2Deployment = Map2Parent(report.Deployment)
|
||||
Map2ReplicaSet = Map2Parent(report.ReplicaSet)
|
||||
)
|
||||
|
||||
// Map2Parent maps Nodes to some parent grouping.
|
||||
func Map2Parent(topology string) func(n report.Node, _ report.Networks) report.Nodes {
|
||||
// Map2Parent returns a MapFunc which maps Nodes to some parent grouping.
|
||||
func Map2Parent(
|
||||
// The topology ID of the parents
|
||||
topology string,
|
||||
// Either the ID prefix of the pseudo node to use for nodes without
|
||||
// any parents in the group, eg. UnmanagedID, or "" to drop nodes without any parents.
|
||||
noParentsPseudoID string,
|
||||
// Optional (can be nil) function to modify any parent nodes,
|
||||
// eg. to copy over details from the original node.
|
||||
modifyMappedNode func(parent, original report.Node) report.Node,
|
||||
) MapFunc {
|
||||
return func(n report.Node, _ report.Networks) report.Nodes {
|
||||
// Uncontained becomes Unmanaged/whatever if noParentsPseudoID is set
|
||||
if noParentsPseudoID != "" && strings.HasPrefix(n.ID, MakePseudoNodeID(UncontainedID)) {
|
||||
id := MakePseudoNodeID(noParentsPseudoID, report.ExtractHostID(n))
|
||||
node := NewDerivedPseudoNode(id, n)
|
||||
return report.Nodes{id: node}
|
||||
}
|
||||
|
||||
// Propagate all pseudo nodes
|
||||
if n.Topology == Pseudo {
|
||||
return report.Nodes{n.ID: n}
|
||||
}
|
||||
|
||||
// Otherwise, if some some reason the node doesn't have any of these ids
|
||||
// (maybe slightly out of sync reports, or its not in this group), just
|
||||
// drop it
|
||||
// If some some reason the node doesn't have any of these ids
|
||||
// (maybe slightly out of sync reports, or its not in this group),
|
||||
// either drop it or put it in Uncontained/Unmanaged/whatever if one was given
|
||||
groupIDs, ok := n.Parents.Lookup(topology)
|
||||
if !ok {
|
||||
return report.Nodes{}
|
||||
if !ok || len(groupIDs) == 0 {
|
||||
if noParentsPseudoID == "" {
|
||||
return report.Nodes{}
|
||||
}
|
||||
id := MakePseudoNodeID(UnmanagedID, report.ExtractHostID(n))
|
||||
node := NewDerivedPseudoNode(id, n)
|
||||
return report.Nodes{id: node}
|
||||
}
|
||||
|
||||
result := report.Nodes{}
|
||||
for _, id := range groupIDs {
|
||||
node := NewDerivedNode(id, n).WithTopology(topology)
|
||||
node.Counters = node.Counters.Add(n.Topology, 1)
|
||||
|
||||
// When mapping replica(tionController)s(ets) to deployments
|
||||
// we must propagate the pod counter.
|
||||
if n.Topology != report.Pod {
|
||||
if count, ok := n.Counters.Lookup(report.Pod); ok {
|
||||
node.Counters = node.Counters.Add(report.Pod, count)
|
||||
}
|
||||
if modifyMappedNode != nil {
|
||||
node = modifyMappedNode(node, n)
|
||||
}
|
||||
|
||||
result[id] = node
|
||||
}
|
||||
return result
|
||||
|
||||
Reference in New Issue
Block a user