Merge branch '17344-easy-demo'
[arvados.git] / lib / boot / service.go
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 package boot
6
7 import (
8         "context"
9         "errors"
10         "path/filepath"
11
12         "git.arvados.org/arvados.git/sdk/go/arvados"
13 )
14
15 // Run a service using the arvados-server binary.
16 //
17 // In future this will bring up the service in the current process,
18 // but for now (at least until the subcommand handlers get a shutdown
19 // mechanism) it starts a child process using the arvados-server
20 // binary, which the supervisor is assumed to have installed in
21 // {super.tempdir}/bin/.
22 type runServiceCommand struct {
23         name    string           // arvados-server subcommand, e.g., "controller"
24         svc     arvados.Service  // cluster.Services.* entry with the desired InternalURLs
25         depends []supervisedTask // wait for these tasks before starting
26 }
27
28 func (runner runServiceCommand) String() string {
29         return runner.name
30 }
31
32 func (runner runServiceCommand) Run(ctx context.Context, fail func(error), super *Supervisor) error {
33         binfile := filepath.Join(super.bindir, "arvados-server")
34         err := super.RunProgram(ctx, super.bindir, runOptions{}, binfile, "-version")
35         if err != nil {
36                 return err
37         }
38         super.wait(ctx, createCertificates{})
39         super.wait(ctx, runner.depends...)
40         for u := range runner.svc.InternalURLs {
41                 u := u
42                 if islocal, err := addrIsLocal(u.Host); err != nil {
43                         return err
44                 } else if !islocal {
45                         continue
46                 }
47                 super.waitShutdown.Add(1)
48                 go func() {
49                         defer super.waitShutdown.Done()
50                         fail(super.RunProgram(ctx, super.tempdir, runOptions{
51                                 env: []string{
52                                         "ARVADOS_SERVICE_INTERNAL_URL=" + u.String(),
53                                         // Child process should not
54                                         // try to tell systemd that we
55                                         // are ready.
56                                         "NOTIFY_SOCKET=",
57                                 },
58                         }, binfile, runner.name, "-config", super.configfile))
59                 }()
60         }
61         return nil
62 }
63
64 // Run a Go service that isn't bundled in arvados-server.
65 type runGoProgram struct {
66         src     string           // source dir, e.g., "services/keepproxy"
67         svc     arvados.Service  // cluster.Services.* entry with the desired InternalURLs
68         depends []supervisedTask // wait for these tasks before starting
69 }
70
71 func (runner runGoProgram) String() string {
72         _, basename := filepath.Split(runner.src)
73         return basename
74 }
75
76 func (runner runGoProgram) Run(ctx context.Context, fail func(error), super *Supervisor) error {
77         if len(runner.svc.InternalURLs) == 0 {
78                 return errors.New("bug: runGoProgram needs non-empty svc.InternalURLs")
79         }
80
81         binfile, err := super.installGoProgram(ctx, runner.src)
82         if err != nil {
83                 return err
84         }
85         if ctx.Err() != nil {
86                 return ctx.Err()
87         }
88
89         err = super.RunProgram(ctx, super.tempdir, runOptions{}, binfile, "-version")
90         if err != nil {
91                 return err
92         }
93
94         super.wait(ctx, createCertificates{})
95         super.wait(ctx, runner.depends...)
96         for u := range runner.svc.InternalURLs {
97                 u := u
98                 if islocal, err := addrIsLocal(u.Host); err != nil {
99                         return err
100                 } else if !islocal {
101                         continue
102                 }
103                 super.waitShutdown.Add(1)
104                 go func() {
105                         defer super.waitShutdown.Done()
106                         fail(super.RunProgram(ctx, super.tempdir, runOptions{env: []string{"ARVADOS_SERVICE_INTERNAL_URL=" + u.String()}}, binfile))
107                 }()
108         }
109         return nil
110 }