Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add filters for pseudo nodes. #1581

Merged
merged 2 commits into from
Jun 16, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 41 additions & 19 deletions app/api_topologies.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@ var (
topologyRegistry = &registry{
items: map[string]APITopologyDesc{},
}
k8sPseudoFilter = APITopologyOptionGroup{
ID: "pseudo",
Default: "show",
Options: []APITopologyOption{
{"show", "Show Unmanaged", nil, false},
{"hide", "Hide Unmanaged", render.IsNotPseudo, true},
},
}
)

func init() {
Expand All @@ -29,18 +37,26 @@ func init() {
ID: "system",
Default: "application",
Options: []APITopologyOption{
{"system", "System containers", render.IsSystem},
{"application", "Application containers", render.IsApplication},
{"both", "Both", nil},
{"system", "System containers", render.IsSystem, false},
{"application", "Application containers", render.IsApplication, false},
{"both", "Both", nil, false},
},
},
{
ID: "stopped",
Default: "running",
Options: []APITopologyOption{
{"stopped", "Stopped containers", render.IsStopped},
{"running", "Running containers", render.IsRunning},
{"both", "Both", nil},
{"stopped", "Stopped containers", render.IsStopped, false},
{"running", "Running containers", render.IsRunning, false},
{"both", "Both", nil, false},
},
},
{
ID: "pseudo",
Default: "show",
Options: []APITopologyOption{
{"show", "Show Uncontained", nil, false},
{"hide", "Hide Uncontained", render.IsNotPseudo, true},
},
},
}
Expand All @@ -52,7 +68,7 @@ func init() {
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", nil},
{"hide", "Unconnected nodes hidden", nil, false},
},
},
}
Expand Down Expand Up @@ -142,9 +158,11 @@ func kubernetesFilters(namespaces ...string) APITopologyOptionGroup {
if namespace == "default" {
options.Default = namespace
}
options.Options = append(options.Options, APITopologyOption{namespace, namespace, render.IsNamespace(namespace)})
options.Options = append(options.Options, APITopologyOption{
namespace, namespace, render.IsNamespace(namespace), false,
})
}
options.Options = append(options.Options, APITopologyOption{"all", "All Namespaces", nil})
options.Options = append(options.Options, APITopologyOption{"all", "All Namespaces", nil, false})
return options
}

Expand All @@ -169,7 +187,9 @@ func updateFilters(rpt report.Report, topologies []APITopologyDesc) []APITopolog
sort.Strings(ns)
for i, t := range topologies {
if t.id == "pods" || t.id == "services" || t.id == "deployments" || t.id == "replica-sets" {
topologies[i] = updateTopologyFilters(t, []APITopologyOptionGroup{kubernetesFilters(ns...)})
topologies[i] = updateTopologyFilters(t, []APITopologyOptionGroup{
kubernetesFilters(ns...), k8sPseudoFilter,
})
}
}
return topologies
Expand Down Expand Up @@ -224,7 +244,8 @@ type APITopologyOption struct {
Value string `json:"value"`
Label string `json:"label"`

filter render.FilterFunc
filter render.FilterFunc
filterPseudo bool

This comment was marked as abuse.

}

type topologyStats struct {
Expand Down Expand Up @@ -329,25 +350,26 @@ func (r *registry) rendererForTopology(topologyID string, values url.Values, rpt
}
topology = updateFilters(rpt, []APITopologyDesc{topology})[0]

var filters []render.FilterFunc
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) {
filters = append(filters, opt.filter)
if opt.filterPseudo {
decorators = append(decorators, render.MakeFilterPseudoDecorator(opt.filter))
} else {
decorators = append(decorators, render.MakeFilterDecorator(opt.filter))
}
}
}
}
var decorator render.Decorator
if len(filters) > 0 {
decorator = func(renderer render.Renderer) render.Renderer {
return render.MakeFilter(render.ComposeFilterFuncs(filters...), renderer)
}
if len(decorators) > 0 {
return topology.renderer, render.ComposeDecorators(decorators...), nil
}
return topology.renderer, decorator, nil
return topology.renderer, nil, nil
}

