Skip to content

Commit

Permalink
Add filters for pseudo nodes.
Browse files Browse the repository at this point in the history
- Don't filter the internet node as a pseudo node.
- Rename pseudo filter to unmanaged/uncontained.
- Review feedback
- Move the FilterFoo funcs into the tests
- Drop the 'nodes' from filter labels.
  • Loading branch information
tomwilkie committed Jun 16, 2016
1 parent 4e03a30 commit 575805c
Show file tree
Hide file tree
Showing 14 changed files with 134 additions and 95 deletions.
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
}

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
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 @@ -58,6 +58,26 @@ var ContainerRenderer = MakeFilter(
),
)

// 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

0 comments on commit 575805c

Please sign in to comment.