1
0
mirror of https://blitiri.com.ar/repos/chasquid synced 2025-12-17 14:37:02 +00:00

Add /exit endpoint to monitoring server

Allows terminating chasquid via the network. Useful to trigger a restart
(if there is an init system to relaunch chasquid) and thus reload certificates.

Amended-by: Alberto Bertogli <albertito@blitiri.com.ar>
  Added tests, and adjusted shutdown sequence.
This commit is contained in:
ThinkChaos
2020-10-31 21:46:47 +01:00
committed by Alberto Bertogli
parent e9c6775418
commit bb1b921e3c
4 changed files with 50 additions and 2 deletions

View File

@@ -93,7 +93,7 @@ func main() {
go signalHandler()
if conf.MonitoringAddress != "" {
launchMonitoringServer(conf)
go launchMonitoringServer(conf)
}
s := smtpsrv.NewServer()

View File

@@ -1,6 +1,7 @@
package main
import (
"context"
"flag"
"fmt"
"html/template"
@@ -49,11 +50,16 @@ func launchMonitoringServer(conf *config.Config) {
}
})
srv := &http.Server{Addr: conf.MonitoringAddress}
http.HandleFunc("/exit", exitHandler(srv))
http.HandleFunc("/metrics", expvarom.MetricsHandler)
http.HandleFunc("/debug/flags", debugFlagsHandler)
http.HandleFunc("/debug/config", debugConfigHandler(conf))
go http.ListenAndServe(conf.MonitoringAddress, nil)
if err := srv.ListenAndServe(); err != http.ErrServerClosed {
log.Fatalf("Monitoring server failed: %v", err)
}
}
// Functions available inside the templates.
@@ -123,6 +129,28 @@ os hostname <i>{{.Hostname}}</i><br>
</html>
`))
func exitHandler(srv *http.Server) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if r.Method != "POST" {
http.Error(w, "Use POST method for exiting", http.StatusMethodNotAllowed)
return
}
log.Infof("Received /exit")
http.Error(w, "OK exiting", http.StatusOK)
// Launch srv.Shutdown asynchronously, and then exit.
// The http documentation says to wait for Shutdown to return before
// exiting, to gracefully close all ongoing requests.
go func() {
if err := srv.Shutdown(context.Background()); err != nil {
log.Fatalf("Monitoring server shutdown failed: %v", err)
}
os.Exit(0)
}()
}
}
func debugFlagsHandler(w http.ResponseWriter, r *http.Request) {
visited := make(map[string]bool)

View File

@@ -62,4 +62,15 @@ then
fail "new chasquid log did not have the expected entry"
fi
# Test that we can make the server exit using the /exit endpoint.
# First, a GET should fail with status 405.
fexp http://localhost:1099/exit -status 405
# A POST should succeed, return an OK body, and the daemon should
# eventually exit.
CHASQUID_PID=$(pgrep -s 0 chasquid)
fexp http://localhost:1099/exit -method POST -bodyre "OK"
wait_until ! kill -s 0 $CHASQUID_PID 2> /dev/null
success

View File

@@ -153,6 +153,15 @@ function wait_for_file() {
done
}
function wait_until() {
while true; do
if eval "$@"; then
return 0
fi
sleep 0.05
done
}
# Generate certs for the given hostname.
function generate_certs_for() {
CONFDIR="${CONFDIR:-config}"