2fcb33613d70e34337d833b0f13368f5a3f5bcb1
[arvados.git] / services / boot / supervisor.go
1 package main
2
3 import (
4         "context"
5         "log"
6         "os"
7
8         "github.com/hashicorp/consul/api"
9 )
10
11 type supervisor interface {
12         Running(ctx context.Context) (bool, error)
13         Start(ctx context.Context) error
14 }
15
16 func newSupervisor(ctx context.Context, name, cmd string, args ...string) supervisor {
17         if _, err := os.Stat("/run/systemd/system"); err == nil {
18                 return &systemdUnit{
19                         name: name,
20                         cmd:  cmd,
21                         args: args,
22                 }
23         }
24         return &runitService{
25                 name: name,
26                 cmd:  cmd,
27                 args: args,
28         }
29 }
30
31 type supervisedService struct {
32         name string
33         cmd  string
34         args []string
35 }
36
37 func (s *supervisedService) Boot(ctx context.Context) error {
38         bin := s.cmd
39         if bin == "" {
40                 bin = s.name
41         }
42         if _, err := os.Stat(bin); err != nil {
43                 return err
44         }
45         sup := newSupervisor(ctx, s.name, bin)
46         if ok, err := sup.Running(ctx); err != nil {
47                 return err
48         } else if !ok {
49                 if err := sup.Start(ctx); err != nil {
50                         return err
51                 }
52         }
53         if err := consul.Boot(ctx); err != nil {
54                 return err
55         }
56         consul, err := api.NewClient(consulCfg)
57         if err != nil {
58                 return err
59         }
60         agent := consul.Agent()
61         svcs, err := agent.Services()
62         if err != nil {
63                 return err
64         }
65         if svc, ok := svcs[s.name]; ok {
66                 log.Printf("%s is registered: %#v", s.name, svc)
67                 return nil
68         }
69         return agent.ServiceRegister(&api.AgentServiceRegistration{
70                 ID:   s.name,
71                 Name: s.name,
72                 Port: availablePort(),
73         })
74 }