Skip to content
Snippets Groups Projects
Select Git revision
  • a11b46dd8fcf9b4d0cf876376c4d571d82108e87
  • master default protected
  • renovate/bootstrap-5.x
  • renovate/purgecss-webpack-plugin-7.x
  • renovate/mini-css-extract-plugin-2.x
  • renovate/html-webpack-plugin-5.x
  • renovate/golang-1.x
  • renovate/css-loader-6.x
8 results

links.go

Blame
  • 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
    }