readiness.go 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. package metrics
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "net/http"
  6. "github.com/google/uuid"
  7. "github.com/rs/zerolog"
  8. conn "github.com/cloudflare/cloudflared/connection"
  9. "github.com/cloudflare/cloudflared/tunnelstate"
  10. )
  11. // ReadyServer serves HTTP 200 if the tunnel can serve traffic. Intended for k8s readiness checks.
  12. type ReadyServer struct {
  13. clientID uuid.UUID
  14. tracker *tunnelstate.ConnTracker
  15. }
  16. // NewReadyServer initializes a ReadyServer and starts listening for dis/connection events.
  17. func NewReadyServer(log *zerolog.Logger, clientID uuid.UUID) *ReadyServer {
  18. return &ReadyServer{
  19. clientID: clientID,
  20. tracker: tunnelstate.NewConnTracker(log),
  21. }
  22. }
  23. func (rs *ReadyServer) OnTunnelEvent(c conn.Event) {
  24. rs.tracker.OnTunnelEvent(c)
  25. }
  26. type body struct {
  27. Status int `json:"status"`
  28. ReadyConnections uint `json:"readyConnections"`
  29. ConnectorID uuid.UUID `json:"connectorId"`
  30. }
  31. // ServeHTTP responds with HTTP 200 if the tunnel is connected to the edge.
  32. func (rs *ReadyServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  33. statusCode, readyConnections := rs.makeResponse()
  34. w.WriteHeader(statusCode)
  35. body := body{
  36. Status: statusCode,
  37. ReadyConnections: readyConnections,
  38. ConnectorID: rs.clientID,
  39. }
  40. msg, err := json.Marshal(body)
  41. if err != nil {
  42. _, _ = fmt.Fprintf(w, `{"error": "%s"}`, err)
  43. }
  44. _, _ = w.Write(msg)
  45. }
  46. // This is the bulk of the logic for ServeHTTP, broken into its own pure function
  47. // to make unit testing easy.
  48. func (rs *ReadyServer) makeResponse() (statusCode int, readyConnections uint) {
  49. readyConnections = rs.tracker.CountActiveConns()
  50. if readyConnections > 0 {
  51. return http.StatusOK, readyConnections
  52. } else {
  53. return http.StatusServiceUnavailable, readyConnections
  54. }
  55. }