diff --git a/app/api_topologies.go b/app/api_topologies.go index e4c6eafaf..684801e45 100644 --- a/app/api_topologies.go +++ b/app/api_topologies.go @@ -227,7 +227,7 @@ func MakeRegistry() *Registry { }, APITopologyDesc{ id: containersID, - renderer: render.ContainerWithImageNameRenderer, + renderer: render.FilterUnconnectedPseudo(render.ContainerWithImageNameRenderer), Name: "Containers", Rank: 2, Options: containerFilters, @@ -235,20 +235,20 @@ func MakeRegistry() *Registry { APITopologyDesc{ id: containersByHostnameID, parent: containersID, - renderer: render.ContainerHostnameRenderer, + renderer: render.FilterUnconnectedPseudo(render.ContainerHostnameRenderer), Name: "by DNS name", Options: containerFilters, }, APITopologyDesc{ id: containersByImageID, parent: containersID, - renderer: render.ContainerImageRenderer, + renderer: render.FilterUnconnectedPseudo(render.ContainerImageRenderer), Name: "by image", Options: containerFilters, }, APITopologyDesc{ id: podsID, - renderer: render.PodRenderer, + renderer: render.FilterUnconnectedPseudo(render.PodRenderer), Name: "Pods", Rank: 3, Options: []APITopologyOptionGroup{unmanagedFilter}, @@ -257,7 +257,7 @@ func MakeRegistry() *Registry { APITopologyDesc{ id: replicaSetsID, parent: podsID, - renderer: render.ReplicaSetRenderer, + renderer: render.FilterUnconnectedPseudo(render.ReplicaSetRenderer), Name: "replica sets", Options: []APITopologyOptionGroup{unmanagedFilter}, HideIfEmpty: true, @@ -265,7 +265,7 @@ func MakeRegistry() *Registry { APITopologyDesc{ id: kubeControllersID, parent: podsID, - renderer: render.KubeControllerRenderer, + renderer: render.FilterUnconnectedPseudo(render.KubeControllerRenderer), Name: "controllers", Options: []APITopologyOptionGroup{unmanagedFilter, k8sControllersTypeFilter}, HideIfEmpty: true, @@ -273,14 +273,14 @@ func MakeRegistry() *Registry { APITopologyDesc{ id: servicesID, parent: podsID, - renderer: render.PodServiceRenderer, + renderer: render.FilterUnconnectedPseudo(render.PodServiceRenderer), Name: "services", Options: []APITopologyOptionGroup{unmanagedFilter}, HideIfEmpty: true, }, APITopologyDesc{ id: ecsTasksID, - renderer: render.ECSTaskRenderer, + renderer: render.FilterUnconnectedPseudo(render.ECSTaskRenderer), Name: "Tasks", Rank: 3, Options: []APITopologyOptionGroup{unmanagedFilter}, @@ -289,14 +289,14 @@ func MakeRegistry() *Registry { APITopologyDesc{ id: ecsServicesID, parent: ecsTasksID, - renderer: render.ECSServiceRenderer, + renderer: render.FilterUnconnectedPseudo(render.ECSServiceRenderer), Name: "services", Options: []APITopologyOptionGroup{unmanagedFilter}, HideIfEmpty: true, }, APITopologyDesc{ id: swarmServicesID, - renderer: render.SwarmServiceRenderer, + renderer: render.FilterUnconnectedPseudo(render.SwarmServiceRenderer), Name: "services", Rank: 3, Options: []APITopologyOptionGroup{unmanagedFilter}, @@ -304,14 +304,14 @@ func MakeRegistry() *Registry { }, APITopologyDesc{ id: hostsID, - renderer: render.HostRenderer, + renderer: render.FilterUnconnectedPseudo(render.HostRenderer), Name: "Hosts", Rank: 4, }, APITopologyDesc{ id: weaveID, parent: hostsID, - renderer: render.WeaveRenderer, + renderer: render.FilterUnconnectedPseudo(render.WeaveRenderer), Name: "Weave Net", }, ) diff --git a/render/container.go b/render/container.go index dbec44a0d..e50673ad1 100644 --- a/render/container.go +++ b/render/container.go @@ -45,13 +45,7 @@ var ContainerRenderer = MakeFilter( ), ) -var mapEndpoint2IP = MakeMap( - endpoint2IP, - // We drop endpoint nodes which were procspied, as they will be - // joined to containers through the process topology, and we don't - // want to double count edges. - MakeFilter(Complement(procspied), SelectEndpoint), -) +var mapEndpoint2IP = MakeMap(endpoint2IP, SelectEndpoint) const originalNodeID = "original_node_id" const originalNodeTopology = "original_node_topology" @@ -74,13 +68,13 @@ func ConnectionJoin(r Renderer, toIPs func(report.Node) []string) Renderer { return result } - return FilterUnconnected(MakeMap( + return MakeMap( ipToNode, MakeReduce( MakeMap(nodeToIP, r), mapEndpoint2IP, ), - )) + ) } func ipToNode(n report.Node, _ report.Networks) report.Nodes { @@ -121,8 +115,11 @@ func endpoint2IP(m report.Node, local report.Networks) report.Nodes { return report.Nodes{} } - if externalNode, ok := NewDerivedExternalNode(m, addr, local); ok { - return report.Nodes{externalNode.ID: externalNode} + // Nodes without a hostid may be pseudo nodes + if _, ok := m.Latest.Lookup(report.HostNodeID); !ok { + if externalNode, ok := NewDerivedExternalNode(m, addr, local); ok { + return report.Nodes{externalNode.ID: externalNode} + } } // We also allow for joining on ip:port pairs. This is useful for diff --git a/render/filters.go b/render/filters.go index 8cf384618..bfc235a16 100644 --- a/render/filters.go +++ b/render/filters.go @@ -5,7 +5,6 @@ import ( "github.com/weaveworks/common/mtime" "github.com/weaveworks/scope/probe/docker" - "github.com/weaveworks/scope/probe/endpoint" "github.com/weaveworks/scope/probe/kubernetes" "github.com/weaveworks/scope/report" ) @@ -216,7 +215,7 @@ func Complement(f FilterFunc) FilterFunc { // FilterUnconnected produces a renderer that filters unconnected nodes // from the given renderer func FilterUnconnected(r Renderer) Renderer { - return MakeFilter( + return MakeFilterPseudo( func(node report.Node) bool { _, ok := node.Latest.Lookup(IsConnected) return ok @@ -225,6 +224,21 @@ func FilterUnconnected(r Renderer) Renderer { ) } +// FilterUnconnectedPseudo produces a renderer that filters +// unconnected pseudo nodes from the given renderer +func FilterUnconnectedPseudo(r Renderer) Renderer { + return MakeFilterPseudo( + func(node report.Node) bool { + if !IsPseudoTopology(node) { + return true + } + _, ok := node.Latest.Lookup(IsConnected) + return ok + }, + ColorConnected(r), + ) +} + // Noop allows all nodes through func Noop(_ report.Node) bool { return true } @@ -237,25 +251,6 @@ func IsRunning(n report.Node) bool { // IsStopped checks if the node is *not* a running docker container var IsStopped = Complement(IsRunning) -func procspied(node report.Node) bool { - _, ok := node.Latest.Lookup(endpoint.Procspied) - return ok -} - -func procspiedOrEBPF(node report.Node) bool { - if procspied(node) { - return true - } - _, ok := node.Latest.Lookup(endpoint.EBPF) - return ok -} - -// FilterProcspiedOrEBPF keeps only endpoints which were found via -// procspy or eBPF. -func FilterProcspiedOrEBPF(r Renderer) Renderer { - return MakeFilter(procspiedOrEBPF, r) -} - // IsApplication checks if the node is an "application" node func IsApplication(n report.Node) bool { containerName, _ := n.Latest.Lookup(docker.ContainerName) diff --git a/render/process.go b/render/process.go index 1f19c8c60..c6ce509b7 100644 --- a/render/process.go +++ b/render/process.go @@ -22,7 +22,7 @@ func renderProcesses(rpt report.Report) bool { } // EndpointRenderer is a Renderer which produces a renderable endpoint graph. -var EndpointRenderer = FilterProcspiedOrEBPF(SelectEndpoint) +var EndpointRenderer = SelectEndpoint // ProcessRenderer is a Renderer which produces a renderable process // graph by merging the endpoint graph and the process topology.