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

Remove MappedNode & generalise render logic #233

Merged
merged 2 commits into from
Jun 16, 2015
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
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ $(SCOPE_EXPORT): $(APP_EXE) $(PROBE_EXE) docker/*
$(SUDO) docker build -t $(SCOPE_IMAGE) docker/
$(SUDO) docker save $(SCOPE_IMAGE):latest | sudo $(DOCKER_SQUASH) -t $(SCOPE_IMAGE) | tee $@ | $(SUDO) docker load

$(APP_EXE): app/*.go report/*.go xfer/*.go
$(APP_EXE): app/*.go render/*.go report/*.go xfer/*.go

$(PROBE_EXE): probe/*.go probe/tag/*.go report/*.go xfer/*.go

Expand Down
4 changes: 2 additions & 2 deletions app/api_topologies.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,15 @@ func makeTopologyList(rep Reporter) func(w http.ResponseWriter, r *http.Request)
subTopologies = append(subTopologies, APITopologyDesc{
Name: subDef.human,
URL: "/api/topology/" + subName,
Stats: stats(render(rpt, subDef.maps)),
Stats: stats(subDef.renderer.Render(rpt)),
})
}
}
topologies = append(topologies, APITopologyDesc{
Name: def.human,
URL: "/api/topology/" + name,
SubTopologies: subTopologies,
Stats: stats(render(rpt, def.maps)),
Stats: stats(def.renderer.Render(rpt)),
})
}
respondWith(w, http.StatusOK, topologies)
Expand Down
21 changes: 4 additions & 17 deletions app/api_topology.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,10 @@ type APIEdge struct {
Metadata report.AggregateMetadata `json:"metadata"`
}

func render(rpt report.Report, maps []topologyMapper) report.RenderableNodes {
result := report.RenderableNodes{}
for _, m := range maps {
rns := m.selector(rpt).RenderBy(m.mapper, m.pseudo)
result.Merge(rns)
}
return result
}

// Full topology.
func handleTopology(rep Reporter, t topologyView, w http.ResponseWriter, r *http.Request) {
respondWith(w, http.StatusOK, APITopology{
Nodes: render(rep.Report(), t.maps),
Nodes: t.renderer.Render(rep.Report()),
})
}

Expand All @@ -69,7 +60,7 @@ func handleNode(rep Reporter, t topologyView, w http.ResponseWriter, r *http.Req
vars = mux.Vars(r)
nodeID = vars["id"]
rpt = rep.Report()
node, ok = render(rpt, t.maps)[nodeID]
node, ok = t.renderer.Render(rep.Report())[nodeID]
)
if !ok {
http.NotFound(w, r)
Expand All @@ -85,13 +76,9 @@ func handleEdge(rep Reporter, t topologyView, w http.ResponseWriter, r *http.Req
localID = vars["local"]
remoteID = vars["remote"]
rpt = rep.Report()
metadata = report.AggregateMetadata{}
metadata = t.renderer.AggregateMetadata(rpt, localID, remoteID)
)

for _, m := range t.maps {
metadata.Merge(m.selector(rpt).EdgeMetadata(m.mapper, localID, remoteID).Transform())
}

respondWith(w, http.StatusOK, APIEdge{Metadata: metadata})
}

Expand Down Expand Up @@ -128,7 +115,7 @@ func handleWebsocket(
tick = time.Tick(loop)
)
for {
newTopo := render(rep.Report(), t.maps)
newTopo := t.renderer.Render(rep.Report())
diff := report.TopoDiff(previousTopo, newTopo)
previousTopo = newTopo

Expand Down
53 changes: 20 additions & 33 deletions app/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

"github.com/gorilla/mux"

"github.com/weaveworks/scope/render"
"github.com/weaveworks/scope/report"
)

Expand Down Expand Up @@ -47,51 +48,37 @@ func apiHandler(w http.ResponseWriter, r *http.Request) {

var topologyRegistry = map[string]topologyView{
"applications": {
human: "Applications",
parent: "",
maps: []topologyMapper{
{report.SelectEndpoint, report.ProcessPID, report.GenericPseudoNode},
},
human: "Applications",
parent: "",
renderer: render.Map{Selector: report.SelectEndpoint, Mapper: report.ProcessPID, Pseudo: report.GenericPseudoNode},
},
"applications-by-name": {
human: "by name",
parent: "applications",
maps: []topologyMapper{
{report.SelectEndpoint, report.ProcessName, report.GenericGroupedPseudoNode},
},
human: "by name",
parent: "applications",
renderer: render.Map{Selector: report.SelectEndpoint, Mapper: report.ProcessName, Pseudo: report.GenericGroupedPseudoNode},
},
"containers": {
human: "Containers",
parent: "",
maps: []topologyMapper{
{report.SelectEndpoint, report.MapEndpoint2Container, report.InternetOnlyPseudoNode},
{report.SelectContainer, report.MapContainerIdentity, report.InternetOnlyPseudoNode},
},
renderer: render.Reduce([]render.Renderer{
render.Map{Selector: report.SelectEndpoint, Mapper: report.MapEndpoint2Container, Pseudo: report.InternetOnlyPseudoNode},
render.Map{Selector: report.SelectContainer, Mapper: report.MapContainerIdentity, Pseudo: report.InternetOnlyPseudoNode},
}),
},
"containers-by-image": {
human: "by image",
parent: "containers",
maps: []topologyMapper{
{report.SelectEndpoint, report.ProcessContainerImage, report.InternetOnlyPseudoNode},
},
human: "by image",
parent: "containers",
renderer: render.Map{Selector: report.SelectEndpoint, Mapper: report.ProcessContainerImage, Pseudo: report.InternetOnlyPseudoNode},
},
"hosts": {
human: "Hosts",
parent: "",
maps: []topologyMapper{
{report.SelectAddress, report.NetworkHostname, report.GenericPseudoNode},
},
human: "Hosts",
parent: "",
renderer: render.Map{Selector: report.SelectAddress, Mapper: report.NetworkHostname, Pseudo: report.GenericPseudoNode},
},
}

type topologyView struct {
human string
parent string
maps []topologyMapper
}

type topologyMapper struct {
selector report.TopologySelector
mapper report.MapFunc
pseudo report.PseudoFunc
human string
parent string
renderer render.Renderer
}
1 change: 1 addition & 0 deletions circle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ dependencies:
mv scope_ui_build.tar $(dirname "$SCOPE_UI_BUILD");
fi
post:
- go version
- go clean -i net
- go install -tags netgo std
- make deps
Expand Down
51 changes: 51 additions & 0 deletions render/render.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package render

import (
"github.com/weaveworks/scope/report"
)

// Renderer is something that can render a report to a set of RenderableNodes
type Renderer interface {
Render(report.Report) report.RenderableNodes
AggregateMetadata(rpt report.Report, localID, remoteID string) report.AggregateMetadata
}

// Reduce renderer is a Renderer which merges together the output of several
// other renderers
type Reduce []Renderer

// Render produces a set of RenderableNodes given a Report
func (r Reduce) Render(rpt report.Report) report.RenderableNodes {
result := report.RenderableNodes{}
for _, renderer := range r {
result.Merge(renderer.Render(rpt))
}
return result
}

// AggregateMetadata produces an AggregateMetadata for a given edge
func (r Reduce) AggregateMetadata(rpt report.Report, localID, remoteID string) report.AggregateMetadata {
metadata := report.AggregateMetadata{}
for _, renderer := range r {
metadata.Merge(renderer.AggregateMetadata(rpt, localID, remoteID))
}
return metadata
}

// Map is a Renderer which produces a set of RendererNodes by using a
// Mapper functions and topology selector.
type Map struct {
Selector report.TopologySelector
Mapper report.MapFunc
Pseudo report.PseudoFunc
}

// Render produces a set of RenderableNodes given a Report
func (m Map) Render(rpt report.Report) report.RenderableNodes {
return m.Selector(rpt).RenderBy(m.Mapper, m.Pseudo)
}

// AggregateMetadata produces an AggregateMetadata for a given edge
func (m Map) AggregateMetadata(rpt report.Report, localID, remoteID string) report.AggregateMetadata {
return m.Selector(rpt).EdgeMetadata(m.Mapper, localID, remoteID).Transform()
}
49 changes: 49 additions & 0 deletions render/render_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package render_test

import (
"reflect"
"testing"

"github.com/weaveworks/scope/render"
"github.com/weaveworks/scope/report"
)

type mockRenderer struct {
report.RenderableNodes
aggregateMetadata report.AggregateMetadata
}

func (m mockRenderer) Render(rpt report.Report) report.RenderableNodes {
return m.RenderableNodes
}
func (m mockRenderer) AggregateMetadata(rpt report.Report, localID, remoteID string) report.AggregateMetadata {
return m.aggregateMetadata
}

This comment was marked as abuse.

This comment was marked as abuse.


func TestReduceRender(t *testing.T) {
renderer := render.Reduce([]render.Renderer{
mockRenderer{RenderableNodes: report.RenderableNodes{"foo": {ID: "foo"}}},
mockRenderer{RenderableNodes: report.RenderableNodes{"bar": {ID: "bar"}}},
})

want := report.RenderableNodes{"foo": {ID: "foo"}, "bar": {ID: "bar"}}
have := renderer.Render(report.MakeReport())

if !reflect.DeepEqual(want, have) {
t.Errorf("want %+v, have %+v", want, have)
}
}

func TestReduceEdge(t *testing.T) {
renderer := render.Reduce([]render.Renderer{
mockRenderer{aggregateMetadata: report.AggregateMetadata{"foo": 1}},
mockRenderer{aggregateMetadata: report.AggregateMetadata{"bar": 2}},
})

want := report.AggregateMetadata{"foo": 1, "bar": 2}
have := renderer.AggregateMetadata(report.MakeReport(), "", "")

if !reflect.DeepEqual(want, have) {
t.Errorf("want %+v, have %+v", want, have)
}
}
Loading