Browse Source

Merge pull request #28524 from aluzzardi/experimental-routes

router: Return explicit error rather than 404 for experimental.
Victor Vieux 8 years ago
parent
commit
c3fab6d473

+ 3 - 3
api/server/router/checkpoint/checkpoint.go

@@ -29,8 +29,8 @@ func (r *checkpointRouter) Routes() []router.Route {
 
 func (r *checkpointRouter) initRoutes() {
 	r.routes = []router.Route{
-		router.NewGetRoute("/containers/{name:.*}/checkpoints", r.getContainerCheckpoints),
-		router.NewPostRoute("/containers/{name:.*}/checkpoints", r.postContainerCheckpoint),
-		router.NewDeleteRoute("/containers/{name}/checkpoints/{checkpoint}", r.deleteContainerCheckpoint),
+		router.Experimental(router.NewGetRoute("/containers/{name:.*}/checkpoints", r.getContainerCheckpoints)),
+		router.Experimental(router.NewPostRoute("/containers/{name:.*}/checkpoints", r.postContainerCheckpoint)),
+		router.Experimental(router.NewDeleteRoute("/containers/{name}/checkpoints/{checkpoint}", r.deleteContainerCheckpoint)),
 	}
 }

+ 67 - 0
api/server/router/experimental.go

@@ -0,0 +1,67 @@
+package router
+
+import (
+	"errors"
+	"net/http"
+
+	"golang.org/x/net/context"
+
+	apierrors "github.com/docker/docker/api/errors"
+	"github.com/docker/docker/api/server/httputils"
+)
+
+var (
+	errExperimentalFeature = errors.New("This experimental feature is disabled by default. Start the Docker daemon with --experimental in order to enable it.")
+)
+
+// ExperimentalRoute defines an experimental API route that can be enabled or disabled.
+type ExperimentalRoute interface {
+	Route
+
+	Enable()
+	Disable()
+}
+
+// experimentalRoute defines an experimental API route that can be enabled or disabled.
+// It implements ExperimentalRoute
+type experimentalRoute struct {
+	local   Route
+	handler httputils.APIFunc
+}
+
+// Enable enables this experimental route
+func (r *experimentalRoute) Enable() {
+	r.handler = r.local.Handler()
+}
+
+// Disable disables the experimental route
+func (r *experimentalRoute) Disable() {
+	r.handler = experimentalHandler
+}
+
+func experimentalHandler(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+	return apierrors.NewErrorWithStatusCode(errExperimentalFeature, http.StatusNotImplemented)
+}
+
+// Handler returns returns the APIFunc to let the server wrap it in middlewares.
+func (r *experimentalRoute) Handler() httputils.APIFunc {
+	return r.handler
+}
+
+// Method returns the http method that the route responds to.
+func (r *experimentalRoute) Method() string {
+	return r.local.Method()
+}
+
+// Path returns the subpath where the route responds to.
+func (r *experimentalRoute) Path() string {
+	return r.local.Path()
+}
+
+// Experimental will mark a route as experimental.
+func Experimental(r Route) Route {
+	return &experimentalRoute{
+		local:   r,
+		handler: experimentalHandler,
+	}
+}

+ 3 - 14
api/server/router/swarm/cluster.go

@@ -1,9 +1,6 @@
 package swarm
 
-import (
-	"github.com/docker/docker/api/server/router"
-	"github.com/docker/docker/daemon"
-)
+import "github.com/docker/docker/api/server/router"
 
 // swarmRouter is a router to talk with the build controller
 type swarmRouter struct {
@@ -12,14 +9,11 @@ type swarmRouter struct {
 }
 
 // NewRouter initializes a new build router
-func NewRouter(d *daemon.Daemon, b Backend) router.Router {
+func NewRouter(b Backend) router.Router {
 	r := &swarmRouter{
 		backend: b,
 	}
 	r.initRoutes()
-	if d.HasExperimental() {
-		r.addExperimentalRoutes()
-	}
 	return r
 }
 
@@ -28,12 +22,6 @@ func (sr *swarmRouter) Routes() []router.Route {
 	return sr.routes
 }
 
-func (sr *swarmRouter) addExperimentalRoutes() {
-	sr.routes = append(sr.routes,
-		router.Cancellable(router.NewGetRoute("/services/{id}/logs", sr.getServiceLogs)),
-	)
-}
-
 func (sr *swarmRouter) initRoutes() {
 	sr.routes = []router.Route{
 		router.NewPostRoute("/swarm/init", sr.initCluster),
@@ -48,6 +36,7 @@ func (sr *swarmRouter) initRoutes() {
 		router.NewPostRoute("/services/create", sr.createService),
 		router.NewPostRoute("/services/{id}/update", sr.updateService),
 		router.NewDeleteRoute("/services/{id}", sr.removeService),
+		router.Experimental(router.Cancellable(router.NewGetRoute("/services/{id}/logs", sr.getServiceLogs))),
 		router.NewGetRoute("/nodes", sr.getNodes),
 		router.NewGetRoute("/nodes/{id}", sr.getNode),
 		router.NewDeleteRoute("/nodes/{id}", sr.removeNode),

+ 16 - 8
cmd/dockerd/daemon.go

@@ -17,6 +17,7 @@ import (
 	"github.com/docker/docker/api/server/middleware"
 	"github.com/docker/docker/api/server/router"
 	"github.com/docker/docker/api/server/router/build"
+	checkpointrouter "github.com/docker/docker/api/server/router/checkpoint"
 	"github.com/docker/docker/api/server/router/container"
 	"github.com/docker/docker/api/server/router/image"
 	"github.com/docker/docker/api/server/router/network"
@@ -461,25 +462,32 @@ func loadDaemonCliConfig(opts daemonOptions) (*daemon.Config, error) {
 func initRouter(s *apiserver.Server, d *daemon.Daemon, c *cluster.Cluster) {
 	decoder := runconfig.ContainerDecoder{}
 
-	routers := []router.Router{}
-
-	// we need to add the checkpoint router before the container router or the DELETE gets masked
-	routers = addExperimentalRouters(routers, d, decoder)
-
-	routers = append(routers, []router.Router{
+	routers := []router.Router{
+		// we need to add the checkpoint router before the container router or the DELETE gets masked
+		checkpointrouter.NewRouter(d, decoder),
 		container.NewRouter(d, decoder),
 		image.NewRouter(d, decoder),
 		systemrouter.NewRouter(d, c),
 		volume.NewRouter(d),
 		build.NewRouter(dockerfile.NewBuildManager(d)),
-		swarmrouter.NewRouter(d, c),
+		swarmrouter.NewRouter(c),
 		pluginrouter.NewRouter(plugin.GetManager()),
-	}...)
+	}
 
 	if d.NetworkControllerEnabled() {
 		routers = append(routers, network.NewRouter(d, c))
 	}
 
+	if d.HasExperimental() {
+		for _, r := range routers {
+			for _, route := range r.Routes() {
+				if experimental, ok := route.(router.ExperimentalRoute); ok {
+					experimental.Enable()
+				}
+			}
+		}
+	}
+
 	s.InitRouter(utils.IsDebugEnabled(), routers...)
 }
 

+ 0 - 15
cmd/dockerd/routes_experimental.go

@@ -1,15 +0,0 @@
-package main
-
-import (
-	"github.com/docker/docker/api/server/httputils"
-	"github.com/docker/docker/api/server/router"
-	checkpointrouter "github.com/docker/docker/api/server/router/checkpoint"
-	"github.com/docker/docker/daemon"
-)
-
-func addExperimentalRouters(routers []router.Router, d *daemon.Daemon, decoder httputils.ContainerDecoder) []router.Router {
-	if !d.HasExperimental() {
-		return []router.Router{}
-	}
-	return append(routers, checkpointrouter.NewRouter(d, decoder))
-}