add runit support
[arvados.git] / services / boot / os_package.go
1 package main
2
3 import (
4         "context"
5         "fmt"
6         "os"
7         "os/exec"
8         "strings"
9         "sync"
10 )
11
12 var (
13         installCerts = &osPackage{
14                 Debian: "ca-certificates",
15         }
16         installRunit = &osPackage{
17                 Debian: "runit",
18         }
19 )
20
21 type osPackage struct {
22         Debian string
23         RedHat string
24 }
25
26 var (
27         osPackageMutex     sync.Mutex
28         osPackageDidUpdate bool
29 )
30
31 func (pkg *osPackage) Boot(ctx context.Context) error {
32         osPackageMutex.Lock()
33         defer osPackageMutex.Unlock()
34
35         if _, err := os.Stat("/var/lib/dpkg/info/" + pkg.Debian + ".list"); err == nil {
36                 return nil
37         }
38         if !osPackageDidUpdate {
39                 d, err := os.Open("/var/lib/apt/lists")
40                 if err != nil {
41                         return err
42                 }
43                 defer d.Close()
44                 if files, err := d.Readdir(4); len(files) < 4 || err != nil {
45                         err = pkg.aptGet("update")
46                         if err != nil {
47                                 return err
48                         }
49                         osPackageDidUpdate = true
50                 }
51         }
52         return pkg.aptGet("install", "-y", "--no-install-recommends", pkg.Debian)
53 }
54
55 func (*osPackage) aptGet(args ...string) error {
56         cmd := exec.Command("apt-get", args...)
57         cmd.Stdout = os.Stderr
58         cmd.Stderr = os.Stderr
59         for _, kv := range os.Environ() {
60                 if !strings.HasPrefix(kv, "DEBIAN_FRONTEND=") {
61                         cmd.Env = append(cmd.Env, kv)
62                 }
63         }
64         cmd.Env = append(cmd.Env, "DEBIAN_FRONTEND=noninteractive")
65         err := cmd.Run()
66         if err != nil {
67                 return fmt.Errorf("%s: %s", cmd.Args, err)
68         }
69         return nil
70 }