type reporterHandler func(context.Context, Reporter, http.ResponseWriter, *http.Request)
Expand Down
2 changes: 1 addition & 1 deletion experimental/graphviz/render.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,5 @@ func renderTo(rpt report.Report, topology string) (detailed.NodeSummaries, error
if !ok {
return detailed.NodeSummaries{}, fmt.Errorf("unknown topology %v", topology)
}
return detailed.Summaries(rpt, renderer.Render(rpt, render.FilterNoop)), nil
return detailed.Summaries(rpt, renderer.Render(rpt, nil)), nil
}
4 changes: 2 additions & 2 deletions render/benchmark_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func benchmarkRender(b *testing.B, r render.Renderer) {
b.StopTimer()
render.ResetCache()
b.StartTimer()
benchmarkRenderResult = r.Render(report, render.FilterNoop)
benchmarkRenderResult = r.Render(report, FilterNoop)
if len(benchmarkRenderResult) == 0 {
b.Errorf("Rendered topology contained no nodes")
}
Expand All @@ -94,7 +94,7 @@ func benchmarkStats(b *testing.B, r render.Renderer) {
b.StopTimer()
render.ResetCache()
b.StartTimer()
benchmarkStatsResult = r.Stats(report, render.FilterNoop)
benchmarkStatsResult = r.Stats(report, FilterNoop)
}
}

Expand Down
20 changes: 20 additions & 0 deletions render/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,26 @@ func ShortLivedConnectionJoin(r Renderer, toIPs func(report.Node) []string) Rend
))
}

// FilterEmpty is a Renderer which filters out nodes which have no children
// from the specified topology.
func FilterEmpty(topology string, r Renderer) Renderer {
return MakeFilter(HasChildren(topology), r)
}

// HasChildren returns true if the node has no children from the specified
// topology.
func HasChildren(topology string) FilterFunc {
return func(n report.Node) bool {
count := 0
n.Children.ForEach(func(child report.Node) {
if child.Topology == topology {
count++
}
})
return count > 0
}
}

type containerWithImageNameRenderer struct {
Renderer
}
Expand Down
20 changes: 14 additions & 6 deletions render/container_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@ import (
"github.com/weaveworks/scope/test/reflect"
)

// FilterApplication is a Renderer which filters out application nodes.
func FilterApplication(r render.Renderer) render.Renderer {
return render.MakeFilter(render.IsApplication, r)
}

// FilterNoop does nothing.
func FilterNoop(r render.Renderer) render.Renderer { return r }

