add vault, consul-template, arvados pkgs
[arvados.git] / services / boot / consul.go
1 package main
2
3 import (
4         "context"
5         "fmt"
6         "os"
7         "os/exec"
8         "sync"
9
10         "github.com/hashicorp/consul/api"
11 )
12
13 var consul = &consulBooter{}
14
15 type consulBooter struct {
16         sync.Mutex
17 }
18
19 func (cb *consulBooter) Boot(ctx context.Context) error {
20         cb.Lock()
21         defer cb.Unlock()
22
23         if cb.check(ctx) == nil {
24                 return nil
25         }
26         cfg := cfg(ctx)
27         bin := cfg.UsrDir + "/bin/consul"
28         err := (&download{
29                 URL:  "https://releases.hashicorp.com/consul/0.7.2/consul_0.7.2_linux_amd64.zip",
30                 Dest: bin,
31                 Size: 29079005,
32                 Mode: 0755,
33         }).Boot(ctx)
34         if err != nil {
35                 return err
36         }
37         dataDir := cfg.DataDir + "/consul"
38         if err := os.MkdirAll(dataDir, 0700); err != nil {
39                 return err
40         }
41         args := []string{
42                 "agent",
43                 "-server",
44                 "-datacenter=" + cfg.SiteID,
45                 "-dns-port=" + fmt.Sprintf("%d", cfg.Ports.ConsulDNS),
46                 "-http-port=" + fmt.Sprintf("%d", cfg.Ports.ConsulHTTP),
47                 "-serf-lan-bind=0.0.0.0:" + fmt.Sprintf("%d", cfg.Ports.ConsulSerfLAN),
48                 "-serf-wan-bind=0.0.0.0:" + fmt.Sprintf("%d", cfg.Ports.ConsulSerfWAN),
49                 "-data-dir", dataDir,
50                 "-bootstrap-expect", fmt.Sprintf("%d", len(cfg.ControlHosts))}
51         supervisor := newSupervisor(ctx, "consul", bin, args...)
52         running, err := supervisor.Running(ctx)
53         if err != nil {
54                 return err
55         }
56         if !running {
57                 defer feedbackf(ctx, "starting consul service")()
58                 err = supervisor.Start(ctx)
59                 if err != nil {
60                         return fmt.Errorf("starting consul: %s", err)
61                 }
62                 if len(cfg.ControlHosts) > 1 {
63                         cmd := exec.Command(bin, append([]string{"join"}, cfg.ControlHosts...)...)
64                         cmd.Stdout = os.Stderr
65                         cmd.Stderr = os.Stderr
66                         err := cmd.Run()
67                         if err != nil {
68                                 return fmt.Errorf("consul join: %s", err)
69                         }
70                 }
71         }
72         return cb.check(ctx)
73 }
74
75 var consulCfg = api.DefaultConfig()
76
77 func (cb *consulBooter) check(ctx context.Context) error {
78         cfg := cfg(ctx)
79         consulCfg.Address = fmt.Sprintf("127.0.0.1:%d", cfg.Ports.ConsulHTTP)
80         consulCfg.Datacenter = cfg.SiteID
81         consul, err := api.NewClient(consulCfg)
82         if err != nil {
83                 return err
84         }
85         _, err = consul.Catalog().Datacenters()
86         if err != nil {
87                 return err
88         }
89         return nil
90 }