diff --git a/.gitignore b/.gitignore index d7618d0..e7f4e38 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ acme-dns.db acme-dns.log .vagrant coverage.out +.idea/ diff --git a/README.md b/README.md index 28d1d37..f996a9a 100644 --- a/README.md +++ b/README.md @@ -102,6 +102,28 @@ The method allows you to update the TXT answer contents of your unique subdomain } ``` +### Health check endpoint + +The method can be used to check readiness and/or liveness of the server. It will return status code 200 on success or won't be reachable. + +```GET /health``` + +#### Example using a Kubernetes deployment + +``` +# ... +readinessProbe: + httpGet: + path: /health + port: 80 + periodSeconds: 2 + initialDelaySeconds: 2 + failureThreshold: 3 + successThreshold: 1 +livenessProbe: + # same as for readinessProbe... +``` + ## Self-hosted You are encouraged to run your own acme-dns instance, because you are effectively authorizing the acme-dns server to act on your behalf in providing the answer to the challenging CA, making the instance able to request (and get issued) a TLS certificate for the domain that has CNAME pointing to it. @@ -304,6 +326,8 @@ logformat = "text" ## Changelog - master + - Unreleased + - Added new endpoint to perform health checks - Changed - A new protocol selection for DNS server "both", that binds both - UDP and TCP ports. - v0.6 diff --git a/api.go b/api.go index d151c82..5e532ef 100644 --- a/api.go +++ b/api.go @@ -93,3 +93,8 @@ func webUpdatePost(w http.ResponseWriter, r *http.Request, _ httprouter.Params) w.WriteHeader(updStatus) w.Write(upd) } + +// Endpoint used to check the readiness and/or liveness (health) of the server. +func healthCheck(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { + w.WriteHeader(http.StatusOK) +} diff --git a/api_test.go b/api_test.go index bd359f2..b3368f8 100644 --- a/api_test.go +++ b/api_test.go @@ -71,6 +71,7 @@ func setupRouter(debug bool, noauth bool) http.Handler { Debug: Config.General.Debug, }) api.POST("/register", webRegisterPost) + api.GET("/health", healthCheck) if noauth { api.POST("/update", noAuth(webUpdatePost)) } else { @@ -406,3 +407,11 @@ func TestApiManyUpdateWithIpCheckHeaders(t *testing.T) { } Config.API.UseHeader = false } + +func TestApiHealthCheck(t *testing.T) { + router := setupRouter(false, false) + server := httptest.NewServer(router) + defer server.Close() + e := getExpect(t, server) + e.GET("/health").Expect().Status(http.StatusOK) +} diff --git a/main.go b/main.go index 6eabf44..1557c8e 100644 --- a/main.go +++ b/main.go @@ -128,6 +128,7 @@ func startHTTPAPI(errChan chan error) { api.POST("/register", webRegisterPost) } api.POST("/update", Auth(webUpdatePost)) + api.GET("/health", healthCheck) host := Config.API.IP + ":" + Config.API.Port