mirror of
https://github.com/weaveworks/scope.git
synced 2026-07-15 19:41:02 +00:00
api_topologies: Add a selectType field to option groups
This field changes the option group behaviour depending on its value. Currently only supports two values: "one" (default): Old behaviour, one option can be selected "union": Any number of options can be selected, and the filters are OR-ed togther It is written in such a way as to easily enable a future "intersection" option, as per union but AND-ing the filters. But this is not done here. YAGNI.
This commit is contained in:
@@ -5,8 +5,10 @@ import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
log "github.com/Sirupsen/logrus"
|
||||
"github.com/gorilla/mux"
|
||||
"golang.org/x/net/context"
|
||||
|
||||
@@ -295,6 +297,59 @@ type APITopologyOptionGroup struct {
|
||||
ID string `json:"id"`
|
||||
Default string `json:"defaultValue,omitempty"`
|
||||
Options []APITopologyOption `json:"options,omitempty"`
|
||||
// SelectType describes how options can be picked. Currently defined values:
|
||||
// "one": Default if empty. Exactly one option may be picked from the list.
|
||||
// "union": Any number of options may be picked. Nodes matching any option filter selected are displayed.
|
||||
// Value and Default should be a ","-seperated list.
|
||||
SelectType string `json:"selectType,omitempty"`
|
||||
}
|
||||
|
||||
// Get the render filters to use for this option group as a Decorator, if any.
|
||||
// If second arg is false, no decorator was needed.
|
||||
func (g APITopologyOptionGroup) getFilterDecorator(value string) (render.Decorator, bool) {
|
||||
if value == "" {
|
||||
value = g.Default
|
||||
}
|
||||
selectType := g.SelectType
|
||||
if selectType == "" {
|
||||
selectType = "one"
|
||||
}
|
||||
var values []string
|
||||
switch selectType {
|
||||
case "one":
|
||||
values = []string{value}
|
||||
case "union":
|
||||
values = strings.Split(value, ",")
|
||||
default:
|
||||
log.Errorf("Invalid select type %s for option group %s, ignoring option", selectType, g.ID)
|
||||
return nil, false
|
||||
}
|
||||
filters := []render.FilterFunc{}
|
||||
for _, opt := range g.Options {
|
||||
for _, v := range values {
|
||||
if v != opt.Value {
|
||||
continue
|
||||
}
|
||||
var filter render.FilterFunc
|
||||
if opt.filter == nil {
|
||||
// No filter means match everything (pseudo doesn't matter)
|
||||
filter = func(n report.Node) bool { return true }
|
||||
} else if opt.filterPseudo {
|
||||
// Apply filter to pseudo topologies also
|
||||
filter = opt.filter
|
||||
} else {
|
||||
// Allow all pseudo topology nodes, only apply filter to non-pseudo
|
||||
filter = render.AnyFilterFunc(render.IsPseudoTopology, opt.filter)
|
||||
}
|
||||
filters = append(filters, filter)
|
||||
}
|
||||
}
|
||||
if len(filters) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
// Since we've encoded whether to ignore pseudo topologies into each subfilter,
|
||||
// we want no special behaviour for pseudo topologies here, which corresponds to MakePseudo
|
||||
return render.MakeFilterPseudoDecorator(render.AnyFilterFunc(filters...)), true
|
||||
}
|
||||
|
||||
// APITopologyOption describes a ¶m=value to a given topology.
|
||||
@@ -437,17 +492,8 @@ func (r *Registry) RendererForTopology(topologyID string, values url.Values, rpt
|
||||
var decorators []render.Decorator
|
||||
for _, group := range topology.Options {
|
||||
value := values.Get(group.ID)
|
||||
for _, opt := range group.Options {
|
||||
if opt.filter == nil {
|
||||
continue
|
||||
}
|
||||
if (value == "" && group.Default == opt.Value) || (opt.Value != "" && opt.Value == value) {
|
||||
if opt.filterPseudo {
|
||||
decorators = append(decorators, render.MakeFilterPseudoDecorator(opt.filter))
|
||||
} else {
|
||||
decorators = append(decorators, render.MakeFilterDecorator(opt.filter))
|
||||
}
|
||||
}
|
||||
if decorator, ok := group.getFilterDecorator(value); ok {
|
||||
decorators = append(decorators, decorator)
|
||||
}
|
||||
}
|
||||
if len(decorators) > 0 {
|
||||
|
||||
@@ -321,6 +321,12 @@ func IsNotPseudo(n report.Node) bool {
|
||||
return n.Topology != Pseudo || strings.HasSuffix(n.ID, TheInternetID) || strings.HasPrefix(n.ID, ServiceNodeIDPrefix)
|
||||
}
|
||||
|
||||
// IsPseudoTopology returns true if the node is in a pseudo topology,
|
||||
// mimicing the check performed by MakeFilter() instead of the more complex check in IsNotPseudo()
|
||||
func IsPseudoTopology(n report.Node) bool {
|
||||
return n.Topology == Pseudo
|
||||
}
|
||||
|
||||
// IsNamespace checks if the node is a pod/service in the specified namespace
|
||||
func IsNamespace(namespace string) FilterFunc {
|
||||
return func(n report.Node) bool {
|
||||
|
||||
Reference in New Issue
Block a user