diff --git a/.gitignore b/.gitignore index d7618d0c4f0a2e42a6cf74f1b6d6f16e571e6421..e7f4e384341b658e0e5022c93eef2554c8464574 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 28d1d3709e58873abc607a1eb8dca99b8162443f..f996a9ad140f361c17b1eeec31fea7c1651e33c3 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 d151c8265b2c01a48136105d087572a35da79460..5e532efb3940b5d7468cfbaa32a3ccaf46e70faa 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 bd359f2c4750a659a6bd61e5ff184beac48cb298..b3368f8010009c4408ab38d69cc813115c14ff50 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 6eabf44584dbfecd72b2893c3cd79ff33db869fb..1557c8e75fcb371e5bf3e2d2aea72d760483cc4d 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