21285: Send all SSH and tunnel endpoints to tunnel queue.
[arvados.git] / lib / boot / workbench2.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         "fmt"
11         "io"
12         "io/fs"
13         "io/ioutil"
14         "net"
15         "os"
16
17         "git.arvados.org/arvados.git/sdk/go/arvados"
18 )
19
20 type runWorkbench2 struct {
21         svc arvados.Service
22 }
23
24 func (runner runWorkbench2) String() string {
25         return "runWorkbench2"
26 }
27
28 func (runner runWorkbench2) Run(ctx context.Context, fail func(error), super *Supervisor) error {
29         host, port, err := internalPort(runner.svc)
30         if err != nil {
31                 return fmt.Errorf("bug: no internalPort for %q: %v (%#v)", runner, err, runner.svc)
32         }
33         super.waitShutdown.Add(1)
34         go func() {
35                 defer super.waitShutdown.Done()
36                 if super.ClusterType == "production" {
37                         err = super.RunProgram(ctx, "/var/lib/arvados/workbench2", runOptions{
38                                 user: "www-data",
39                         }, "arvados-server", "workbench2", super.cluster.Services.Controller.ExternalURL.Host, net.JoinHostPort(host, port), ".")
40                 } else {
41                         // super.SourcePath might be readonly, so for
42                         // dev/test mode we make a copy in a writable
43                         // dir.
44                         livedir := super.wwwtempdir + "/workbench2"
45                         if err := super.RunProgram(ctx, super.SourcePath+"/services/workbench2", runOptions{}, "rsync", "-a", "--delete-after", super.SourcePath+"/services/workbench2/", livedir); err != nil {
46                                 fail(err)
47                                 return
48                         }
49                         if err = os.Mkdir(livedir+"/public/_health", 0777); err != nil && !errors.Is(err, fs.ErrExist) {
50                                 fail(err)
51                                 return
52                         }
53                         if err = ioutil.WriteFile(livedir+"/public/_health/ping", []byte(`{"health":"OK"}`), 0666); err != nil {
54                                 fail(err)
55                                 return
56                         }
57
58                         stdinr, stdinw := io.Pipe()
59                         defer stdinw.Close()
60                         go func() {
61                                 <-ctx.Done()
62                                 stdinw.Close()
63                         }()
64                         err = super.RunProgram(ctx, livedir, runOptions{
65                                 env: []string{
66                                         "CI=true",
67                                         "HTTPS=false",
68                                         "PORT=" + port,
69                                         "REACT_APP_ARVADOS_API_HOST=" + super.cluster.Services.Controller.ExternalURL.Host,
70                                 },
71                                 // If we don't connect stdin, "yarn start" just exits.
72                                 stdin: stdinr,
73                         }, "yarn", "start")
74                         fail(errors.New("`yarn start` exited"))
75                 }
76                 fail(err)
77         }()
78         return nil
79 }