add optional fields in daemon.json to enable buildkit

Signed-off-by: Anda Xu <anda.xu@docker.com>
This commit is contained in:
Anda Xu 2018-08-05 18:52:35 -07:00
parent 14d5569f19
commit 2be17666b4
10 changed files with 71 additions and 33 deletions

View File

@ -1,17 +1,21 @@
package build // import "github.com/docker/docker/api/server/router/build"
import "github.com/docker/docker/api/server/router"
import (
"github.com/docker/docker/api/server/router"
"github.com/docker/docker/api/types"
)
// buildRouter is a router to talk with the build controller
type buildRouter struct {
backend Backend
daemon experimentalProvider
routes []router.Route
backend Backend
daemon experimentalProvider
routes []router.Route
builderVersion types.BuilderVersion
}
// NewRouter initializes a new build router
func NewRouter(b Backend, d experimentalProvider) router.Router {
r := &buildRouter{backend: b, daemon: d}
func NewRouter(b Backend, d experimentalProvider, bv types.BuilderVersion) router.Router {
r := &buildRouter{backend: b, daemon: d, builderVersion: bv}
r.initRoutes()
return r
}

View File

@ -230,8 +230,10 @@ func (br *buildRouter) postBuild(ctx context.Context, w http.ResponseWriter, r *
return errdefs.InvalidParameter(errors.New("squash is only supported with experimental mode"))
}
if buildOptions.Version == types.BuilderBuildKit && !br.daemon.HasExperimental() {
return errdefs.InvalidParameter(errors.New("buildkit is only supported with experimental mode"))
// check if the builder feature has been enabled from daemon as well.
if buildOptions.Version == types.BuilderBuildKit &&
(br.builderVersion != types.BuilderBuildKit || !br.daemon.HasExperimental()) {
return errdefs.InvalidParameter(errors.New("buildkit is not enabled on daemon"))
}
out := io.Writer(output)

View File

@ -2,6 +2,7 @@ package system // import "github.com/docker/docker/api/server/router/system"
import (
"github.com/docker/docker/api/server/router"
"github.com/docker/docker/api/types"
buildkit "github.com/docker/docker/builder/builder-next"
"github.com/docker/docker/builder/fscache"
)
@ -9,25 +10,27 @@ import (
// systemRouter provides information about the Docker system overall.
// It gathers information about host, daemon and container events.
type systemRouter struct {
backend Backend
cluster ClusterBackend
routes []router.Route
fscache *fscache.FSCache // legacy
builder *buildkit.Builder
backend Backend
cluster ClusterBackend
routes []router.Route
fscache *fscache.FSCache // legacy
builder *buildkit.Builder
builderVersion types.BuilderVersion
}
// NewRouter initializes a new system router
func NewRouter(b Backend, c ClusterBackend, fscache *fscache.FSCache, builder *buildkit.Builder) router.Router {
func NewRouter(b Backend, c ClusterBackend, fscache *fscache.FSCache, builder *buildkit.Builder, bv types.BuilderVersion) router.Router {
r := &systemRouter{
backend: b,
cluster: c,
fscache: fscache,
builder: builder,
backend: b,
cluster: c,
fscache: fscache,
builder: builder,
builderVersion: bv,
}
r.routes = []router.Route{
router.NewOptionsRoute("/{anyroute:.*}", optionsHandler),
router.NewGetRoute("/_ping", pingHandler),
router.NewGetRoute("/_ping", r.pingHandler),
router.NewGetRoute("/events", r.getEvents, router.WithCancel),
router.NewGetRoute("/info", r.getInfo),
router.NewGetRoute("/version", r.getVersion),

View File

@ -25,7 +25,10 @@ func optionsHandler(ctx context.Context, w http.ResponseWriter, r *http.Request,
return nil
}
func pingHandler(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
func (s *systemRouter) pingHandler(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if bv := s.builderVersion; bv != "" {
w.Header().Set("Builder-Version", string(bv))
}
_, err := w.Write([]byte{'O', 'K'})
return err
}

View File

@ -6972,6 +6972,9 @@ paths:
API-Version:
type: "string"
description: "Max API Version the server supports"
BuildKit-Version:
type: "string"
description: "Default version of docker image builder"
Docker-Experimental:
type: "boolean"
description: "If the server is running with experimental mode enabled"

View File

@ -102,9 +102,10 @@ type ContainerStats struct {
// Ping contains response of Engine API:
// GET "/_ping"
type Ping struct {
APIVersion string
OSType string
Experimental bool
APIVersion string
OSType string
Experimental bool
BuilderVersion BuilderVersion
}
// ComponentVersion describes the version information for a specific component.

View File

@ -7,7 +7,7 @@ import (
"github.com/docker/docker/api/types"
)
// Ping pings the server and returns the value of the "Docker-Experimental", "OS-Type" & "API-Version" headers
// Ping pings the server and returns the value of the "Docker-Experimental", "Builder-Version", "OS-Type" & "API-Version" headers
func (cli *Client) Ping(ctx context.Context) (types.Ping, error) {
var ping types.Ping
req, err := cli.buildRequest("GET", path.Join(cli.basePath, "/_ping"), nil, nil)
@ -27,6 +27,9 @@ func (cli *Client) Ping(ctx context.Context) (types.Ping, error) {
ping.Experimental = true
}
ping.OSType = serverResp.header.Get("OSType")
if bv := serverResp.header.Get("Builder-Version"); bv != "" {
ping.BuilderVersion = types.BuilderVersion(bv)
}
}
return ping, cli.checkResponseErr(serverResp)
}

View File

@ -65,7 +65,6 @@ func installCommonConfigFlags(conf *config.Config, flags *pflag.FlagSet) {
flags.StringVar(&conf.SwarmDefaultAdvertiseAddr, "swarm-default-advertise-addr", "", "Set default address or interface for swarm advertised address")
flags.BoolVar(&conf.Experimental, "experimental", false, "Enable experimental features")
flags.StringVar(&conf.MetricsAddress, "metrics-addr", "", "Set default address and port to serve the metrics api on")
flags.Var(opts.NewNamedListOptsRef("node-generic-resources", &conf.NodeGenericResources, opts.ValidateSingleGenericResource), "node-generic-resource", "Advertise user-defined resource")

View File

@ -27,6 +27,7 @@ import (
swarmrouter "github.com/docker/docker/api/server/router/swarm"
systemrouter "github.com/docker/docker/api/server/router/system"
"github.com/docker/docker/api/server/router/volume"
"github.com/docker/docker/api/types"
buildkit "github.com/docker/docker/builder/builder-next"
"github.com/docker/docker/builder/dockerfile"
"github.com/docker/docker/builder/fscache"
@ -253,6 +254,7 @@ type routerOptions struct {
buildBackend *buildbackend.Backend
buildCache *fscache.FSCache // legacy
buildkit *buildkit.Builder
builderVersion types.BuilderVersion
daemon *daemon.Daemon
api *apiserver.Server
cluster *cluster.Cluster
@ -283,8 +285,7 @@ func newRouterOptions(config *config.Config, daemon *daemon.Daemon) (routerOptio
if err != nil {
return opts, err
}
buildkit, err := buildkit.New(buildkit.Opt{
bk, err := buildkit.New(buildkit.Opt{
SessionManager: sm,
Root: filepath.Join(config.Root, "buildkit"),
Dist: daemon.DistributionServices(),
@ -293,16 +294,24 @@ func newRouterOptions(config *config.Config, daemon *daemon.Daemon) (routerOptio
return opts, err
}
bb, err := buildbackend.NewBackend(daemon.ImageService(), manager, buildCache, buildkit)
bb, err := buildbackend.NewBackend(daemon.ImageService(), manager, buildCache, bk)
if err != nil {
return opts, errors.Wrap(err, "failed to create buildmanager")
}
var bv types.BuilderVersion
if v, ok := config.Features["buildkit"]; ok {
if v {
bv = types.BuilderBuildKit
} else {
bv = types.BuilderV1
}
}
return routerOptions{
sessionManager: sm,
buildBackend: bb,
buildCache: buildCache,
buildkit: buildkit,
buildkit: bk,
builderVersion: bv,
daemon: daemon,
}, nil
}
@ -476,9 +485,9 @@ func initRouter(opts routerOptions) {
checkpointrouter.NewRouter(opts.daemon, decoder),
container.NewRouter(opts.daemon, decoder),
image.NewRouter(opts.daemon.ImageService()),
systemrouter.NewRouter(opts.daemon, opts.cluster, opts.buildCache, opts.buildkit),
systemrouter.NewRouter(opts.daemon, opts.cluster, opts.buildCache, opts.buildkit, opts.builderVersion),
volume.NewRouter(opts.daemon.VolumesService()),
build.NewRouter(opts.buildBackend, opts.daemon),
build.NewRouter(opts.buildBackend, opts.daemon, opts.builderVersion),
sessionrouter.NewRouter(opts.sessionManager),
swarmrouter.NewRouter(opts.cluster),
pluginrouter.NewRouter(opts.daemon.PluginManager()),

View File

@ -56,6 +56,13 @@ var flatOptions = map[string]bool{
"default-ulimits": true,
}
// skipValidateOptions contains configuration keys
// that will be skipped from findConfigurationConflicts
// for unknown flag validation.
var skipValidateOptions = map[string]bool{
"features": true,
}
// LogConfig represents the default log configuration.
// It includes json tags to deserialize configuration from a file
// using the same names that the flags in the command line use.
@ -203,6 +210,10 @@ type CommonConfig struct {
// should be configured with the CRI plugin enabled. This allows using
// Docker's containerd instance directly with a Kubernetes kubelet.
CriContainerd bool `json:"cri-containerd,omitempty"`
// Features contains a list of feature key value pairs indicating what features are enabled or disabled.
// If a certain feature doesn't appear in this list then it's unset (i.e. neither true nor false).
Features map[string]bool `json:"features,omitempty"`
}
// IsValueSet returns true if a configuration value
@ -444,7 +455,7 @@ func findConfigurationConflicts(config map[string]interface{}, flags *pflag.Flag
// 1. Search keys from the file that we don't recognize as flags.
unknownKeys := make(map[string]interface{})
for key, value := range config {
if flag := flags.Lookup(key); flag == nil {
if flag := flags.Lookup(key); flag == nil && !skipValidateOptions[key] {
unknownKeys[key] = value
}
}