17574: Merge branch 'main'
[arvados.git] / sdk / go / arvadostest / run_servers.go
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: Apache-2.0
4
5 package arvadostest
6
7 import (
8         "bufio"
9         "bytes"
10         "fmt"
11         "io/ioutil"
12         "log"
13         "os"
14         "os/exec"
15         "path"
16         "strconv"
17         "strings"
18 )
19
20 var authSettings = make(map[string]string)
21
22 // ResetEnv resets test env
23 func ResetEnv() {
24         for k, v := range authSettings {
25                 os.Setenv(k, v)
26         }
27 }
28
29 // APIHost returns the address:port of the current test server.
30 func APIHost() string {
31         h := authSettings["ARVADOS_API_HOST"]
32         if h == "" {
33                 log.Fatal("arvadostest.APIHost() was called but authSettings is not populated")
34         }
35         return h
36 }
37
38 // ParseAuthSettings parses auth settings from given input
39 func ParseAuthSettings(authScript []byte) {
40         scanner := bufio.NewScanner(bytes.NewReader(authScript))
41         for scanner.Scan() {
42                 line := scanner.Text()
43                 if 0 != strings.Index(line, "export ") {
44                         log.Printf("Ignoring: %v", line)
45                         continue
46                 }
47                 toks := strings.SplitN(strings.Replace(line, "export ", "", 1), "=", 2)
48                 if len(toks) == 2 {
49                         authSettings[toks[0]] = toks[1]
50                 } else {
51                         log.Fatalf("Could not parse: %v", line)
52                 }
53         }
54         log.Printf("authSettings: %v", authSettings)
55 }
56
57 var pythonTestDir string
58
59 func chdirToPythonTests() {
60         if pythonTestDir != "" {
61                 if err := os.Chdir(pythonTestDir); err != nil {
62                         log.Fatalf("chdir %s: %s", pythonTestDir, err)
63                 }
64                 return
65         }
66         for {
67                 if err := os.Chdir("sdk/python/tests"); err == nil {
68                         pythonTestDir, err = os.Getwd()
69                         if err != nil {
70                                 log.Fatal(err)
71                         }
72                         return
73                 }
74                 if parent, err := os.Getwd(); err != nil || parent == "/" {
75                         log.Fatalf("sdk/python/tests/ not found in any ancestor")
76                 }
77                 if err := os.Chdir(".."); err != nil {
78                         log.Fatal(err)
79                 }
80         }
81 }
82
83 // StartAPI starts test API server
84 func StartAPI() {
85         cwd, _ := os.Getwd()
86         defer os.Chdir(cwd)
87         chdirToPythonTests()
88
89         cmd := exec.Command("python", "run_test_server.py", "start", "--auth", "admin")
90         cmd.Stdin = nil
91         cmd.Stderr = os.Stderr
92
93         authScript, err := cmd.Output()
94         if err != nil {
95                 log.Fatalf("%+v: %s", cmd.Args, err)
96         }
97         ParseAuthSettings(authScript)
98         ResetEnv()
99 }
100
101 // StopAPI stops test API server
102 func StopAPI() {
103         cwd, _ := os.Getwd()
104         defer os.Chdir(cwd)
105         chdirToPythonTests()
106
107         cmd := exec.Command("python", "run_test_server.py", "stop")
108         bgRun(cmd)
109         // Without Wait, "go test" in go1.10.1 tends to hang. https://github.com/golang/go/issues/24050
110         cmd.Wait()
111 }
112
113 // StartKeep starts the given number of keep servers,
114 // optionally with --keep-blob-signing enabled.
115 // Use numKeepServers = 2 and blobSigning = false under all normal circumstances.
116 func StartKeep(numKeepServers int, blobSigning bool) {
117         cwd, _ := os.Getwd()
118         defer os.Chdir(cwd)
119         chdirToPythonTests()
120
121         cmdArgs := []string{"run_test_server.py", "start_keep", "--num-keep-servers", strconv.Itoa(numKeepServers)}
122         if blobSigning {
123                 cmdArgs = append(cmdArgs, "--keep-blob-signing")
124         }
125
126         bgRun(exec.Command("python", cmdArgs...))
127 }
128
129 // StopKeep stops keep servers that were started with StartKeep.
130 // numkeepServers should be the same value that was passed to StartKeep,
131 // which is 2 under all normal circumstances.
132 func StopKeep(numKeepServers int) {
133         cwd, _ := os.Getwd()
134         defer os.Chdir(cwd)
135         chdirToPythonTests()
136
137         cmd := exec.Command("python", "run_test_server.py", "stop_keep", "--num-keep-servers", strconv.Itoa(numKeepServers))
138         bgRun(cmd)
139         // Without Wait, "go test" in go1.10.1 tends to hang. https://github.com/golang/go/issues/24050
140         cmd.Wait()
141 }
142
143 // Start cmd, with stderr and stdout redirected to our own
144 // stderr. Return when the process exits, but do not wait for its
145 // stderr and stdout to close: any grandchild processes will continue
146 // writing to our stderr.
147 func bgRun(cmd *exec.Cmd) {
148         cmd.Stdin = nil
149         cmd.Stderr = os.Stderr
150         cmd.Stdout = os.Stderr
151         if err := cmd.Start(); err != nil {
152                 log.Fatalf("%+v: %s", cmd.Args, err)
153         }
154         if _, err := cmd.Process.Wait(); err != nil {
155                 log.Fatalf("%+v: %s", cmd.Args, err)
156         }
157 }
158
159 // CreateBadPath creates a tmp dir, appends given string and returns that path
160 // This will guarantee that the path being returned does not exist
161 func CreateBadPath() (badpath string, err error) {
162         tempdir, err := ioutil.TempDir("", "bad")
163         if err != nil {
164                 return "", fmt.Errorf("Could not create temporary directory for bad path: %v", err)
165         }
166         badpath = path.Join(tempdir, "bad")
167         return badpath, nil
168 }
169
170 // DestroyBadPath deletes the tmp dir created by the previous CreateBadPath call
171 func DestroyBadPath(badpath string) error {
172         tempdir := path.Join(badpath, "..")
173         err := os.Remove(tempdir)
174         if err != nil {
175                 return fmt.Errorf("Could not remove bad path temporary directory %v: %v", tempdir, err)
176         }
177         return nil
178 }