Enable pprof/debug endpoints by default
Makes sure that debug endpoints are always available, which will aid in debugging demon issues. Wraps debug endpoints in the middleware chain so the can be blocked by authz. Signed-off-by: Brian Goff <cpuguy83@gmail.com> Upstream-commit: 408c7ade7008ca9b2181e12e51a01250a7a94413 Component: engine
This commit is contained in:
@@ -1,46 +0,0 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"expvar"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/pprof"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
const debugPathPrefix = "/debug/"
|
||||
|
||||
func profilerSetup(mainRouter *mux.Router) {
|
||||
var r = mainRouter.PathPrefix(debugPathPrefix).Subrouter()
|
||||
r.HandleFunc("/vars", expVars)
|
||||
r.HandleFunc("/pprof/", pprof.Index)
|
||||
r.HandleFunc("/pprof/cmdline", pprof.Cmdline)
|
||||
r.HandleFunc("/pprof/profile", pprof.Profile)
|
||||
r.HandleFunc("/pprof/symbol", pprof.Symbol)
|
||||
r.HandleFunc("/pprof/trace", pprof.Trace)
|
||||
r.HandleFunc("/pprof/{name}", handlePprof)
|
||||
}
|
||||
|
||||
func handlePprof(w http.ResponseWriter, r *http.Request) {
|
||||
var name string
|
||||
if vars := mux.Vars(r); vars != nil {
|
||||
name = vars["name"]
|
||||
}
|
||||
pprof.Handler(name).ServeHTTP(w, r)
|
||||
}
|
||||
|
||||
// Replicated from expvar.go as not public.
|
||||
func expVars(w http.ResponseWriter, r *http.Request) {
|
||||
first := true
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
fmt.Fprintln(w, "{")
|
||||
expvar.Do(func(kv expvar.KeyValue) {
|
||||
if !first {
|
||||
fmt.Fprintln(w, ",")
|
||||
}
|
||||
first = false
|
||||
fmt.Fprintf(w, "%q: %s", kv.Key, kv.Value)
|
||||
})
|
||||
fmt.Fprintln(w, "\n}")
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package debug
|
||||
|
||||
import (
|
||||
"expvar"
|
||||
"net/http"
|
||||
"net/http/pprof"
|
||||
|
||||
"github.com/docker/docker/api/server/httputils"
|
||||
"github.com/docker/docker/api/server/router"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
// NewRouter creates a new debug router
|
||||
// The debug router holds endpoints for debug the daemon, such as those for pprof.
|
||||
func NewRouter() router.Router {
|
||||
r := &debugRouter{}
|
||||
r.initRoutes()
|
||||
return r
|
||||
}
|
||||
|
||||
type debugRouter struct {
|
||||
routes []router.Route
|
||||
}
|
||||
|
||||
func (r *debugRouter) initRoutes() {
|
||||
r.routes = []router.Route{
|
||||
router.NewGetRoute("/vars", frameworkAdaptHandler(expvar.Handler())),
|
||||
router.NewGetRoute("/pprof/", frameworkAdaptHandlerFunc(pprof.Index)),
|
||||
router.NewGetRoute("/pprof/cmdline", frameworkAdaptHandlerFunc(pprof.Cmdline)),
|
||||
router.NewGetRoute("/pprof/profile", frameworkAdaptHandlerFunc(pprof.Profile)),
|
||||
router.NewGetRoute("/pprof/symbol", frameworkAdaptHandlerFunc(pprof.Symbol)),
|
||||
router.NewGetRoute("/pprof/trace", frameworkAdaptHandlerFunc(pprof.Trace)),
|
||||
router.NewGetRoute("/pprof/{name}", handlePprof),
|
||||
}
|
||||
}
|
||||
|
||||
func (r *debugRouter) Routes() []router.Route {
|
||||
return r.routes
|
||||
}
|
||||
|
||||
func frameworkAdaptHandler(handler http.Handler) httputils.APIFunc {
|
||||
return func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
handler.ServeHTTP(w, r)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func frameworkAdaptHandlerFunc(handler http.HandlerFunc) httputils.APIFunc {
|
||||
return func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
handler(w, r)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package debug
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/pprof"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
func handlePprof(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
pprof.Handler(vars["name"]).ServeHTTP(w, r)
|
||||
return nil
|
||||
}
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/docker/docker/api/server/httputils"
|
||||
"github.com/docker/docker/api/server/middleware"
|
||||
"github.com/docker/docker/api/server/router"
|
||||
"github.com/docker/docker/api/server/router/debug"
|
||||
"github.com/docker/docker/dockerversion"
|
||||
"github.com/gorilla/mux"
|
||||
"golang.org/x/net/context"
|
||||
@@ -148,13 +149,10 @@ func (s *Server) makeHTTPHandler(handler httputils.APIFunc) http.HandlerFunc {
|
||||
|
||||
// InitRouter initializes the list of routers for the server.
|
||||
// This method also enables the Go profiler if enableProfiler is true.
|
||||
func (s *Server) InitRouter(enableProfiler bool, routers ...router.Router) {
|
||||
func (s *Server) InitRouter(routers ...router.Router) {
|
||||
s.routers = append(s.routers, routers...)
|
||||
|
||||
m := s.createMux()
|
||||
if enableProfiler {
|
||||
profilerSetup(m)
|
||||
}
|
||||
s.routerSwapper = &routerSwapper{
|
||||
router: m,
|
||||
}
|
||||
@@ -175,6 +173,13 @@ func (s *Server) createMux() *mux.Router {
|
||||
}
|
||||
}
|
||||
|
||||
debugRouter := debug.NewRouter()
|
||||
s.routers = append(s.routers, debugRouter)
|
||||
for _, r := range debugRouter.Routes() {
|
||||
f := s.makeHTTPHandler(r.Handler())
|
||||
m.Path("/debug" + r.Path()).Handler(f)
|
||||
}
|
||||
|
||||
err := errors.NewRequestNotFoundError(fmt.Errorf("page not found"))
|
||||
notFoundHandler := httputils.MakeErrorHandler(err)
|
||||
m.HandleFunc(versionMatcher+"/{path:.*}", notFoundHandler)
|
||||
@@ -194,15 +199,3 @@ func (s *Server) Wait(waitChan chan error) {
|
||||
}
|
||||
waitChan <- nil
|
||||
}
|
||||
|
||||
// DisableProfiler reloads the server mux without adding the profiler routes.
|
||||
func (s *Server) DisableProfiler() {
|
||||
s.routerSwapper.Swap(s.createMux())
|
||||
}
|
||||
|
||||
// EnableProfiler reloads the server mux adding the profiler routes.
|
||||
func (s *Server) EnableProfiler() {
|
||||
m := s.createMux()
|
||||
profilerSetup(m)
|
||||
s.routerSwapper.Swap(m)
|
||||
}
|
||||
|
||||
@@ -383,10 +383,8 @@ func (cli *DaemonCli) reloadConfig() {
|
||||
switch {
|
||||
case debugEnabled && !config.Debug: // disable debug
|
||||
debug.Disable()
|
||||
cli.api.DisableProfiler()
|
||||
case config.Debug && !debugEnabled: // enable debug
|
||||
debug.Enable()
|
||||
cli.api.EnableProfiler()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -536,7 +534,7 @@ func initRouter(opts routerOptions) {
|
||||
}
|
||||
}
|
||||
|
||||
opts.api.InitRouter(debug.IsEnabled(), routers...)
|
||||
opts.api.InitRouter(routers...)
|
||||
}
|
||||
|
||||
// TODO: remove this from cli and return the authzMiddleware
|
||||
|
||||
Reference in New Issue
Block a user