|
|
@@ -0,0 +1,68 @@
|
|
|
+// package readiness implements a minimal health-checking mechanism for use as k8s readiness probes. It will always
|
|
|
+// return a "ready" state after the conditions have been met for the first time - it's not meant for monitoring.
|
|
|
+//
|
|
|
+// Uses a global singleton registry (similar to the Prometheus client's default behavior).
|
|
|
+package readiness
|
|
|
+
|
|
|
+import (
|
|
|
+ "bytes"
|
|
|
+ "fmt"
|
|
|
+ "net/http"
|
|
|
+ "sync"
|
|
|
+)
|
|
|
+
|
|
|
+var (
|
|
|
+ mu = sync.Mutex{}
|
|
|
+ registry = map[string]bool{}
|
|
|
+)
|
|
|
+
|
|
|
+// RegisterComponent registers the given component name such that it is required to be ready for the global check to succeed.
|
|
|
+func RegisterComponent(component string) {
|
|
|
+ mu.Lock()
|
|
|
+ if _, ok := registry[component]; ok {
|
|
|
+ panic("component already registered")
|
|
|
+ }
|
|
|
+ registry[component] = false
|
|
|
+ mu.Unlock()
|
|
|
+}
|
|
|
+
|
|
|
+// SetReady sets the given global component state.
|
|
|
+func SetReady(component string) {
|
|
|
+ mu.Lock()
|
|
|
+ if !registry[component] {
|
|
|
+ registry[component] = true
|
|
|
+ }
|
|
|
+ mu.Unlock()
|
|
|
+}
|
|
|
+
|
|
|
+// Handler returns a net/http handler for the readiness check. It returns 200 OK if all components are ready,
|
|
|
+// or 412 Precondition Failed otherwise. For operator convenience, a list of components and their states
|
|
|
+// is returned as plain text (not meant for machine consumption!).
|
|
|
+func Handler(w http.ResponseWriter, r *http.Request) {
|
|
|
+ ready := true
|
|
|
+
|
|
|
+ resp := new(bytes.Buffer)
|
|
|
+ _, err := resp.Write([]byte("[not suitable for monitoring - do not parse]\n\n"))
|
|
|
+ if err != nil {
|
|
|
+ panic(err)
|
|
|
+ }
|
|
|
+
|
|
|
+ for k, v := range registry {
|
|
|
+ _, err = fmt.Fprintln(resp, fmt.Sprintf("%s\t%v", k, v))
|
|
|
+ if err != nil {
|
|
|
+ panic(err)
|
|
|
+ }
|
|
|
+
|
|
|
+ if !v {
|
|
|
+ ready = false
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if !ready {
|
|
|
+ w.WriteHeader(http.StatusPreconditionFailed)
|
|
|
+ } else {
|
|
|
+ w.WriteHeader(http.StatusOK)
|
|
|
+ }
|
|
|
+
|
|
|
+ _, _ = resp.WriteTo(w)
|
|
|
+}
|