-
Notifications
You must be signed in to change notification settings - Fork 1
/
health.go
89 lines (79 loc) · 2.81 KB
/
health.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
package gitserver
import (
"bytes"
"context"
_ "embed" // Required by the `go:embed` comment below.
"fmt"
"io"
"net/http"
"os"
"path"
"time"
)
//go:embed testproblem.zip
var testproblemZip []byte
// HealthHandler is an implementation of k8s readiness and liveness checks. The
// liveness check just returns HTTP 200 (because the server is reachable), but
// the readiness check tries to interact with the service by requesting the
// settings.json file of the sumas problem. Getting a 404 is fine.
func HealthHandler(rootPath string, port uint16) http.Handler {
mux := http.NewServeMux()
mux.HandleFunc("/health/live", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write([]byte("ok"))
})
mux.HandleFunc("/health/ready", func(w http.ResponseWriter, r *http.Request) {
ctx, cancel := context.WithTimeout(r.Context(), 5*time.Second)
defer cancel()
if _, err := os.Stat(path.Join(rootPath, ":testproblem")); os.IsNotExist(err) {
// Creating problem!
req, err := http.NewRequestWithContext(ctx, "POST", fmt.Sprintf("http://localhost:%d/:testproblem/git-upload-zip?create=true&message=Test&acceptsSubmissions=true&updatePublished=true&mergeStrategy=theirs", port), nil)
if err != nil {
w.WriteHeader(http.StatusServiceUnavailable)
w.Write([]byte(fmt.Sprintf("git-upload-zip request: %v", err)))
return
}
req.Header.Add("Authorization", "omegaup:health")
req.Header.Add("Content-Type", "application/zip")
req.Body = io.NopCloser(bytes.NewReader(testproblemZip))
res, err := http.DefaultClient.Do(req)
if err != nil {
w.WriteHeader(http.StatusServiceUnavailable)
w.Write([]byte(fmt.Sprintf("git-upload-zip request: %v", err)))
return
}
contents, readErr := io.ReadAll(res.Body)
if readErr != nil {
contents = append(contents, []byte(fmt.Sprintf(", error=%v", readErr))...)
}
res.Body.Close()
if res.StatusCode != 200 {
w.WriteHeader(http.StatusServiceUnavailable)
w.Write([]byte(fmt.Sprintf("git-upload-zip HTTP/%d. headers: %v, body: %v", res.StatusCode, res.Header, string(contents))))
return
}
}
req, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("http://localhost:%d/:testproblem/+/private/settings.json", port), nil)
if err != nil {
w.WriteHeader(http.StatusServiceUnavailable)
w.Write([]byte(fmt.Sprintf("request: %v", err)))
return
}
req.Header.Add("Authorization", "omegaup:health")
res, err := http.DefaultClient.Do(req)
if err != nil {
w.WriteHeader(http.StatusServiceUnavailable)
w.Write([]byte(fmt.Sprintf("request: %v", err)))
return
}
res.Body.Close()
if res.StatusCode != 200 {
w.WriteHeader(http.StatusServiceUnavailable)
w.Write([]byte(fmt.Sprintf("HTTP/%d", res.StatusCode)))
return
}
w.WriteHeader(http.StatusOK)
w.Write([]byte("ok"))
})
return mux
}