Change from grouped URL to sub-topologies

This commit is contained in:
Peter Bourgon
2015-06-12 13:23:25 +02:00
parent 816e1e9e99
commit 086ff3b791
4 changed files with 80 additions and 49 deletions

View File

@@ -2,17 +2,16 @@ package main
import (
"net/http"
"strings"
"github.com/weaveworks/scope/report"
)
// APITopologyDesc is returned in a list by the /api/topology handler.
type APITopologyDesc struct {
Name string `json:"name"`
URL string `json:"url"`
GroupedURL string `json:"grouped_url,omitempty"`
Stats topologyStats `json:"stats"`
Name string `json:"name"`
URL string `json:"url"`
SubTopologies []APITopologyDesc `json:"sub_topologies,omitempty"`
Stats *topologyStats `json:"stats,omitempty"`
}
type topologyStats struct {
@@ -25,31 +24,29 @@ type topologyStats struct {
func makeTopologyList(rep Reporter) func(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
rpt := rep.Report()
var a []APITopologyDesc
topologies := []APITopologyDesc{}
for name, def := range topologyRegistry {
if strings.HasSuffix(name, "grouped") {
continue
subTopologies := []APITopologyDesc{}
for subName, subDef := range topologyRegistry {
if subDef.parent == name {
subTopologies = append(subTopologies, APITopologyDesc{
Name: subDef.human,
URL: "/api/topology/" + subName,
})
}
}
url := "/api/topology/" + name
var groupedURL string
if def.groupedTopology != "" {
groupedURL = "/api/topology/" + def.groupedTopology
}
a = append(a, APITopologyDesc{
Name: def.human,
URL: url,
GroupedURL: groupedURL,
Stats: stats(render(rpt, def.maps)),
topologies = append(topologies, APITopologyDesc{
Name: def.human,
URL: "/api/topology/" + name,
SubTopologies: subTopologies,
Stats: stats(render(rpt, def.maps)),
})
}
respondWith(w, http.StatusOK, a)
respondWith(w, http.StatusOK, topologies)
}
}
func stats(r report.RenderableNodes) topologyStats {
func stats(r report.RenderableNodes) *topologyStats {
var (
nodes int
realNodes int
@@ -64,7 +61,7 @@ func stats(r report.RenderableNodes) topologyStats {
edges += len(n.Adjacency)
}
return topologyStats{
return &topologyStats{
NodeCount: nodes,
NonpseudoNodeCount: realNodes,
EdgeCount: edges,

View File

@@ -11,23 +11,29 @@ func TestAPITopology(t *testing.T) {
defer ts.Close()
body := getRawJSON(t, ts, "/api/topology")
var topos []APITopologyDesc
if err := json.Unmarshal(body, &topos); err != nil {
var topologies []APITopologyDesc
if err := json.Unmarshal(body, &topologies); err != nil {
t.Fatalf("JSON parse error: %s", err)
}
equals(t, 3, len(topos))
for _, topo := range topos {
is200(t, ts, topo.URL)
if topo.GroupedURL != "" {
is200(t, ts, topo.GroupedURL)
equals(t, 5, len(topologies))
for _, topology := range topologies {
is200(t, ts, topology.URL)
for _, subTopology := range topology.SubTopologies {
is200(t, ts, subTopology.URL)
}
if have := topo.Stats.EdgeCount; have <= 0 {
if have := topology.Stats.EdgeCount; have <= 0 {
t.Errorf("EdgeCount isn't positive: %d", have)
}
if have := topo.Stats.NodeCount; have <= 0 {
if have := topology.Stats.NodeCount; have <= 0 {
t.Errorf("NodeCount isn't positive: %d", have)
}
if have := topo.Stats.NonpseudoNodeCount; have <= 0 {
if have := topology.Stats.NonpseudoNodeCount; have <= 0 {
t.Errorf("NonpseudoNodeCount isn't positive: %d", have)
}
}

View File

@@ -18,7 +18,7 @@ import (
)
// Set during buildtime.
var version = "unknown"
var version = "dev"
func main() {
var (

View File

@@ -45,10 +45,49 @@ func apiHandler(w http.ResponseWriter, r *http.Request) {
respondWith(w, http.StatusOK, APIDetails{Version: version})
}
var topologyRegistry = map[string]topologyView{
"applications": {
human: "Applications",
parent: "",
maps: []topologyMapper{
{report.SelectEndpoint, report.ProcessPID, report.GenericPseudoNode},
},
},
"applications-by-name": {
human: "Applications by name",
parent: "applications",
maps: []topologyMapper{
{report.SelectEndpoint, report.ProcessName, report.GenericGroupedPseudoNode},
},
},
"containers": {
human: "Containers",
parent: "",
maps: []topologyMapper{
{report.SelectEndpoint, report.MapEndpoint2Container, report.InternetOnlyPseudoNode},
{report.SelectContainer, report.MapContainerIdentity, report.InternetOnlyPseudoNode},
},
},
"containers-by-image": {
human: "Containers by image",
parent: "containers",
maps: []topologyMapper{
{report.SelectEndpoint, report.ProcessContainerImage, report.InternetOnlyPseudoNode},
},
},
"hosts": {
human: "Hosts",
parent: "",
maps: []topologyMapper{
{report.SelectAddress, report.NetworkHostname, report.GenericPseudoNode},
},
},
}
type topologyView struct {
human string
groupedTopology string
maps []topologyMapper
human string
parent string
maps []topologyMapper
}
type topologyMapper struct {
@@ -56,14 +95,3 @@ type topologyMapper struct {
mapper report.MapFunc
pseudo report.PseudoFunc
}
var topologyRegistry = map[string]topologyView{
"applications": {"Applications", "applications-grouped", []topologyMapper{{report.SelectEndpoint, report.ProcessPID, report.GenericPseudoNode}}},
"applications-grouped": {"Applications", "", []topologyMapper{{report.SelectEndpoint, report.ProcessName, report.GenericGroupedPseudoNode}}},
"containers": {"Containers", "containers-grouped", []topologyMapper{
{report.SelectEndpoint, report.MapEndpoint2Container, report.InternetOnlyPseudoNode},
{report.SelectContainer, report.MapContainerIdentity, report.InternetOnlyPseudoNode},
}},
"containers-grouped": {"Containers", "", []topologyMapper{{report.SelectEndpoint, report.ProcessContainerImage, report.InternetOnlyPseudoNode}}},
"hosts": {"Hosts", "", []topologyMapper{{report.SelectAddress, report.NetworkHostname, report.GenericPseudoNode}}},
}