Decorators, begone!

Decorators were just a complicated way of constructing filters.
This commit is contained in:
Matthias Radestock
2017-11-21 20:16:30 +00:00
parent 093857f37f
commit 88e8b52d66
9 changed files with 65 additions and 122 deletions

View File

@@ -15,18 +15,10 @@ import (
"github.com/weaveworks/scope/test/utils"
)
// FilterApplication is a Renderer which filters out application nodes.
func FilterApplication(r render.Renderer) render.Renderer {
return render.MakeFilter(render.IsApplication, r)
}
// FilterSystem is a Renderer which filters out system nodes.
func FilterSystem(r render.Renderer) render.Renderer {
return render.MakeFilter(render.IsSystem, r)
}
// FilterNoop does nothing.
func FilterNoop(r render.Renderer) render.Renderer { return r }
var (
filterApplication = render.AnyFilterFunc(render.IsPseudoTopology, render.IsApplication)
filterSystem = render.AnyFilterFunc(render.IsPseudoTopology, render.IsSystem)
)
func TestMapProcess2Container(t *testing.T) {
for _, input := range []testcase{
@@ -70,12 +62,10 @@ func TestContainerFilterRenderer(t *testing.T) {
// tag on of the containers in the topology and ensure
// it is filtered out correctly.
input := fixture.Report.Copy()
input.Container.Nodes[fixture.ClientContainerNodeID] = input.Container.Nodes[fixture.ClientContainerNodeID].WithLatests(map[string]string{
docker.LabelPrefix + "works.weave.role": "system",
})
have := utils.Prune(render.Decorate(input, render.ContainerWithImageNameRenderer, FilterApplication).Nodes)
have := utils.Prune(render.Render(input, render.ContainerWithImageNameRenderer, filterApplication).Nodes)
want := utils.Prune(expected.RenderedContainers.Copy())
delete(want, fixture.ClientContainerNodeID)
if !reflect.DeepEqual(want, have) {
@@ -84,7 +74,7 @@ func TestContainerFilterRenderer(t *testing.T) {
}
func TestContainerHostnameRenderer(t *testing.T) {
have := utils.Prune(render.Decorate(fixture.Report, render.ContainerHostnameRenderer, FilterNoop).Nodes)
have := utils.Prune(render.Render(fixture.Report, render.ContainerHostnameRenderer, nil).Nodes)
want := utils.Prune(expected.RenderedContainerHostnames)
if !reflect.DeepEqual(want, have) {
t.Error(test.Diff(want, have))
@@ -92,7 +82,7 @@ func TestContainerHostnameRenderer(t *testing.T) {
}
func TestContainerHostnameFilterRenderer(t *testing.T) {
have := utils.Prune(render.Decorate(fixture.Report, render.ContainerHostnameRenderer, FilterSystem).Nodes)
have := utils.Prune(render.Render(fixture.Report, render.ContainerHostnameRenderer, filterSystem).Nodes)
want := utils.Prune(expected.RenderedContainerHostnames.Copy())
delete(want, fixture.ClientContainerHostname)
delete(want, fixture.ServerContainerHostname)
@@ -103,7 +93,7 @@ func TestContainerHostnameFilterRenderer(t *testing.T) {
}
func TestContainerImageRenderer(t *testing.T) {
have := utils.Prune(render.Decorate(fixture.Report, render.ContainerImageRenderer, FilterNoop).Nodes)
have := utils.Prune(render.Render(fixture.Report, render.ContainerImageRenderer, nil).Nodes)
want := utils.Prune(expected.RenderedContainerImages)
if !reflect.DeepEqual(want, have) {
t.Error(test.Diff(want, have))
@@ -111,7 +101,7 @@ func TestContainerImageRenderer(t *testing.T) {
}
func TestContainerImageFilterRenderer(t *testing.T) {
have := utils.Prune(render.Decorate(fixture.Report, render.ContainerImageRenderer, FilterSystem).Nodes)
have := utils.Prune(render.Render(fixture.Report, render.ContainerImageRenderer, filterSystem).Nodes)
want := utils.Prune(expected.RenderedContainerHostnames.Copy())
delete(want, fixture.ClientContainerHostname)
delete(want, fixture.ServerContainerHostname)

View File

@@ -106,22 +106,6 @@ func MakeFilterPseudo(f FilterFunc, r Renderer) Renderer {
}
}
// MakeFilterDecorator makes a decorator that filters out non-pseudo nodes
// which match the predicate.
func MakeFilterDecorator(f FilterFunc) Decorator {
return func(renderer Renderer) Renderer {
return MakeFilter(f, renderer)
}
}
// MakeFilterPseudoDecorator makes a decorator that filters out all nodes
// (including pseudo nodes) which match the predicate.
func MakeFilterPseudoDecorator(f FilterFunc) Decorator {
return func(renderer Renderer) Renderer {
return MakeFilterPseudo(f, renderer)
}
}
// Render implements Renderer
func (f Filter) Render(rpt report.Report) Nodes {
return f.render(rpt)

View File

@@ -9,13 +9,8 @@ import (
"github.com/weaveworks/scope/test/reflect"
)
func isNotBar(renderer render.Renderer) render.Renderer {
return &render.Filter{
FilterFunc: func(node report.Node) bool {
return node.ID != "bar"
},
Renderer: renderer,
}
func isNotBar(node report.Node) bool {
return node.ID != "bar"
}
func TestFilterRender(t *testing.T) {
@@ -25,7 +20,7 @@ func TestFilterRender(t *testing.T) {
"baz": report.MakeNode("baz"),
}}
have := report.MakeIDList()
for id := range render.Decorate(report.MakeReport(), renderer, render.FilterUnconnected).Nodes {
for id := range render.Render(report.MakeReport(), render.ColorConnected(renderer), render.IsConnected).Nodes {
have = have.Add(id)
}
want := report.MakeIDList("foo", "bar")
@@ -41,7 +36,7 @@ func TestFilterRender2(t *testing.T) {
"bar": report.MakeNode("bar").WithAdjacent("foo"),
"baz": report.MakeNode("baz"),
}}
have := render.Decorate(report.MakeReport(), renderer, isNotBar).Nodes
have := render.Render(report.MakeReport(), renderer, isNotBar).Nodes
if have["foo"].Adjacency.Contains("bar") {
t.Error("adjacencies for removed nodes should have been removed")
}
@@ -57,16 +52,8 @@ func TestFilterUnconnectedPseudoNodes(t *testing.T) {
"baz": report.MakeNode("baz").WithTopology(render.Pseudo),
}
renderer := mockRenderer{Nodes: nodes}
filter := func(renderer render.Renderer) render.Renderer {
return &render.Filter{
FilterFunc: func(node report.Node) bool {
return true
},
Renderer: renderer,
}
}
want := nodes
have := render.Decorate(report.MakeReport(), renderer, filter).Nodes
have := render.Render(report.MakeReport(), renderer, nil).Nodes
if !reflect.DeepEqual(want, have) {
t.Error(test.Diff(want, have))
}
@@ -77,7 +64,7 @@ func TestFilterUnconnectedPseudoNodes(t *testing.T) {
"bar": report.MakeNode("bar").WithAdjacent("baz"),
"baz": report.MakeNode("baz").WithTopology(render.Pseudo),
}}
have := render.Decorate(report.MakeReport(), renderer, isNotBar).Nodes
have := render.Render(report.MakeReport(), renderer, isNotBar).Nodes
if _, ok := have["baz"]; ok {
t.Error("expected the unconnected pseudonode baz to have been removed")
}
@@ -88,7 +75,7 @@ func TestFilterUnconnectedPseudoNodes(t *testing.T) {
"bar": report.MakeNode("bar").WithAdjacent("foo"),
"baz": report.MakeNode("baz").WithTopology(render.Pseudo).WithAdjacent("bar"),
}}
have := render.Decorate(report.MakeReport(), renderer, isNotBar).Nodes
have := render.Render(report.MakeReport(), renderer, isNotBar).Nodes
if _, ok := have["baz"]; ok {
t.Error("expected the unconnected pseudonode baz to have been removed")
}
@@ -102,7 +89,7 @@ func TestFilterUnconnectedSelf(t *testing.T) {
"foo": report.MakeNode("foo").WithAdjacent("foo"),
}
renderer := mockRenderer{Nodes: nodes}
have := render.Decorate(report.MakeReport(), renderer, render.FilterUnconnected).Nodes
have := render.Render(report.MakeReport(), render.ColorConnected(renderer), render.IsConnected).Nodes
if len(have) > 0 {
t.Error("expected node only connected to self to be removed")
}

View File

@@ -20,9 +20,7 @@ func TestPodRenderer(t *testing.T) {
}
}
func filterNonKubeSystem(renderer render.Renderer) render.Renderer {
return render.MakeFilter(render.Complement(render.IsNamespace("kube-system")), renderer)
}
var filterNonKubeSystem = render.Complement(render.IsNamespace("kube-system"))
func TestPodFilterRenderer(t *testing.T) {
// tag on containers or pod namespace in the topology and ensure
@@ -32,7 +30,7 @@ func TestPodFilterRenderer(t *testing.T) {
kubernetes.Namespace: "kube-system",
})
have := utils.Prune(render.Decorate(input, render.PodRenderer, filterNonKubeSystem).Nodes)
have := utils.Prune(render.Render(input, render.PodRenderer, filterNonKubeSystem).Nodes)
want := utils.Prune(expected.RenderedPods.Copy())
delete(want, fixture.ClientPodNodeID)
if !reflect.DeepEqual(want, have) {
@@ -56,7 +54,7 @@ func TestPodServiceFilterRenderer(t *testing.T) {
kubernetes.Namespace: "kube-system",
})
have := utils.Prune(render.Decorate(input, render.PodServiceRenderer, filterNonKubeSystem).Nodes)
have := utils.Prune(render.Render(input, render.PodServiceRenderer, filterNonKubeSystem).Nodes)
want := utils.Prune(expected.RenderedPodServices.Copy())
delete(want, fixture.ServiceNodeID)
delete(want, render.IncomingInternetID)

View File

@@ -29,10 +29,10 @@ func (r Nodes) Merge(o Nodes) Nodes {
}
}
// Decorate renders the report with a decorated renderer
func Decorate(rpt report.Report, renderer Renderer, dct Decorator) Nodes {
if dct != nil {
renderer = dct(renderer)
// Render renders the report and then applies the filter
func Render(rpt report.Report, renderer Renderer, filter FilterFunc) Nodes {
if filter != nil {
renderer = MakeFilterPseudo(filter, renderer)
}
return renderer.Render(rpt)
}
@@ -119,19 +119,6 @@ func (m Map) Render(rpt report.Report) Nodes {
return Nodes{Nodes: output}
}
// Decorator transforms one renderer to another. e.g. Filters.
type Decorator func(Renderer) Renderer
// ComposeDecorators composes decorators into one.
func ComposeDecorators(decorators ...Decorator) Decorator {
return func(r Renderer) Renderer {
for _, decorator := range decorators {
r = decorator(r)
}
return r
}
}
func propagateLatest(key string, from, to report.Node) report.Node {
if value, timestamp, ok := from.Latest.LookupEntry(key); ok {
to.Latest = to.Latest.Set(key, timestamp, value)