Select Git revision
edit-comments.js
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
}
return mkTag(name, svcname)
}
func findContainerByPort(service *floatschema.Service, port int) *floatschema.Container {
for i := 0; i < len(service.Containers); i++ {
c := &service.Containers[i]
if c.Port > 0 && c.Port == port {
return c
}
for _, p := range c.Ports {
if p == port {
return c
}
}
}
return nil
}
func findFirstRealSystemdService(service *floatschema.Service) (string, bool) {
for _, s := range service.SystemdServices {
if !strings.HasPrefix(s, "docker-") {
return strings.TrimSuffix(s, ".service"), true
}
}
return "", false
}