16306: Refactor docker scripts into arvados-package command.
[arvados.git] / cmd / arvados-package / install.go
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 package main
6
7 import (
8         "context"
9         "errors"
10         "fmt"
11         "io"
12         "io/ioutil"
13         "os"
14         "os/exec"
15         "path/filepath"
16         "strings"
17
18         "github.com/docker/docker/api/types"
19         "github.com/docker/docker/client"
20 )
21
22 // sourcesfile=/tmp/sources.conf.d-arvados
23 // echo >$sourcesfile "deb [trusted=yes] file:///pkg ./"
24
25 // installimage="arvados-installpackage-${osbase}"
26 // if [[ "${opts[force-installimage]}" || -z "$(docker images --format {{.Repository}} "${installimage}")" ]]; then
27 //     echo >&2 building ${installimage}...
28 //     installctr=${installimage/:/-}
29 //     docker rm "${installctr}" || true
30 //     docker run -it \
31 //            --name "${installctr}" \
32 //            --tmpfs /tmp \
33 //            -v /tmp/pkg:/pkg:ro \
34 //            -v ${sourcesfile}:/etc/apt/sources.list.d/arvados-local.list:ro \
35 //            --env DEBIAN_FRONTEND=noninteractive \
36 //            "${osbase}" \
37 //            bash -c 'apt update && apt install -y eatmydata && eatmydata apt install -y arvados-server-easy postgresql && eatmydata apt remove -y arvados-server-easy'
38 //     docker commit "${installctr}" "${installimage}"
39 //     docker rm "${installctr}"
40 //     installctr=
41 // fi
42
43 func testinstall(ctx context.Context, opts opts, stdin io.Reader, stdout, stderr io.Writer) error {
44         if opts.PackageVersion != "" {
45                 return errors.New("not implemented: package version was specified, but I only know how to test the latest version in pkgdir")
46         }
47         depsImageName := "arvados-package-deps-" + opts.TargetOS
48         depsCtrName := strings.Replace(depsImageName, ":", "-", -1)
49
50         _, prog := filepath.Split(os.Args[0])
51         tmpdir, err := ioutil.TempDir("", prog+".")
52         if err != nil {
53                 return fmt.Errorf("TempDir: %w", err)
54         }
55         defer os.RemoveAll(tmpdir)
56
57         sourcesFile := tmpdir + "/arvados-local.list"
58         err = ioutil.WriteFile(sourcesFile, []byte("deb [trusted=yes] file:///pkg ./\n"), 0644)
59         if err != nil {
60                 return fmt.Errorf("Write %s: %w", sourcesFile, err)
61         }
62
63         if exists, err := dockerImageExists(ctx, depsImageName); err != nil {
64                 return err
65         } else if !exists || opts.RebuildImage {
66                 err = dockerRm(ctx, depsCtrName)
67                 if err != nil {
68                         return err
69                 }
70                 defer dockerRm(ctx, depsCtrName)
71                 cmd := exec.CommandContext(ctx, "docker", "run",
72                         "--name", depsCtrName,
73                         "--tmpfs", "/tmp:exec,mode=01777",
74                         "-v", opts.PackageDir+":/pkg:ro",
75                         "-v", sourcesFile+":/etc/apt/sources.list.d/arvados-local.list:ro",
76                         "--env", "DEBIAN_FRONTEND=noninteractive",
77                         opts.TargetOS,
78                         "bash", "-c", `
79 set -e
80 apt-get update
81 apt-get install -y eatmydata
82 eatmydata apt-get install -y --no-install-recommends arvados-server-easy postgresql
83 eatmydata apt-get remove -y arvados-server-easy
84 `)
85                 cmd.Stdout = stdout
86                 cmd.Stderr = stderr
87                 err = cmd.Run()
88                 if err != nil {
89                         return fmt.Errorf("docker run: %w", err)
90                 }
91
92                 cmd = exec.CommandContext(ctx, "docker", "commit", depsCtrName, depsImageName)
93                 cmd.Stdout = stdout
94                 cmd.Stderr = stderr
95                 err = cmd.Run()
96                 if err != nil {
97                         return fmt.Errorf("docker commit: %w", err)
98                 }
99         }
100
101         cmd := exec.CommandContext(ctx, "docker", "run", "--rm",
102                 "--tmpfs", "/tmp:exec,mode=01777",
103                 "-v", opts.PackageDir+":/pkg:ro",
104                 "-v", sourcesFile+":/etc/apt/sources.list.d/arvados-local.list:ro",
105                 "--env", "DEBIAN_FRONTEND=noninteractive",
106                 depsImageName,
107                 "bash", "-c", `
108 set -e
109 PATH="/var/lib/arvados/bin:$PATH"
110 apt-get update
111 eatmydata apt-get install --reinstall -y --no-install-recommends arvados-server-easy
112 apt-get -y autoremove
113 /etc/init.d/postgresql start
114 arvados-server init -cluster-id x1234
115 exec arvados-server boot -listen-host 0.0.0.0 -shutdown
116 `)
117         cmd.Stdout = stdout
118         cmd.Stderr = stderr
119         err = cmd.Run()
120         if err != nil {
121                 return fmt.Errorf("docker run: %w", err)
122         }
123         return nil
124 }
125
126 func dockerImageExists(ctx context.Context, name string) (bool, error) {
127         cli, err := client.NewEnvClient()
128         if err != nil {
129                 return false, err
130         }
131         imgs, err := cli.ImageList(ctx, types.ImageListOptions{All: true})
132         if err != nil {
133                 return false, err
134         }
135         for _, img := range imgs {
136                 for _, tag := range img.RepoTags {
137                         if tag == name {
138                                 return true, nil
139                         }
140                 }
141         }
142         return false, nil
143 }