func TestMapProcess2Container(t *testing.T) {
for _, input := range []testcase{
{"empty", report.MakeNode("empty"), true},
Expand Down Expand Up @@ -47,7 +55,7 @@ func testMap(t *testing.T, f render.MapFunc, input testcase) {
}

func TestContainerRenderer(t *testing.T) {
have := Prune(render.ContainerWithImageNameRenderer.Render(fixture.Report, render.FilterNoop))
have := Prune(render.ContainerWithImageNameRenderer.Render(fixture.Report, FilterNoop))
want := Prune(expected.RenderedContainers)
if !reflect.DeepEqual(want, have) {
t.Error(test.Diff(want, have))
Expand All @@ -61,7 +69,7 @@ func TestContainerFilterRenderer(t *testing.T) {
input.Container.Nodes[fixture.ClientContainerNodeID] = input.Container.Nodes[fixture.ClientContainerNodeID].WithLatests(map[string]string{
docker.LabelPrefix + "works.weave.role": "system",
})
have := Prune(render.ContainerWithImageNameRenderer.Render(input, render.FilterApplication))
have := Prune(render.ContainerWithImageNameRenderer.Render(input, FilterApplication))
want := Prune(expected.RenderedContainers.Copy())
delete(want, fixture.ClientContainerNodeID)
if !reflect.DeepEqual(want, have) {
Expand All @@ -70,7 +78,7 @@ func TestContainerFilterRenderer(t *testing.T) {
}

func TestContainerHostnameRenderer(t *testing.T) {
have := Prune(render.ContainerHostnameRenderer.Render(fixture.Report, render.FilterNoop))
have := Prune(render.ContainerHostnameRenderer.Render(fixture.Report, FilterNoop))
want := Prune(expected.RenderedContainerHostnames)
if !reflect.DeepEqual(want, have) {
t.Error(test.Diff(want, have))
Expand All @@ -93,7 +101,7 @@ func TestContainerHostnameFilterRenderer(t *testing.T) {
Add("host", report.MakeStringSet(fixture.ClientHostNodeID)),
).WithTopology(report.Container))

have := Prune(render.ContainerHostnameRenderer.Render(input, render.FilterApplication))
have := Prune(render.ContainerHostnameRenderer.Render(input, FilterApplication))
want := Prune(expected.RenderedContainerHostnames)
// Test works by virtue of the RenderedContainerHostname only having a container
// counter == 1
Expand All @@ -104,7 +112,7 @@ func TestContainerHostnameFilterRenderer(t *testing.T) {
}

func TestContainerImageRenderer(t *testing.T) {
have := Prune(render.ContainerImageRenderer.Render(fixture.Report, render.FilterNoop))
have := Prune(render.ContainerImageRenderer.Render(fixture.Report, FilterNoop))
want := Prune(expected.RenderedContainerImages)
if !reflect.DeepEqual(want, have) {
t.Error(test.Diff(want, have))
Expand All @@ -129,7 +137,7 @@ func TestContainerImageFilterRenderer(t *testing.T) {
Add("host", report.MakeStringSet(fixture.ClientHostNodeID)),
).WithTopology(report.ContainerImage))

have := Prune(render.ContainerImageRenderer.Render(input, render.FilterApplication))
have := Prune(render.ContainerImageRenderer.Render(input, FilterApplication))
want := Prune(expected.RenderedContainerImages.Copy())
// Test works by virtue of the RenderedContainerImage only having a container
// counter == 1
Expand Down
8 changes: 4 additions & 4 deletions render/detailed/node_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@ import (
)

func child(t *testing.T, r render.Renderer, id string) detailed.NodeSummary {
s, ok := detailed.MakeNodeSummary(fixture.Report, r.Render(fixture.Report, render.FilterNoop)[id])
s, ok := detailed.MakeNodeSummary(fixture.Report, r.Render(fixture.Report, nil)[id])
if !ok {
t.Fatalf("Expected node %s to be summarizable, but wasn't", id)
}
return s.SummarizeMetrics()
}

func TestMakeDetailedHostNode(t *testing.T) {
renderableNodes := render.HostRenderer.Render(fixture.Report, render.FilterNoop)
renderableNodes := render.HostRenderer.Render(fixture.Report, nil)
renderableNode := renderableNodes[fixture.ClientHostNodeID]
have := detailed.MakeNode("hosts", fixture.Report, renderableNodes, renderableNode)

Expand Down Expand Up @@ -177,7 +177,7 @@ func TestMakeDetailedHostNode(t *testing.T) {

func TestMakeDetailedContainerNode(t *testing.T) {
id := fixture.ServerContainerNodeID
renderableNodes := render.ContainerWithImageNameRenderer.Render(fixture.Report, render.FilterNoop)
renderableNodes := render.ContainerWithImageNameRenderer.Render(fixture.Report, nil)
renderableNode, ok := renderableNodes[id]
if !ok {
t.Fatalf("Node not found: %s", id)
Expand Down Expand Up @@ -310,7 +310,7 @@ func TestMakeDetailedContainerNode(t *testing.T) {

func TestMakeDetailedPodNode(t *testing.T) {
id := fixture.ServerPodNodeID
renderableNodes := render.PodRenderer.Render(fixture.Report, render.FilterNoop)
renderableNodes := render.PodRenderer.Render(fixture.Report, nil)
renderableNode, ok := renderableNodes[id]
if !ok {
t.Fatalf("Node not found: %s", id)
Expand Down
10 changes: 5 additions & 5 deletions render/detailed/parents_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,33 +21,33 @@ func TestParents(t *testing.T) {
}{
{
name: "Node accidentally tagged with itself",
node: render.HostRenderer.Render(fixture.Report, render.FilterNoop)[fixture.ClientHostNodeID].WithParents(
node: render.HostRenderer.Render(fixture.Report, nil)[fixture.ClientHostNodeID].WithParents(
report.EmptySets.Add(report.Host, report.MakeStringSet(fixture.ClientHostNodeID)),
),
want: nil,
},
{
node: render.HostRenderer.Render(fixture.Report, render.FilterNoop)[fixture.ClientHostNodeID],
node: render.HostRenderer.Render(fixture.Report, nil)[fixture.ClientHostNodeID],
want: nil,
},
{
name: "Container image",
node: render.ContainerImageRenderer.Render(fixture.Report, render.FilterNoop)[expected.ClientContainerImageNodeID],
node: render.ContainerImageRenderer.Render(fixture.Report, nil)[expected.ClientContainerImageNodeID],
want: []detailed.Parent{
{ID: fixture.ClientHostNodeID, Label: fixture.ClientHostName, TopologyID: "hosts"},
},
},
{
name: "Container",
node: render.ContainerWithImageNameRenderer.Render(fixture.Report, render.FilterNoop)[fixture.ClientContainerNodeID],
node: render.ContainerWithImageNameRenderer.Render(fixture.Report, nil)[fixture.ClientContainerNodeID],
want: []detailed.Parent{
{ID: expected.ClientContainerImageNodeID, Label: fixture.ClientContainerImageName, TopologyID: "containers-by-image"},
{ID: fixture.ClientHostNodeID, Label: fixture.ClientHostName, TopologyID: "hosts"},
{ID: fixture.ClientPodNodeID, Label: "pong-a", TopologyID: "pods"},
},
},
{
node: render.ProcessRenderer.Render(fixture.Report, render.FilterNoop)[fixture.ClientProcess1NodeID],
node: render.ProcessRenderer.Render(fixture.Report, nil)[fixture.ClientProcess1NodeID],
want: []detailed.Parent{
{ID: fixture.ClientContainerNodeID, Label: fixture.ClientContainerName, TopologyID: "containers"},
{ID: fixture.ClientHostNodeID, Label: fixture.ClientHostName, TopologyID: "hosts"},
Expand Down
4 changes: 2 additions & 2 deletions render/detailed/summary_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (
func TestSummaries(t *testing.T) {
{
// Just a convenient source of some rendered nodes
have := detailed.Summaries(fixture.Report, render.ProcessRenderer.Render(fixture.Report, render.FilterNoop))
have := detailed.Summaries(fixture.Report, render.ProcessRenderer.Render(fixture.Report, nil))
// The ids of the processes rendered above
expectedIDs := []string{
fixture.ClientProcess1NodeID,
Expand Down Expand Up @@ -51,7 +51,7 @@ func TestSummaries(t *testing.T) {
input := fixture.Report.Copy()

input.Process.Nodes[fixture.ClientProcess1NodeID] = input.Process.Nodes[fixture.ClientProcess1NodeID].WithMetrics(report.Metrics{process.CPUUsage: metric})
have := detailed.Summaries(input, render.ProcessRenderer.Render(input, render.FilterNoop))
have := detailed.Summaries(input, render.ProcessRenderer.Render(input, nil))

node, ok := have[fixture.ClientProcess1NodeID]
if !ok {
Expand Down
Loading