12 "github.com/hashicorp/consul/api"
15 var consul = &consulBooter{}
17 type consulBooter struct {
21 func (cb *consulBooter) Boot(ctx context.Context) error {
25 if cb.check(ctx) == nil {
29 bin := cfg.UsrDir + "/bin/consul"
31 URL: "https://releases.hashicorp.com/consul/0.7.2/consul_0.7.2_linux_amd64.zip",
39 dataDir := cfg.DataDir + "/consul"
40 if err := os.MkdirAll(dataDir, 0700); err != nil {
43 args := []string{"agent"}
45 cf := path.Join(cfg.DataDir, "consul-encrypt.json")
47 if os.IsNotExist(err) {
48 key, err := exec.Command(bin, "keygen").CombinedOutput()
52 err = atomicWriteJSON(cf, map[string]interface{}{
53 "encrypt": strings.TrimSpace(string(key)),
59 args = append(args, "-config-file="+cf)
62 cf := path.Join(cfg.DataDir, "consul-ports.json")
63 err = atomicWriteJSON(cf, map[string]interface{}{
64 "client_addr": "0.0.0.0",
65 "bootstrap_expect": len(cfg.ControlHosts),
67 "datacenter": cfg.SiteID,
70 "ports": map[string]int{
71 "dns": cfg.Ports.ConsulDNS,
72 "http": cfg.Ports.ConsulHTTP,
73 "https": cfg.Ports.ConsulHTTPS,
74 "rpc": cfg.Ports.ConsulRPC,
75 "serf_lan": cfg.Ports.ConsulSerfLAN,
76 "serf_wan": cfg.Ports.ConsulSerfWAN,
77 "server": cfg.Ports.ConsulServer,
83 args = append(args, "-config-file="+cf)
85 supervisor := newSupervisor(ctx, "arvados-consul", bin, args...)
86 running, err := supervisor.Running(ctx)
91 defer feedbackf(ctx, "starting consul service")()
92 err = supervisor.Start(ctx)
94 return fmt.Errorf("starting consul: %s", err)
96 if len(cfg.ControlHosts) > 1 {
97 cmd := exec.Command(bin, append([]string{"join"}, cfg.ControlHosts...)...)
98 cmd.Stdout = os.Stderr
99 cmd.Stderr = os.Stderr
102 return fmt.Errorf("consul join: %s", err)
109 var consulCfg = api.DefaultConfig()
111 func (cb *consulBooter) check(ctx context.Context) error {
113 consulCfg.Address = fmt.Sprintf("127.0.0.1:%d", cfg.Ports.ConsulHTTP)
114 consulCfg.Datacenter = cfg.SiteID
115 consul, err := api.NewClient(consulCfg)
119 _, err = consul.Catalog().Datacenters()
126 // OnlyNode returns true if this is the only consul node.
127 func (cb *consulBooter) OnlyNode() (bool, error) {
128 c, err := api.NewClient(consulCfg)
132 nodes, _, err := c.Catalog().Nodes(nil)
133 return len(nodes) == 1, err