cmd/gitmirror: use liveness probes

Change-Id: I9fd7a368dad2c884b97f6527ed92fab9dada9d73
Reviewed-on: https://go-review.googlesource.com/c/build/+/327757
Trust: Heschi Kreinick <heschi@google.com>
Run-TryBot: Heschi Kreinick <heschi@google.com>
Reviewed-by: Carlos Amedee <carlos@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
diff --git a/cmd/gitmirror/deployment.yaml b/cmd/gitmirror/deployment.yaml
index 1ff6a92..238e389 100644
--- a/cmd/gitmirror/deployment.yaml
+++ b/cmd/gitmirror/deployment.yaml
@@ -34,6 +34,13 @@
           name: cache-volume
         ports:
         - containerPort: 8585
+        livenessProbe:
+          httpGet:
+            path: /healthz
+            port: 8585
+          initialDelaySeconds: 300
+          failureThreshold: 60
+          periodSeconds: 10
         resources:
           requests:
             cpu: "2"
diff --git a/cmd/gitmirror/gitmirror.go b/cmd/gitmirror/gitmirror.go
index c128703..f68e8a6 100644
--- a/cmd/gitmirror/gitmirror.go
+++ b/cmd/gitmirror/gitmirror.go
@@ -86,13 +86,16 @@
 		mirrorCSR:    *flagMirrorCSR,
 		timeoutScale: 1,
 	}
-	http.HandleFunc("/", m.handleRoot)
 
 	var eg errgroup.Group
 	for _, repo := range repospkg.ByGerritProject {
 		r := m.addRepo(repo)
 		eg.Go(r.init)
 	}
+
+	http.HandleFunc("/", m.handleRoot)
+	http.HandleFunc("/healthz", m.handleHealth)
+
 	if err := eg.Wait(); err != nil {
 		log.Fatalf("initializing repos: %v", err)
 	}
@@ -271,6 +274,23 @@
 	fmt.Fprint(w, "</pre></body></html>")
 }
 
+func (m *gitMirror) handleHealth(w http.ResponseWriter, r *http.Request) {
+	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
+	for _, r := range m.repos {
+		r.mu.Lock()
+		err := r.err
+		r.mu.Unlock()
+
+		if err != nil {
+			w.WriteHeader(http.StatusInternalServerError)
+			fmt.Fprintf(w, "%v: %v\n", r.name, err)
+			return
+		}
+	}
+
+	w.WriteHeader(http.StatusOK)
+}
+
 // a statusEntry is a status string at a specific time.
 type statusEntry struct {
 	status string