mirror of
https://github.com/weaveworks/scope.git
synced 2026-05-06 01:08:03 +00:00
Change from grouped URL to sub-topologies
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ import (
|
||||
)
|
||||
|
||||
// Set during buildtime.
|
||||
var version = "unknown"
|
||||
var version = "dev"
|
||||
|
||||
func main() {
|
||||
var (
|
||||
|
||||
@@ -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}}},
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user