Add /stop endpoint to admin (#2671)

* Add stop command to admin.  Exit after stop.

* Return error on incorrect http Method and provide better logging.

* reuse stopAndCleanup function for all graceful stops
This commit is contained in:
Toby Allen 2019-07-20 17:48:46 +01:00 committed by Matt Holt
parent b855e66170
commit d98f2faef9
2 changed files with 26 additions and 8 deletions

View File

@ -24,10 +24,12 @@ import (
"net" "net"
"net/http" "net/http"
"net/http/pprof" "net/http/pprof"
"os"
"strings" "strings"
"sync" "sync"
"time" "time"
"github.com/mholt/certmagic"
"github.com/rs/cors" "github.com/rs/cors"
) )
@ -83,6 +85,7 @@ func StartAdmin(initialConfigJSON []byte) error {
mux := http.NewServeMux() mux := http.NewServeMux()
mux.HandleFunc("/load", handleLoadConfig) mux.HandleFunc("/load", handleLoadConfig)
mux.HandleFunc("/stop", handleStop)
///// BEGIN PPROF STUFF (TODO: Temporary) ///// ///// BEGIN PPROF STUFF (TODO: Temporary) /////
mux.HandleFunc("/debug/pprof/", pprof.Index) mux.HandleFunc("/debug/pprof/", pprof.Index)
@ -149,7 +152,7 @@ type AdminRoute struct {
func handleLoadConfig(w http.ResponseWriter, r *http.Request) { func handleLoadConfig(w http.ResponseWriter, r *http.Request) {
r.Close = true r.Close = true
if r.Method != "POST" { if r.Method != http.MethodPost {
http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed) http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
return return
} }
@ -167,6 +170,27 @@ func handleLoadConfig(w http.ResponseWriter, r *http.Request) {
} }
} }
func handleStop(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
return
}
log.Println("[ADMIN] Initiating shutdown")
if err := stopAndCleanup(); err != nil {
log.Printf("[ADMIN][ERROR] stopping: %v \n", err)
}
log.Println("[ADMIN] Exiting")
os.Exit(0)
}
func stopAndCleanup() error {
if err := Stop(); err != nil {
return err
}
certmagic.CleanUpOwnLocks()
return nil
}
// Load loads and starts a configuration. // Load loads and starts a configuration.
func Load(r io.Reader) error { func Load(r io.Reader) error {
buf := bufPool.Get().(*bytes.Buffer) buf := bufPool.Get().(*bytes.Buffer)

View File

@ -18,8 +18,6 @@ import (
"log" "log"
"os" "os"
"os/signal" "os/signal"
"github.com/mholt/certmagic"
) )
// TrapSignals create signal/interrupt handlers as best it can for the // TrapSignals create signal/interrupt handlers as best it can for the
@ -57,16 +55,12 @@ func trapSignalsCrossPlatform() {
func gracefulStop(sigName string) { func gracefulStop(sigName string) {
exitCode := ExitCodeSuccess exitCode := ExitCodeSuccess
// first stop all the apps err := stopAndCleanup()
err := Stop()
if err != nil { if err != nil {
log.Printf("[ERROR] %s stop: %v", sigName, err) log.Printf("[ERROR] %s stop: %v", sigName, err)
exitCode = ExitCodeFailedQuit exitCode = ExitCodeFailedQuit
} }
// always, always, always try to clean up locks
certmagic.CleanUpOwnLocks()
log.Printf("[INFO] %s: Shutdown done", sigName) log.Printf("[INFO] %s: Shutdown done", sigName)
os.Exit(exitCode) os.Exit(exitCode)
} }