mirror of
https://github.com/weaveworks/scope.git
synced 2026-03-03 02:00:43 +00:00
backend changes for new option rendering
This commit is contained in:
committed by
David Kaltschmidt
parent
619c63a0a5
commit
430130c03a
@@ -21,14 +21,60 @@ var (
|
||||
)
|
||||
|
||||
func init() {
|
||||
containerFilters := map[string][]APITopologyOption{
|
||||
"system": {
|
||||
{"show", "System containers shown", false, render.FilterNoop},
|
||||
{"hide", "System containers hidden", true, render.FilterSystem},
|
||||
serviceFilters := []APITopologyOptionGroup{
|
||||
{
|
||||
ID: "system",
|
||||
Default: "application",
|
||||
Options: []APITopologyOption{
|
||||
{"system", "System services", render.FilterApplication},
|
||||
{"application", "Application services", render.FilterSystem},
|
||||
{"both", "Both", render.FilterNoop},
|
||||
},
|
||||
},
|
||||
"stopped": {
|
||||
{"show", "Stopped containers shown", false, render.FilterNoop},
|
||||
{"hide", "Stopped containers hidden", true, render.FilterStopped},
|
||||
}
|
||||
|
||||
podFilters := []APITopologyOptionGroup{
|
||||
{
|
||||
ID: "system",
|
||||
Default: "application",
|
||||
Options: []APITopologyOption{
|
||||
{"system", "System pods", render.FilterApplication},
|
||||
{"application", "Application pods", render.FilterSystem},
|
||||
{"both", "Both", render.FilterNoop},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
containerFilters := []APITopologyOptionGroup{
|
||||
{
|
||||
ID: "system",
|
||||
Default: "application",
|
||||
Options: []APITopologyOption{
|
||||
{"system", "System containers", render.FilterApplication},
|
||||
{"application", "Application containers", render.FilterSystem},
|
||||
{"both", "Both", render.FilterNoop},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "stopped",
|
||||
Default: "running",
|
||||
Options: []APITopologyOption{
|
||||
{"stopped", "Stopped containers", render.FilterRunning},
|
||||
{"running", "Running containers", render.FilterStopped},
|
||||
{"both", "Both", render.FilterNoop},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
unconnectedFilter := []APITopologyOptionGroup{
|
||||
{
|
||||
ID: "unconnected",
|
||||
Default: "hide",
|
||||
Options: []APITopologyOption{
|
||||
// Show the user why there are filtered nodes in this view.
|
||||
// Don't give them the option to show those nodes.
|
||||
{"hide", "Unconnected nodes hidden", render.FilterNoop},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -40,21 +86,14 @@ func init() {
|
||||
renderer: render.FilterUnconnected(render.ProcessWithContainerNameRenderer),
|
||||
Name: "Processes",
|
||||
Rank: 1,
|
||||
Options: map[string][]APITopologyOption{"unconnected": {
|
||||
// Show the user why there are filtered nodes in this view.
|
||||
// Don't give them the option to show those nodes.
|
||||
{"hide", "Unconnected nodes hidden", true, render.FilterNoop},
|
||||
}},
|
||||
Options: unconnectedFilter,
|
||||
},
|
||||
APITopologyDesc{
|
||||
id: "processes-by-name",
|
||||
parent: "processes",
|
||||
renderer: render.FilterUnconnected(render.ProcessNameRenderer),
|
||||
Name: "by name",
|
||||
Options: map[string][]APITopologyOption{"unconnected": {
|
||||
// Ditto above.
|
||||
{"hide", "Unconnected nodes hidden", true, render.FilterNoop},
|
||||
}},
|
||||
Options: unconnectedFilter,
|
||||
},
|
||||
APITopologyDesc{
|
||||
id: "containers",
|
||||
@@ -82,7 +121,6 @@ func init() {
|
||||
renderer: render.HostRenderer,
|
||||
Name: "Hosts",
|
||||
Rank: 4,
|
||||
Options: map[string][]APITopologyOption{},
|
||||
},
|
||||
APITopologyDesc{
|
||||
id: "pods",
|
||||
@@ -90,10 +128,7 @@ func init() {
|
||||
Name: "Pods",
|
||||
Rank: 3,
|
||||
HideIfEmpty: true,
|
||||
Options: map[string][]APITopologyOption{"system": {
|
||||
{"show", "System pods shown", false, render.FilterNoop},
|
||||
{"hide", "System pods hidden", true, render.FilterSystem},
|
||||
}},
|
||||
Options: podFilters,
|
||||
},
|
||||
APITopologyDesc{
|
||||
id: "pods-by-service",
|
||||
@@ -101,10 +136,7 @@ func init() {
|
||||
renderer: render.PodServiceRenderer,
|
||||
Name: "by service",
|
||||
HideIfEmpty: true,
|
||||
Options: map[string][]APITopologyOption{"system": {
|
||||
{"show", "System services shown", false, render.FilterNoop},
|
||||
{"hide", "System services hidden", true, render.FilterSystem},
|
||||
}},
|
||||
Options: serviceFilters,
|
||||
},
|
||||
)
|
||||
}
|
||||
@@ -121,10 +153,10 @@ type APITopologyDesc struct {
|
||||
parent string
|
||||
renderer render.Renderer
|
||||
|
||||
Name string `json:"name"`
|
||||
Rank int `json:"rank"`
|
||||
HideIfEmpty bool `json:"hide_if_empty"`
|
||||
Options map[string][]APITopologyOption `json:"options"`
|
||||
Name string `json:"name"`
|
||||
Rank int `json:"rank"`
|
||||
HideIfEmpty bool `json:"hide_if_empty"`
|
||||
Options []APITopologyOptionGroup `json:"options"`
|
||||
|
||||
URL string `json:"url"`
|
||||
SubTopologies []APITopologyDesc `json:"sub_topologies,omitempty"`
|
||||
@@ -137,11 +169,17 @@ func (a byName) Len() int { return len(a) }
|
||||
func (a byName) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
func (a byName) Less(i, j int) bool { return a[i].Name < a[j].Name }
|
||||
|
||||
// APITopologyOptionGroup describes a group of APITopologyOptions
|
||||
type APITopologyOptionGroup struct {
|
||||
ID string `json:"id"`
|
||||
Default string `json:"defaultValue,omitempty"`
|
||||
Options []APITopologyOption `json:"options,omitempty"`
|
||||
}
|
||||
|
||||
// APITopologyOption describes a ¶m=value to a given topology.
|
||||
type APITopologyOption struct {
|
||||
Value string `json:"value"`
|
||||
Display string `json:"display"`
|
||||
Default bool `json:"default,omitempty"`
|
||||
Value string `json:"value"`
|
||||
Label string `json:"label"`
|
||||
|
||||
decorator func(render.Renderer) render.Renderer
|
||||
}
|
||||
@@ -244,10 +282,10 @@ func decorateWithStats(rpt report.Report, renderer render.Renderer) topologyStat
|
||||
|
||||
func renderedForRequest(r *http.Request, topology APITopologyDesc) render.Renderer {
|
||||
renderer := topology.renderer
|
||||
for param, opts := range topology.Options {
|
||||
value := r.FormValue(param)
|
||||
for _, opt := range opts {
|
||||
if (value == "" && opt.Default) || (opt.Value != "" && opt.Value == value) {
|
||||
for _, group := range topology.Options {
|
||||
value := r.FormValue(group.ID)
|
||||
for _, opt := range group.Options {
|
||||
if (value == "" && group.Default == opt.Value) || (opt.Value != "" && opt.Value == value) {
|
||||
renderer = opt.decorator(renderer)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
package render
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/weaveworks/scope/probe/docker"
|
||||
"github.com/weaveworks/scope/probe/kubernetes"
|
||||
"github.com/weaveworks/scope/report"
|
||||
)
|
||||
|
||||
@@ -125,6 +121,12 @@ func (f Filter) Stats(rpt report.Report) Stats {
|
||||
// to indicate a node has an edge pointing to it or from it
|
||||
const IsConnected = "is_connected"
|
||||
|
||||
// Complement takes a FilterFunc f and returns a FilterFunc that has the same
|
||||
// effects, if any, and returns the opposite truth value.
|
||||
func Complement(f func(RenderableNode) bool) func(RenderableNode) bool {
|
||||
return func(node RenderableNode) bool { return !f(node) }
|
||||
}
|
||||
|
||||
// FilterPseudo produces a renderer that removes pseudo nodes from the given
|
||||
// renderer
|
||||
func FilterPseudo(r Renderer) Renderer {
|
||||
@@ -155,44 +157,22 @@ func FilterNoop(in Renderer) Renderer {
|
||||
|
||||
// FilterStopped filters out stopped containers.
|
||||
func FilterStopped(r Renderer) Renderer {
|
||||
return MakeFilter(
|
||||
func(node RenderableNode) bool {
|
||||
containerState, ok := node.Latest.Lookup(docker.ContainerState)
|
||||
return !ok || containerState != docker.StateStopped
|
||||
},
|
||||
r,
|
||||
)
|
||||
return MakeFilter(RenderableNode.IsStopped, r)
|
||||
}
|
||||
|
||||
// FilterRunning filters out running containers.
|
||||
func FilterRunning(r Renderer) Renderer {
|
||||
return MakeFilter(Complement(RenderableNode.IsStopped), r)
|
||||
}
|
||||
|
||||
// FilterSystem is a Renderer which filters out system nodes.
|
||||
func FilterSystem(r Renderer) Renderer {
|
||||
return MakeFilter(
|
||||
func(node RenderableNode) bool {
|
||||
containerName, _ := node.Latest.Lookup(docker.ContainerName)
|
||||
if _, ok := systemContainerNames[containerName]; ok {
|
||||
return false
|
||||
}
|
||||
imageName, _ := node.Latest.Lookup(docker.ImageName)
|
||||
imagePrefix := strings.SplitN(imageName, ":", 2)[0] // :(
|
||||
if _, ok := systemImagePrefixes[imagePrefix]; ok {
|
||||
return false
|
||||
}
|
||||
roleLabel, _ := node.Latest.Lookup(docker.LabelPrefix + "works.weave.role")
|
||||
if roleLabel == "system" {
|
||||
return false
|
||||
}
|
||||
namespace, _ := node.Latest.Lookup(kubernetes.Namespace)
|
||||
if namespace == "kube-system" {
|
||||
return false
|
||||
}
|
||||
podName, _ := node.Latest.Lookup(docker.LabelPrefix + "io.kubernetes.pod.name")
|
||||
if strings.HasPrefix(podName, "kube-system/") {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
},
|
||||
r,
|
||||
)
|
||||
return MakeFilter(RenderableNode.IsSystem, r)
|
||||
}
|
||||
|
||||
// FilterApplication is a Renderer which filters out system nodes.
|
||||
func FilterApplication(r Renderer) Renderer {
|
||||
return MakeFilter(Complement(RenderableNode.IsSystem), r)
|
||||
}
|
||||
|
||||
var systemContainerNames = map[string]struct{}{
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
package render
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/weaveworks/scope/probe/docker"
|
||||
"github.com/weaveworks/scope/probe/kubernetes"
|
||||
"github.com/weaveworks/scope/report"
|
||||
)
|
||||
|
||||
@@ -153,6 +157,38 @@ func (rn RenderableNode) Copy() RenderableNode {
|
||||
}
|
||||
}
|
||||
|
||||
// IsStopped checks if the RenderableNode is a stopped docker container.
|
||||
func (rn RenderableNode) IsStopped() bool {
|
||||
containerState, ok := rn.Latest.Lookup(docker.ContainerState)
|
||||
return !ok || containerState != docker.StateStopped
|
||||
}
|
||||
|
||||
// IsSystem checks if the RenderableNode is a system container/pod/etc.
|
||||
func (rn RenderableNode) IsSystem() bool {
|
||||
containerName, _ := rn.Latest.Lookup(docker.ContainerName)
|
||||
if _, ok := systemContainerNames[containerName]; ok {
|
||||
return false
|
||||
}
|
||||
imageName, _ := rn.Latest.Lookup(docker.ImageName)
|
||||
imagePrefix := strings.SplitN(imageName, ":", 2)[0] // :(
|
||||
if _, ok := systemImagePrefixes[imagePrefix]; ok {
|
||||
return false
|
||||
}
|
||||
roleLabel, _ := rn.Latest.Lookup(docker.LabelPrefix + "works.weave.role")
|
||||
if roleLabel == "system" {
|
||||
return false
|
||||
}
|
||||
namespace, _ := rn.Latest.Lookup(kubernetes.Namespace)
|
||||
if namespace == "kube-system" {
|
||||
return false
|
||||
}
|
||||
podName, _ := rn.Latest.Lookup(docker.LabelPrefix + "io.kubernetes.pod.name")
|
||||
if strings.HasPrefix(podName, "kube-system/") {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Prune returns a copy of the RenderableNode with all information not
|
||||
// strictly necessary for rendering nodes and edges stripped away.
|
||||
// Specifically, that means cutting out parts of the Node.
|
||||
|
||||
Reference in New Issue
Block a user