Browse code

allow features option live reloadable

Signed-off-by: Anda Xu <anda.xu@docker.com>

Anda Xu authored on 2018/08/22 15:05:26
Showing 7 changed files
... ...
@@ -7,15 +7,19 @@ import (
7 7
 
8 8
 // buildRouter is a router to talk with the build controller
9 9
 type buildRouter struct {
10
-	backend        Backend
11
-	daemon         experimentalProvider
12
-	routes         []router.Route
13
-	builderVersion types.BuilderVersion
10
+	backend  Backend
11
+	daemon   experimentalProvider
12
+	routes   []router.Route
13
+	features *map[string]bool
14 14
 }
15 15
 
16 16
 // NewRouter initializes a new build router
17
-func NewRouter(b Backend, d experimentalProvider, bv types.BuilderVersion) router.Router {
18
-	r := &buildRouter{backend: b, daemon: d, builderVersion: bv}
17
+func NewRouter(b Backend, d experimentalProvider, features *map[string]bool) router.Router {
18
+	r := &buildRouter{
19
+		backend:  b,
20
+		daemon:   d,
21
+		features: features,
22
+	}
19 23
 	r.initRoutes()
20 24
 	return r
21 25
 }
... ...
@@ -32,3 +36,18 @@ func (r *buildRouter) initRoutes() {
32 32
 		router.NewPostRoute("/build/cancel", r.postCancel),
33 33
 	}
34 34
 }
35
+
36
+// BuilderVersion derives the default docker builder version from the config
37
+// Note: it is valid to have BuilderVersion unset which means it is up to the
38
+// client to choose which builder to use.
39
+func BuilderVersion(features map[string]bool) types.BuilderVersion {
40
+	var bv types.BuilderVersion
41
+	if v, ok := features["buildkit"]; ok {
42
+		if v {
43
+			bv = types.BuilderBuildKit
44
+		} else {
45
+			bv = types.BuilderV1
46
+		}
47
+	}
48
+	return bv
49
+}
... ...
@@ -230,8 +230,9 @@ func (br *buildRouter) postBuild(ctx context.Context, w http.ResponseWriter, r *
230 230
 		return errdefs.InvalidParameter(errors.New("squash is only supported with experimental mode"))
231 231
 	}
232 232
 
233
+	builderVersion := BuilderVersion(*br.features)
233 234
 	// check if the builder feature has been enabled from daemon as well.
234
-	if buildOptions.Version == types.BuilderBuildKit && br.builderVersion != "" && br.builderVersion != types.BuilderBuildKit {
235
+	if buildOptions.Version == types.BuilderBuildKit && builderVersion != "" && builderVersion != types.BuilderBuildKit {
235 236
 		return errdefs.InvalidParameter(errors.New("buildkit is not enabled on daemon"))
236 237
 	}
237 238
 
... ...
@@ -2,30 +2,29 @@ package system // import "github.com/docker/docker/api/server/router/system"
2 2
 
3 3
 import (
4 4
 	"github.com/docker/docker/api/server/router"
5
-	"github.com/docker/docker/api/types"
6
-	buildkit "github.com/docker/docker/builder/builder-next"
5
+	"github.com/docker/docker/builder/builder-next"
7 6
 	"github.com/docker/docker/builder/fscache"
8 7
 )
9 8
 
10 9
 // systemRouter provides information about the Docker system overall.
11 10
 // It gathers information about host, daemon and container events.
12 11
 type systemRouter struct {
13
-	backend        Backend
14
-	cluster        ClusterBackend
15
-	routes         []router.Route
16
-	fscache        *fscache.FSCache // legacy
17
-	builder        *buildkit.Builder
18
-	builderVersion types.BuilderVersion
12
+	backend  Backend
13
+	cluster  ClusterBackend
14
+	routes   []router.Route
15
+	fscache  *fscache.FSCache // legacy
16
+	builder  *buildkit.Builder
17
+	features *map[string]bool
19 18
 }
20 19
 
21 20
 // NewRouter initializes a new system router
22
-func NewRouter(b Backend, c ClusterBackend, fscache *fscache.FSCache, builder *buildkit.Builder, bv types.BuilderVersion) router.Router {
21
+func NewRouter(b Backend, c ClusterBackend, fscache *fscache.FSCache, builder *buildkit.Builder, features *map[string]bool) router.Router {
23 22
 	r := &systemRouter{
24
-		backend:        b,
25
-		cluster:        c,
26
-		fscache:        fscache,
27
-		builder:        builder,
28
-		builderVersion: bv,
23
+		backend:  b,
24
+		cluster:  c,
25
+		fscache:  fscache,
26
+		builder:  builder,
27
+		features: features,
29 28
 	}
30 29
 
31 30
 	r.routes = []router.Route{
... ...
@@ -8,6 +8,7 @@ import (
8 8
 	"time"
9 9
 
10 10
 	"github.com/docker/docker/api/server/httputils"
11
+	"github.com/docker/docker/api/server/router/build"
11 12
 	"github.com/docker/docker/api/types"
12 13
 	"github.com/docker/docker/api/types/events"
13 14
 	"github.com/docker/docker/api/types/filters"
... ...
@@ -26,7 +27,8 @@ func optionsHandler(ctx context.Context, w http.ResponseWriter, r *http.Request,
26 26
 }
27 27
 
28 28
 func (s *systemRouter) pingHandler(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
29
-	if bv := s.builderVersion; bv != "" {
29
+	builderVersion := build.BuilderVersion(*s.features)
30
+	if bv := builderVersion; bv != "" {
30 31
 		w.Header().Set("Builder-Version", string(bv))
31 32
 	}
32 33
 	_, err := w.Write([]byte{'O', 'K'})
... ...
@@ -27,7 +27,6 @@ import (
27 27
 	swarmrouter "github.com/docker/docker/api/server/router/swarm"
28 28
 	systemrouter "github.com/docker/docker/api/server/router/system"
29 29
 	"github.com/docker/docker/api/server/router/volume"
30
-	"github.com/docker/docker/api/types"
31 30
 	buildkit "github.com/docker/docker/builder/builder-next"
32 31
 	"github.com/docker/docker/builder/dockerfile"
33 32
 	"github.com/docker/docker/builder/fscache"
... ...
@@ -253,8 +252,8 @@ type routerOptions struct {
253 253
 	sessionManager *session.Manager
254 254
 	buildBackend   *buildbackend.Backend
255 255
 	buildCache     *fscache.FSCache // legacy
256
+	features       *map[string]bool
256 257
 	buildkit       *buildkit.Builder
257
-	builderVersion types.BuilderVersion
258 258
 	daemon         *daemon.Daemon
259 259
 	api            *apiserver.Server
260 260
 	cluster        *cluster.Cluster
... ...
@@ -300,20 +299,12 @@ func newRouterOptions(config *config.Config, daemon *daemon.Daemon) (routerOptio
300 300
 	if err != nil {
301 301
 		return opts, errors.Wrap(err, "failed to create buildmanager")
302 302
 	}
303
-	var bv types.BuilderVersion
304
-	if v, ok := config.Features["buildkit"]; ok {
305
-		if v {
306
-			bv = types.BuilderBuildKit
307
-		} else {
308
-			bv = types.BuilderV1
309
-		}
310
-	}
311 303
 	return routerOptions{
312 304
 		sessionManager: sm,
313 305
 		buildBackend:   bb,
314 306
 		buildCache:     buildCache,
315 307
 		buildkit:       bk,
316
-		builderVersion: bv,
308
+		features:       daemon.Features(),
317 309
 		daemon:         daemon,
318 310
 	}, nil
319 311
 }
... ...
@@ -487,9 +478,9 @@ func initRouter(opts routerOptions) {
487 487
 		checkpointrouter.NewRouter(opts.daemon, decoder),
488 488
 		container.NewRouter(opts.daemon, decoder),
489 489
 		image.NewRouter(opts.daemon.ImageService()),
490
-		systemrouter.NewRouter(opts.daemon, opts.cluster, opts.buildCache, opts.buildkit, opts.builderVersion),
490
+		systemrouter.NewRouter(opts.daemon, opts.cluster, opts.buildCache, opts.buildkit, opts.features),
491 491
 		volume.NewRouter(opts.daemon.VolumesService()),
492
-		build.NewRouter(opts.buildBackend, opts.daemon, opts.builderVersion),
492
+		build.NewRouter(opts.buildBackend, opts.daemon, opts.features),
493 493
 		sessionrouter.NewRouter(opts.sessionManager),
494 494
 		swarmrouter.NewRouter(opts.cluster),
495 495
 		pluginrouter.NewRouter(opts.daemon.PluginManager()),
... ...
@@ -136,6 +136,11 @@ func (daemon *Daemon) HasExperimental() bool {
136 136
 	return daemon.configStore != nil && daemon.configStore.Experimental
137 137
 }
138 138
 
139
+// Features returns the features map from configStore
140
+func (daemon *Daemon) Features() *map[string]bool {
141
+	return &daemon.configStore.Features
142
+}
143
+
139 144
 func (daemon *Daemon) restore() error {
140 145
 	containers := make(map[string]*container.Container)
141 146
 
... ...
@@ -45,6 +45,7 @@ func (daemon *Daemon) Reload(conf *config.Config) (err error) {
45 45
 	daemon.reloadDebug(conf, attributes)
46 46
 	daemon.reloadMaxConcurrentDownloadsAndUploads(conf, attributes)
47 47
 	daemon.reloadShutdownTimeout(conf, attributes)
48
+	daemon.reloadFeatures(conf, attributes)
48 49
 
49 50
 	if err := daemon.reloadClusterDiscovery(conf, attributes); err != nil {
50 51
 		return err
... ...
@@ -322,3 +323,13 @@ func (daemon *Daemon) reloadNetworkDiagnosticPort(conf *config.Config, attribute
322 322
 
323 323
 	return nil
324 324
 }
325
+
326
+// reloadFeatures updates configuration with enabled/disabled features
327
+func (daemon *Daemon) reloadFeatures(conf *config.Config, attributes map[string]string) {
328
+	// update corresponding configuration
329
+	// note that we allow features option to be entirely unset
330
+	daemon.configStore.Features = conf.Features
331
+
332
+	// prepare reload event attributes with updatable configurations
333
+	attributes["features"] = fmt.Sprintf("%v", daemon.configStore.Features)
334
+}