Select Git revision
-
ale authored
The app is now self-hosted instead of relying on the static-content standalone server, so we can eventually add dynamic code for graph serving. The static content serving has improved, with more consistent cache header management, as well as the capability of serving pre-compressed content. Additional code to implement the generation of dependency (flow) graphs in dot format was added (not hooked to the HTTP server yet).
ale authoredThe app is now self-hosted instead of relying on the static-content standalone server, so we can eventually add dynamic code for graph serving. The static content serving has improved, with more consistent cache header management, as well as the capability of serving pre-compressed content. Additional code to implement the generation of dependency (flow) graphs in dot format was added (not hooked to the HTTP server yet).
service.go 2.37 KiB
package graph
import (
"strings"
floatschema "git.autistici.org/ai3/tools/float-dashboard/schema/float"
)
// ServiceGraph extracts a service dependency graph from a float schema.
func ServiceGraph(services map[string]*floatschema.Service) *Graph {
g := NewGraph()
// Create all nodes first.
for svcname, s := range services {
pelists := [][]floatschema.PublicEndpoint{s.PublicEndpoints, s.PublicTCPEndpoints}
for _, pelist := range pelists {
for _, pe := range pelist {
name := pe.Name
if name == "" {
name = pe.Domains[0]
}
g.addNode(newWebNode(name, svcname))
}
}
for _, c := range s.Containers {
g.addNode(NewNode(mkTag(c.Name, svcname), svcname))
}
for _, sv := range s.SystemdServices {
if strings.HasPrefix(sv, "docker-") {
continue
}
name := strings.TrimSuffix(sv, ".service")
g.addNode(NewNode(mkTag(name, svcname), svcname))
}
}
// Now add all edges.
for svcname, s := range services {
pelists := [][]floatschema.PublicEndpoint{s.PublicEndpoints, s.PublicTCPEndpoints}
for _, pelist := range pelists {
for _, pe := range pelist {
name := pe.Name
if name == "" {
name = pe.Domains[0]
}
g.addEdge(INTERNET, name)
// Match the port with a container, if possible, or
// fall back to the first systemd unit defined for the
// service.
if c := findContainerByPort(s, pe.Port); c != nil {
g.addEdge(name, mkTag(c.Name, svcname))
} else if unitName, ok := findFirstRealSystemdService(s); ok {
g.addEdge(name, mkTag(unitName, svcname))
}
}
}
for _, d := range s.Annotations.Dependencies {
g.addEdge(nodeNameFromDep(d.Client, svcname),
nodeNameFromDep(d.Server, svcname))
}
}
return g
}
func nodeNameFromDep(name, svcname string) string {
if strings.Contains(name, "/") {
return name
}