Make experimental a runtime flag

Signed-off-by: Kenfe-Mickael Laventure <mickael.laventure@gmail.com>
This commit is contained in:
Kenfe-Mickael Laventure 2016-10-06 07:09:54 -07:00
parent 0ab13dda66
commit 7781a1bf0f
112 changed files with 782 additions and 979 deletions

View file

@ -0,0 +1,29 @@
package middleware
import (
"net/http"
"golang.org/x/net/context"
)
// ExperimentalMiddleware is a the middleware in charge of adding the
// 'Docker-Experimental' header to every outgoing request
type ExperimentalMiddleware struct {
experimental string
}
// NewExperimentalMiddleware creates a new ExperimentalMiddleware
func NewExperimentalMiddleware(experimentalEnabled bool) ExperimentalMiddleware {
if experimentalEnabled {
return ExperimentalMiddleware{"true"}
}
return ExperimentalMiddleware{"false"}
}
// WrapHandler returns a new handler function wrapping the previous one in the request chain.
func (e ExperimentalMiddleware) WrapHandler(handler func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error) func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
return func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
w.Header().Set("Docker-Experimental", e.experimental)
return handler(ctx, w, r, vars)
}
}

View file

@ -1,5 +1,3 @@
// +build experimental
package checkpoint package checkpoint
import "github.com/docker/docker/api/types" import "github.com/docker/docker/api/types"

View file

@ -26,3 +26,11 @@ func NewRouter(b Backend, decoder httputils.ContainerDecoder) router.Router {
func (r *checkpointRouter) Routes() []router.Route { func (r *checkpointRouter) Routes() []router.Route {
return r.routes return r.routes
} }
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),
}
}

View file

@ -1,15 +0,0 @@
// +build experimental
package checkpoint
import (
"github.com/docker/docker/api/server/router"
)
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),
}
}

View file

@ -1,8 +0,0 @@
// +build !experimental
package checkpoint
func (r *checkpointRouter) initRoutes() {}
// Backend is empty so that the package can compile in non-experimental
type Backend interface{}

View file

@ -1,5 +1,3 @@
// +build experimental
package checkpoint package checkpoint
import ( import (

View file

@ -1,5 +1,3 @@
// +build experimental
package plugin package plugin
import ( import (

View file

@ -21,3 +21,16 @@ func NewRouter(b Backend) router.Router {
func (r *pluginRouter) Routes() []router.Route { func (r *pluginRouter) Routes() []router.Route {
return r.routes return r.routes
} }
func (r *pluginRouter) initRoutes() {
r.routes = []router.Route{
router.NewGetRoute("/plugins", r.listPlugins),
router.NewGetRoute("/plugins/{name:.*}", r.inspectPlugin),
router.NewDeleteRoute("/plugins/{name:.*}", r.removePlugin),
router.NewPostRoute("/plugins/{name:.*}/enable", r.enablePlugin), // PATCH?
router.NewPostRoute("/plugins/{name:.*}/disable", r.disablePlugin),
router.NewPostRoute("/plugins/pull", r.pullPlugin),
router.NewPostRoute("/plugins/{name:.*}/push", r.pushPlugin),
router.NewPostRoute("/plugins/{name:.*}/set", r.setPlugin),
}
}

View file

@ -1,20 +0,0 @@
// +build experimental
package plugin
import (
"github.com/docker/docker/api/server/router"
)
func (r *pluginRouter) initRoutes() {
r.routes = []router.Route{
router.NewGetRoute("/plugins", r.listPlugins),
router.NewGetRoute("/plugins/{name:.*}", r.inspectPlugin),
router.NewDeleteRoute("/plugins/{name:.*}", r.removePlugin),
router.NewPostRoute("/plugins/{name:.*}/enable", r.enablePlugin), // PATCH?
router.NewPostRoute("/plugins/{name:.*}/disable", r.disablePlugin),
router.NewPostRoute("/plugins/pull", r.pullPlugin),
router.NewPostRoute("/plugins/{name:.*}/push", r.pushPlugin),
router.NewPostRoute("/plugins/{name:.*}/set", r.setPlugin),
}
}

View file

@ -1,9 +0,0 @@
// +build !experimental
package plugin
func (r *pluginRouter) initRoutes() {}
// Backend is empty so that the package can compile in non-experimental
// (Needed by volume driver)
type Backend interface{}

View file

@ -1,5 +1,3 @@
// +build experimental
package plugin package plugin
import ( import (

View file

@ -1,5 +1,3 @@
// +build experimental
package bundlefile package bundlefile
import ( import (

View file

@ -1,5 +1,3 @@
// +build experimental
package bundlefile package bundlefile
import ( import (

View file

@ -1,13 +1,27 @@
// +build !experimental
package checkpoint package checkpoint
import ( import (
"fmt"
"github.com/docker/docker/cli"
"github.com/docker/docker/cli/command" "github.com/docker/docker/cli/command"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
// NewCheckpointCommand returns the `checkpoint` subcommand (only in experimental) // NewCheckpointCommand returns the `checkpoint` subcommand (only in experimental)
func NewCheckpointCommand(dockerCli *command.DockerCli) *cobra.Command { func NewCheckpointCommand(dockerCli *command.DockerCli) *cobra.Command {
return &cobra.Command{} cmd := &cobra.Command{
Use: "checkpoint",
Short: "Manage checkpoints",
Args: cli.NoArgs,
Run: func(cmd *cobra.Command, args []string) {
fmt.Fprintf(dockerCli.Err(), "\n"+cmd.UsageString())
},
}
cmd.AddCommand(
newCreateCommand(dockerCli),
newListCommand(dockerCli),
newRemoveCommand(dockerCli),
)
return cmd
} }

View file

@ -1,30 +0,0 @@
// +build experimental
package checkpoint
import (
"fmt"
"github.com/spf13/cobra"
"github.com/docker/docker/cli"
"github.com/docker/docker/cli/command"
)
// NewCheckpointCommand returns the `checkpoint` subcommand (only in experimental)
func NewCheckpointCommand(dockerCli *command.DockerCli) *cobra.Command {
cmd := &cobra.Command{
Use: "checkpoint",
Short: "Manage checkpoints",
Args: cli.NoArgs,
Run: func(cmd *cobra.Command, args []string) {
fmt.Fprintf(dockerCli.Err(), "\n"+cmd.UsageString())
},
}
cmd.AddCommand(
newCreateCommand(dockerCli),
newListCommand(dockerCli),
newRemoveCommand(dockerCli),
)
return cmd
}

View file

@ -1,5 +1,3 @@
// +build experimental
package checkpoint package checkpoint
import ( import (

View file

@ -1,5 +1,3 @@
// +build experimental
package checkpoint package checkpoint
import ( import (

View file

@ -1,5 +1,3 @@
// +build experimental
package checkpoint package checkpoint
import ( import (

View file

@ -19,6 +19,7 @@ import (
dopts "github.com/docker/docker/opts" dopts "github.com/docker/docker/opts"
"github.com/docker/go-connections/sockets" "github.com/docker/go-connections/sockets"
"github.com/docker/go-connections/tlsconfig" "github.com/docker/go-connections/tlsconfig"
"golang.org/x/net/context"
) )
// Streams is an interface which exposes the standard input and output streams // Streams is an interface which exposes the standard input and output streams
@ -31,12 +32,27 @@ type Streams interface {
// DockerCli represents the docker command line client. // DockerCli represents the docker command line client.
// Instances of the client can be returned from NewDockerCli. // Instances of the client can be returned from NewDockerCli.
type DockerCli struct { type DockerCli struct {
configFile *configfile.ConfigFile configFile *configfile.ConfigFile
in *InStream in *InStream
out *OutStream out *OutStream
err io.Writer err io.Writer
keyFile string keyFile string
client client.APIClient client client.APIClient
hasExperimental *bool
}
// HasExperimental returns true if experimental features are accessible
func (cli *DockerCli) HasExperimental() bool {
if cli.hasExperimental == nil {
if cli.client == nil {
cli.Initialize(cliflags.NewClientOptions())
}
enabled := false
cli.hasExperimental = &enabled
enabled, _ = cli.client.Ping(context.Background())
}
return *cli.hasExperimental
} }
// Client returns the APIClient // Client returns the APIClient

View file

@ -24,8 +24,6 @@ func AddCommands(cmd *cobra.Command, dockerCli *command.DockerCli) {
cmd.AddCommand( cmd.AddCommand(
node.NewNodeCommand(dockerCli), node.NewNodeCommand(dockerCli),
service.NewServiceCommand(dockerCli), service.NewServiceCommand(dockerCli),
stack.NewStackCommand(dockerCli),
stack.NewTopLevelDeployCommand(dockerCli),
swarm.NewSwarmCommand(dockerCli), swarm.NewSwarmCommand(dockerCli),
container.NewContainerCommand(dockerCli), container.NewContainerCommand(dockerCli),
image.NewImageCommand(dockerCli), image.NewImageCommand(dockerCli),
@ -72,9 +70,17 @@ func AddCommands(cmd *cobra.Command, dockerCli *command.DockerCli) {
hide(image.NewSaveCommand(dockerCli)), hide(image.NewSaveCommand(dockerCli)),
hide(image.NewTagCommand(dockerCli)), hide(image.NewTagCommand(dockerCli)),
hide(system.NewInspectCommand(dockerCli)), hide(system.NewInspectCommand(dockerCli)),
checkpoint.NewCheckpointCommand(dockerCli),
plugin.NewPluginCommand(dockerCli),
) )
if dockerCli.HasExperimental() {
cmd.AddCommand(
stack.NewStackCommand(dockerCli),
stack.NewTopLevelDeployCommand(dockerCli),
checkpoint.NewCheckpointCommand(dockerCli),
plugin.NewPluginCommand(dockerCli),
)
}
} }
func hide(cmd *cobra.Command) *cobra.Command { func hide(cmd *cobra.Command) *cobra.Command {

View file

@ -44,7 +44,9 @@ func NewStartCommand(dockerCli *command.DockerCli) *cobra.Command {
flags.BoolVarP(&opts.openStdin, "interactive", "i", false, "Attach container's STDIN") flags.BoolVarP(&opts.openStdin, "interactive", "i", false, "Attach container's STDIN")
flags.StringVar(&opts.detachKeys, "detach-keys", "", "Override the key sequence for detaching a container") flags.StringVar(&opts.detachKeys, "detach-keys", "", "Override the key sequence for detaching a container")
addExperimentalStartFlags(flags, &opts) if dockerCli.HasExperimental() {
flags.StringVar(&opts.checkpoint, "checkpoint", "", "Restore from this checkpoint")
}
return cmd return cmd
} }

View file

@ -1,8 +0,0 @@
// +build !experimental
package container
import "github.com/spf13/pflag"
func addExperimentalStartFlags(flags *pflag.FlagSet, opts *startOptions) {
}

View file

@ -1,9 +0,0 @@
// +build experimental
package container
import "github.com/spf13/pflag"
func addExperimentalStartFlags(flags *pflag.FlagSet, opts *startOptions) {
flags.StringVar(&opts.checkpoint, "checkpoint", "", "Restore from this checkpoint")
}

View file

@ -1,13 +1,33 @@
// +build !experimental
package plugin package plugin
import ( import (
"fmt"
"github.com/docker/docker/cli"
"github.com/docker/docker/cli/command" "github.com/docker/docker/cli/command"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
// NewPluginCommand returns a cobra command for `plugin` subcommands // NewPluginCommand returns a cobra command for `plugin` subcommands
func NewPluginCommand(dockerCli *command.DockerCli) *cobra.Command { func NewPluginCommand(dockerCli *command.DockerCli) *cobra.Command {
return &cobra.Command{} cmd := &cobra.Command{
Use: "plugin",
Short: "Manage plugins",
Args: cli.NoArgs,
Run: func(cmd *cobra.Command, args []string) {
fmt.Fprintf(dockerCli.Err(), "\n"+cmd.UsageString())
},
}
cmd.AddCommand(
newDisableCommand(dockerCli),
newEnableCommand(dockerCli),
newInspectCommand(dockerCli),
newInstallCommand(dockerCli),
newListCommand(dockerCli),
newRemoveCommand(dockerCli),
newSetCommand(dockerCli),
newPushCommand(dockerCli),
)
return cmd
} }

View file

@ -1,35 +0,0 @@
// +build experimental
package plugin
import (
"fmt"
"github.com/docker/docker/cli"
"github.com/docker/docker/cli/command"
"github.com/spf13/cobra"
)
// NewPluginCommand returns a cobra command for `plugin` subcommands
func NewPluginCommand(dockerCli *command.DockerCli) *cobra.Command {
cmd := &cobra.Command{
Use: "plugin",
Short: "Manage plugins",
Args: cli.NoArgs,
Run: func(cmd *cobra.Command, args []string) {
fmt.Fprintf(dockerCli.Err(), "\n"+cmd.UsageString())
},
}
cmd.AddCommand(
newDisableCommand(dockerCli),
newEnableCommand(dockerCli),
newInspectCommand(dockerCli),
newInstallCommand(dockerCli),
newListCommand(dockerCli),
newRemoveCommand(dockerCli),
newSetCommand(dockerCli),
newPushCommand(dockerCli),
)
return cmd
}

View file

@ -1,5 +1,3 @@
// +build experimental
package plugin package plugin
import ( import (

View file

@ -1,5 +1,3 @@
// +build experimental
package plugin package plugin
import ( import (

View file

@ -1,5 +1,3 @@
// +build experimental
package plugin package plugin
import ( import (

View file

@ -1,5 +1,3 @@
// +build experimental
package plugin package plugin
import ( import (

View file

@ -1,5 +1,3 @@
// +build experimental
package plugin package plugin
import ( import (

View file

@ -1,5 +1,3 @@
// +build experimental
package plugin package plugin
import ( import (

View file

@ -1,5 +1,3 @@
// +build experimental
package plugin package plugin
import ( import (

View file

@ -1,5 +1,3 @@
// +build experimental
package plugin package plugin
import ( import (

View file

@ -1,18 +1,38 @@
// +build !experimental
package stack package stack
import ( import (
"fmt"
"github.com/docker/docker/cli"
"github.com/docker/docker/cli/command" "github.com/docker/docker/cli/command"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
// NewStackCommand returns no command // NewStackCommand returns a cobra command for `stack` subcommands
func NewStackCommand(dockerCli *command.DockerCli) *cobra.Command { func NewStackCommand(dockerCli *command.DockerCli) *cobra.Command {
return &cobra.Command{} cmd := &cobra.Command{
Use: "stack",
Short: "Manage Docker stacks",
Args: cli.NoArgs,
Run: func(cmd *cobra.Command, args []string) {
fmt.Fprintf(dockerCli.Err(), "\n"+cmd.UsageString())
},
}
cmd.AddCommand(
newConfigCommand(dockerCli),
newDeployCommand(dockerCli),
newListCommand(dockerCli),
newRemoveCommand(dockerCli),
newServicesCommand(dockerCli),
newPsCommand(dockerCli),
)
return cmd
} }
// NewTopLevelDeployCommand returns no command // NewTopLevelDeployCommand returns a command for `docker deploy`
func NewTopLevelDeployCommand(dockerCli *command.DockerCli) *cobra.Command { func NewTopLevelDeployCommand(dockerCli *command.DockerCli) *cobra.Command {
return &cobra.Command{} cmd := newDeployCommand(dockerCli)
// Remove the aliases at the top level
cmd.Aliases = []string{}
return cmd
} }

View file

@ -1,40 +0,0 @@
// +build experimental
package stack
import (
"fmt"
"github.com/docker/docker/cli"
"github.com/docker/docker/cli/command"
"github.com/spf13/cobra"
)
// NewStackCommand returns a cobra command for `stack` subcommands
func NewStackCommand(dockerCli *command.DockerCli) *cobra.Command {
cmd := &cobra.Command{
Use: "stack",
Short: "Manage Docker stacks",
Args: cli.NoArgs,
Run: func(cmd *cobra.Command, args []string) {
fmt.Fprintf(dockerCli.Err(), "\n"+cmd.UsageString())
},
}
cmd.AddCommand(
newConfigCommand(dockerCli),
newDeployCommand(dockerCli),
newListCommand(dockerCli),
newRemoveCommand(dockerCli),
newServicesCommand(dockerCli),
newPsCommand(dockerCli),
)
return cmd
}
// NewTopLevelDeployCommand returns a command for `docker deploy`
func NewTopLevelDeployCommand(dockerCli *command.DockerCli) *cobra.Command {
cmd := newDeployCommand(dockerCli)
// Remove the aliases at the top level
cmd.Aliases = []string{}
return cmd
}

View file

@ -1,5 +1,3 @@
// +build experimental
package stack package stack
import ( import (

View file

@ -1,5 +1,3 @@
// +build experimental
package stack package stack
import ( import (

View file

@ -1,5 +1,3 @@
// +build experimental
package stack package stack
import ( import (

View file

@ -1,5 +1,3 @@
// +build experimental
package stack package stack
import ( import (

View file

@ -1,5 +1,3 @@
// +build experimental
package stack package stack
import ( import (

View file

@ -1,5 +1,3 @@
// +build experimental
package stack package stack
import ( import (

View file

@ -1,5 +1,3 @@
// +build experimental
package stack package stack
import ( import (

View file

@ -1,5 +1,3 @@
// +build experimental
package stack package stack
import ( import (

View file

@ -225,7 +225,7 @@ func prettyPrintInfo(dockerCli *command.DockerCli, info types.Info) error {
} }
} }
ioutils.FprintfIfTrue(dockerCli.Out(), "Experimental: %v\n", info.ExperimentalBuild) fmt.Fprintf(dockerCli.Out(), "Experimental: %v\n", info.ExperimentalBuild)
if info.ClusterStore != "" { if info.ClusterStore != "" {
fmt.Fprintf(dockerCli.Out(), "Cluster Store: %s\n", info.ClusterStore) fmt.Fprintf(dockerCli.Out(), "Cluster Store: %s\n", info.ClusterStore)
} }

View file

@ -10,7 +10,6 @@ import (
"github.com/docker/docker/cli" "github.com/docker/docker/cli"
"github.com/docker/docker/cli/command" "github.com/docker/docker/cli/command"
"github.com/docker/docker/dockerversion" "github.com/docker/docker/dockerversion"
"github.com/docker/docker/utils"
"github.com/docker/docker/utils/templates" "github.com/docker/docker/utils/templates"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@ -21,8 +20,7 @@ var versionTemplate = `Client:
Go version: {{.Client.GoVersion}} Go version: {{.Client.GoVersion}}
Git commit: {{.Client.GitCommit}} Git commit: {{.Client.GitCommit}}
Built: {{.Client.BuildTime}} Built: {{.Client.BuildTime}}
OS/Arch: {{.Client.Os}}/{{.Client.Arch}}{{if .Client.Experimental}} OS/Arch: {{.Client.Os}}/{{.Client.Arch}}{{if .ServerOK}}
Experimental: {{.Client.Experimental}}{{end}}{{if .ServerOK}}
Server: Server:
Version: {{.Server.Version}} Version: {{.Server.Version}}
@ -30,8 +28,8 @@ Server:
Go version: {{.Server.GoVersion}} Go version: {{.Server.GoVersion}}
Git commit: {{.Server.GitCommit}} Git commit: {{.Server.GitCommit}}
Built: {{.Server.BuildTime}} Built: {{.Server.BuildTime}}
OS/Arch: {{.Server.Os}}/{{.Server.Arch}}{{if .Server.Experimental}} OS/Arch: {{.Server.Os}}/{{.Server.Arch}}
Experimental: {{.Server.Experimental}}{{end}}{{end}}` Experimental: {{.Server.Experimental}}{{end}}`
type versionOptions struct { type versionOptions struct {
format string format string
@ -73,14 +71,13 @@ func runVersion(dockerCli *command.DockerCli, opts *versionOptions) error {
vd := types.VersionResponse{ vd := types.VersionResponse{
Client: &types.Version{ Client: &types.Version{
Version: dockerversion.Version, Version: dockerversion.Version,
APIVersion: dockerCli.Client().ClientVersion(), APIVersion: dockerCli.Client().ClientVersion(),
GoVersion: runtime.Version(), GoVersion: runtime.Version(),
GitCommit: dockerversion.GitCommit, GitCommit: dockerversion.GitCommit,
BuildTime: dockerversion.BuildTime, BuildTime: dockerversion.BuildTime,
Os: runtime.GOOS, Os: runtime.GOOS,
Arch: runtime.GOARCH, Arch: runtime.GOARCH,
Experimental: utils.ExperimentalBuild(),
}, },
} }

View file

@ -127,6 +127,7 @@ type SystemAPIClient interface {
Info(ctx context.Context) (types.Info, error) Info(ctx context.Context) (types.Info, error)
RegistryLogin(ctx context.Context, auth types.AuthConfig) (types.AuthResponse, error) RegistryLogin(ctx context.Context, auth types.AuthConfig) (types.AuthResponse, error)
DiskUsage(ctx context.Context) (types.DiskUsage, error) DiskUsage(ctx context.Context) (types.DiskUsage, error)
Ping(ctx context.Context) (bool, error)
} }
// VolumeAPIClient defines API client methods for the volumes // VolumeAPIClient defines API client methods for the volumes

View file

@ -1,5 +1,3 @@
// +build experimental
package client package client
import ( import (
@ -7,9 +5,7 @@ import (
"golang.org/x/net/context" "golang.org/x/net/context"
) )
// APIClient is an interface that clients that talk with a docker server must implement. type apiClientExperimental interface {
type APIClient interface {
CommonAPIClient
CheckpointAPIClient CheckpointAPIClient
PluginAPIClient PluginAPIClient
} }
@ -32,6 +28,3 @@ type PluginAPIClient interface {
PluginSet(ctx context.Context, name string, args []string) error PluginSet(ctx context.Context, name string, args []string) error
PluginInspectWithRaw(ctx context.Context, name string) (*types.Plugin, []byte, error) PluginInspectWithRaw(ctx context.Context, name string) (*types.Plugin, []byte, error)
} }
// Ensure that Client always implements APIClient.
var _ APIClient = &Client{}

View file

@ -1,10 +1,9 @@
// +build !experimental
package client package client
// APIClient is an interface that clients that talk with a docker server must implement. // APIClient is an interface that clients that talk with a docker server must implement.
type APIClient interface { type APIClient interface {
CommonAPIClient CommonAPIClient
apiClientExperimental
} }
// Ensure that Client always implements APIClient. // Ensure that Client always implements APIClient.

19
client/ping.go Normal file
View file

@ -0,0 +1,19 @@
package client
import "golang.org/x/net/context"
// Ping pings the server and return the value of the "Docker-Experimental" header
func (cli *Client) Ping(ctx context.Context) (bool, error) {
serverResp, err := cli.get(ctx, "/_ping", nil, nil)
if err != nil {
return false, err
}
defer ensureReaderClosed(serverResp)
exp := serverResp.header.Get("Docker-Experimental")
if exp != "true" {
return false, nil
}
return true, nil
}

View file

@ -1,5 +1,3 @@
// +build experimental
package client package client
import ( import (

View file

@ -1,5 +1,3 @@
// +build experimental
package client package client
import ( import (

View file

@ -1,5 +1,3 @@
// +build experimental
package client package client
import ( import (

View file

@ -1,5 +1,3 @@
// +build experimental
package client package client
import ( import (

View file

@ -1,5 +1,3 @@
// +build experimental
package client package client
import ( import (

View file

@ -1,5 +1,3 @@
// +build experimental
package client package client
import ( import (

View file

@ -1,5 +1,3 @@
// +build experimental
package client package client
import ( import (

View file

@ -1,5 +1,3 @@
// +build experimental
package client package client
import ( import (

View file

@ -1,5 +1,3 @@
// +build experimental
package client package client
import ( import (

View file

@ -1,5 +1,3 @@
// +build experimental
package client package client
import ( import (

View file

@ -1,5 +1,3 @@
// +build experimental
package client package client
import ( import (

View file

@ -1,5 +1,3 @@
// +build experimental
package client package client
import ( import (

View file

@ -1,5 +1,3 @@
// +build experimental
package client package client
import ( import (

View file

@ -1,5 +1,3 @@
// +build experimental
package client package client
import ( import (

View file

@ -1,5 +1,3 @@
// +build experimental
package client package client
import ( import (

View file

@ -91,11 +91,7 @@ func main() {
} }
func showVersion() { func showVersion() {
if utils.ExperimentalBuild() { fmt.Printf("Docker version %s, build %s\n", dockerversion.Version, dockerversion.GitCommit)
fmt.Printf("Docker version %s, build %s, experimental\n", dockerversion.Version, dockerversion.GitCommit)
} else {
fmt.Printf("Docker version %s, build %s\n", dockerversion.Version, dockerversion.GitCommit)
}
} }
func dockerPreRun(opts *cliflags.ClientOptions) { func dockerPreRun(opts *cliflags.ClientOptions) {

View file

@ -129,7 +129,7 @@ func (cli *DaemonCli) start(opts daemonOptions) (err error) {
utils.EnableDebug() utils.EnableDebug()
} }
if utils.ExperimentalBuild() { if cli.Config.Experimental {
logrus.Warn("Running experimental build") logrus.Warn("Running experimental build")
} }
@ -435,6 +435,9 @@ func initRouter(s *apiserver.Server, d *daemon.Daemon, c *cluster.Cluster) {
func (cli *DaemonCli) initMiddlewares(s *apiserver.Server, cfg *apiserver.Config) { func (cli *DaemonCli) initMiddlewares(s *apiserver.Server, cfg *apiserver.Config) {
v := cfg.Version v := cfg.Version
exp := middleware.NewExperimentalMiddleware(cli.d.HasExperimental())
s.UseMiddleware(exp)
vm := middleware.NewVersionMiddleware(v, api.DefaultVersion, api.MinVersion) vm := middleware.NewVersionMiddleware(v, api.DefaultVersion, api.MinVersion)
s.UseMiddleware(vm) s.UseMiddleware(vm)

View file

@ -13,7 +13,6 @@ import (
"github.com/docker/docker/dockerversion" "github.com/docker/docker/dockerversion"
"github.com/docker/docker/pkg/reexec" "github.com/docker/docker/pkg/reexec"
"github.com/docker/docker/pkg/term" "github.com/docker/docker/pkg/term"
"github.com/docker/docker/utils"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/pflag" "github.com/spf13/pflag"
) )
@ -85,11 +84,7 @@ func runDaemon(opts daemonOptions) error {
} }
func showVersion() { func showVersion() {
if utils.ExperimentalBuild() { fmt.Printf("Docker version %s, build %s\n", dockerversion.Version, dockerversion.GitCommit)
fmt.Printf("Docker version %s, build %s, experimental\n", dockerversion.Version, dockerversion.GitCommit)
} else {
fmt.Printf("Docker version %s, build %s\n", dockerversion.Version, dockerversion.GitCommit)
}
} }
func main() { func main() {

View file

@ -1,13 +0,0 @@
// +build !experimental
package main
import (
"github.com/docker/docker/api/server/httputils"
"github.com/docker/docker/api/server/router"
"github.com/docker/docker/daemon"
)
func addExperimentalRouters(routers []router.Router, d *daemon.Daemon, decoder httputils.ContainerDecoder) []router.Router {
return routers
}

View file

@ -1,5 +1,3 @@
// +build experimental
package main package main
import ( import (
@ -12,5 +10,8 @@ import (
) )
func addExperimentalRouters(routers []router.Router, d *daemon.Daemon, decoder httputils.ContainerDecoder) []router.Router { 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), pluginrouter.NewRouter(plugin.GetManager())) return append(routers, checkpointrouter.NewRouter(d, decoder), pluginrouter.NewRouter(plugin.GetManager()))
} }

View file

@ -153,6 +153,8 @@ type CommonConfig struct {
reloadLock sync.Mutex reloadLock sync.Mutex
valuesSet map[string]interface{} valuesSet map[string]interface{}
Experimental bool `json:"experimental"` // Experimental indicates whether experimental features should be exposed or not
} }
// InstallCommonFlags adds flags to the pflag.FlagSet to configure the daemon // InstallCommonFlags adds flags to the pflag.FlagSet to configure the daemon
@ -187,6 +189,7 @@ func (config *Config) InstallCommonFlags(flags *pflag.FlagSet) {
flags.IntVar(&config.ShutdownTimeout, "shutdown-timeout", defaultShutdownTimeout, "Set the default shutdown timeout") flags.IntVar(&config.ShutdownTimeout, "shutdown-timeout", defaultShutdownTimeout, "Set the default shutdown timeout")
flags.StringVar(&config.SwarmDefaultAdvertiseAddr, "swarm-default-advertise-addr", "", "Set default address or interface for swarm advertised address") flags.StringVar(&config.SwarmDefaultAdvertiseAddr, "swarm-default-advertise-addr", "", "Set default address or interface for swarm advertised address")
flags.BoolVar(&config.Experimental, "experimental", false, "Enable experimental features")
config.MaxConcurrentDownloads = &maxConcurrentDownloads config.MaxConcurrentDownloads = &maxConcurrentDownloads
config.MaxConcurrentUploads = &maxConcurrentUploads config.MaxConcurrentUploads = &maxConcurrentUploads

View file

@ -1,5 +1,3 @@
// +build experimental
package daemon package daemon
import ( import (

View file

@ -1,10 +0,0 @@
// +build !experimental
package daemon
import (
"github.com/spf13/pflag"
)
func (config *Config) attachExperimentalFlags(cmd *pflag.FlagSet) {
}

View file

@ -104,6 +104,14 @@ type Daemon struct {
clusterProvider cluster.Provider clusterProvider cluster.Provider
} }
// HasExperimental returns whether the experimental features of the daemon are enabled or not
func (daemon *Daemon) HasExperimental() bool {
if daemon.configStore != nil && daemon.configStore.Experimental {
return true
}
return false
}
func (daemon *Daemon) restore() error { func (daemon *Daemon) restore() error {
var ( var (
currentDriver = daemon.GraphDriverName() currentDriver = daemon.GraphDriverName()
@ -667,7 +675,7 @@ func NewDaemon(config *Config, registryService registry.Service, containerdRemot
} }
// Plugin system initialization should happen before restore. Do not change order. // Plugin system initialization should happen before restore. Do not change order.
if err := pluginInit(d, config, containerdRemote); err != nil { if err := d.pluginInit(config, containerdRemote); err != nil {
return nil, err return nil, err
} }
@ -775,7 +783,7 @@ func (daemon *Daemon) Shutdown() error {
} }
// Shutdown plugins after containers. Dont change the order. // Shutdown plugins after containers. Dont change the order.
pluginShutdown() daemon.pluginShutdown()
// trigger libnetwork Stop only if it's initialized // trigger libnetwork Stop only if it's initialized
if daemon.netController != nil { if daemon.netController != nil {
@ -1022,7 +1030,6 @@ func (daemon *Daemon) Reload(config *Config) (err error) {
if err := daemon.containerdRemote.UpdateOptions(libcontainerd.WithLiveRestore(config.LiveRestoreEnabled)); err != nil { if err := daemon.containerdRemote.UpdateOptions(libcontainerd.WithLiveRestore(config.LiveRestoreEnabled)); err != nil {
return err return err
} }
} }
// If no value is set for max-concurrent-downloads we assume it is the default value // If no value is set for max-concurrent-downloads we assume it is the default value

View file

@ -1,5 +1,3 @@
// +build experimental
package daemon package daemon
import ( import (
@ -12,11 +10,17 @@ func (daemon *Daemon) verifyExperimentalContainerSettings(hostConfig *container.
return nil, nil return nil, nil
} }
func pluginInit(d *Daemon, cfg *Config, remote libcontainerd.Remote) error { func (daemon *Daemon) pluginInit(cfg *Config, remote libcontainerd.Remote) error {
return plugin.Init(cfg.Root, d.PluginStore, remote, d.RegistryService, cfg.LiveRestoreEnabled, d.LogPluginEvent) if !daemon.HasExperimental() {
return nil
}
return plugin.Init(cfg.Root, daemon.PluginStore, remote, daemon.RegistryService, cfg.LiveRestoreEnabled, daemon.LogPluginEvent)
} }
func pluginShutdown() { func (daemon *Daemon) pluginShutdown() {
if !daemon.HasExperimental() {
return
}
manager := plugin.GetManager() manager := plugin.GetManager()
// Check for a valid manager object. In error conditions, daemon init can fail // Check for a valid manager object. In error conditions, daemon init can fail
// and shutdown called, before plugin manager is initialized. // and shutdown called, before plugin manager is initialized.

View file

@ -1,19 +0,0 @@
// +build !experimental
package daemon
import (
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/libcontainerd"
)
func (daemon *Daemon) verifyExperimentalContainerSettings(hostConfig *container.HostConfig, config *container.Config) ([]string, error) {
return nil, nil
}
func pluginInit(d *Daemon, config *Config, remote libcontainerd.Remote) error {
return nil
}
func pluginShutdown() {
}

View file

@ -1,5 +1,3 @@
// +build experimental
package graphdriver package graphdriver
import ( import (

View file

@ -1,9 +0,0 @@
// +build !experimental
package graphdriver
import "github.com/docker/docker/pkg/plugingetter"
func lookupPlugin(name, home string, opts []string, pg plugingetter.PluginGetter) (Driver, error) {
return nil, ErrNotSupported
}

View file

@ -1,5 +1,3 @@
// +build experimental
package graphdriver package graphdriver
import ( import (

View file

@ -109,7 +109,7 @@ func (daemon *Daemon) SystemInfo() (*types.Info, error) {
MemTotal: meminfo.MemTotal, MemTotal: meminfo.MemTotal,
DockerRootDir: daemon.configStore.Root, DockerRootDir: daemon.configStore.Root,
Labels: daemon.configStore.Labels, Labels: daemon.configStore.Labels,
ExperimentalBuild: utils.ExperimentalBuild(), ExperimentalBuild: daemon.configStore.Experimental,
ServerVersion: dockerversion.Version, ServerVersion: dockerversion.Version,
ClusterStore: daemon.configStore.ClusterStore, ClusterStore: daemon.configStore.ClusterStore,
ClusterAdvertise: daemon.configStore.ClusterAdvertise, ClusterAdvertise: daemon.configStore.ClusterAdvertise,
@ -158,7 +158,7 @@ func (daemon *Daemon) SystemVersion() types.Version {
Os: runtime.GOOS, Os: runtime.GOOS,
Arch: runtime.GOARCH, Arch: runtime.GOARCH,
BuildTime: dockerversion.BuildTime, BuildTime: dockerversion.BuildTime,
Experimental: utils.ExperimentalBuild(), Experimental: daemon.configStore.Experimental,
} }
kernelVersion := "<unknown>" kernelVersion := "<unknown>"

View file

@ -157,7 +157,7 @@ This section lists each version from latest to oldest. Each listing includes a
* `POST /containers/prune` prunes stopped containers. * `POST /containers/prune` prunes stopped containers.
* `POST /images/prune` prunes unused images. * `POST /images/prune` prunes unused images.
* `POST /volumes/prune` prunes unused volumes. * `POST /volumes/prune` prunes unused volumes.
* Every API response now includes a `Docker-Experimental` header specifying if experimental features are enabled (value can be `true` or `false`).
### v1.24 API changes ### v1.24 API changes

View file

@ -45,6 +45,7 @@ Options:
--dns-search value DNS search domains to use (default []) --dns-search value DNS search domains to use (default [])
--exec-opt value Runtime execution options (default []) --exec-opt value Runtime execution options (default [])
--exec-root string Root directory for execution state files (default "/var/run/docker") --exec-root string Root directory for execution state files (default "/var/run/docker")
--experimental Enable experimental features
--fixed-cidr string IPv4 subnet for fixed IPs --fixed-cidr string IPv4 subnet for fixed IPs
--fixed-cidr-v6 string IPv6 subnet for fixed IPs --fixed-cidr-v6 string IPv6 subnet for fixed IPs
-g, --graph string Root of the Docker runtime (default "/var/lib/docker") -g, --graph string Root of the Docker runtime (default "/var/lib/docker")
@ -1114,6 +1115,7 @@ This is a full example of the allowed configuration options on Linux:
"dns-search": [], "dns-search": [],
"exec-opts": [], "exec-opts": [],
"exec-root": "", "exec-root": "",
"experimental": false,
"storage-driver": "", "storage-driver": "",
"storage-opts": [], "storage-opts": [],
"labels": [], "labels": [],
@ -1195,6 +1197,7 @@ This is a full example of the allowed configuration options on Windows:
"dns-opts": [], "dns-opts": [],
"dns-search": [], "dns-search": [],
"exec-opts": [], "exec-opts": [],
"experimental": false,
"storage-driver": "", "storage-driver": "",
"storage-opts": [], "storage-opts": [],
"labels": [], "labels": [],

View file

@ -126,12 +126,6 @@ if [ ! "$GOPATH" ]; then
exit 1 exit 1
fi fi
if [ "$DOCKER_EXPERIMENTAL" ]; then
echo >&2 '# WARNING! DOCKER_EXPERIMENTAL is set: building experimental features'
echo >&2
DOCKER_BUILDTAGS+=" experimental"
fi
DOCKER_BUILDTAGS+=" daemon" DOCKER_BUILDTAGS+=" daemon"
if ${PKG_CONFIG} 'libsystemd >= 209' 2> /dev/null ; then if ${PKG_CONFIG} 'libsystemd >= 209' 2> /dev/null ; then
DOCKER_BUILDTAGS+=" journald" DOCKER_BUILDTAGS+=" journald"

View file

@ -50,6 +50,11 @@ if [ "$DOCKER_REMAP_ROOT" ]; then
extra_params="--userns-remap $DOCKER_REMAP_ROOT" extra_params="--userns-remap $DOCKER_REMAP_ROOT"
fi fi
if [ "$DOCKER_EXPERIMENTAL" ]; then
echo >&2 '# DOCKER_EXPERIMENTAL is set: starting daemon with experimental features enabled! '
extra_params="$extra_params --experimental"
fi
if [ -z "$DOCKER_TEST_HOST" ]; then if [ -z "$DOCKER_TEST_HOST" ]; then
# Start apparmor if it is enabled # Start apparmor if it is enabled
if [ -e "/sys/module/apparmor/parameters/enabled" ] && [ "$(cat /sys/module/apparmor/parameters/enabled)" == "Y" ]; then if [ -e "/sys/module/apparmor/parameters/enabled" ] && [ "$(cat /sys/module/apparmor/parameters/enabled)" == "Y" ]; then

View file

@ -76,10 +76,6 @@ set -e
# Install runc and containerd # Install runc and containerd
RUN ./hack/dockerfile/install-binaries.sh runc-dynamic containerd-dynamic RUN ./hack/dockerfile/install-binaries.sh runc-dynamic containerd-dynamic
EOF EOF
if [ "$DOCKER_EXPERIMENTAL" ]; then
echo 'ENV DOCKER_EXPERIMENTAL 1' >> "$DEST/$version/Dockerfile.build"
fi
cat >> "$DEST/$version/Dockerfile.build" <<-EOF cat >> "$DEST/$version/Dockerfile.build" <<-EOF
RUN cp -aL hack/make/.build-deb debian RUN cp -aL hack/make/.build-deb debian
RUN { echo '$debSource (${debVersion}-0~${suite}) $suite; urgency=low'; echo; echo ' * Version: $VERSION'; echo; echo " -- $debMaintainer $debDate"; } > debian/changelog && cat >&2 debian/changelog RUN { echo '$debSource (${debVersion}-0~${suite}) $suite; urgency=low'; echo; echo ' * Version: $VERSION'; echo; echo " -- $debMaintainer $debDate"; } > debian/changelog && cat >&2 debian/changelog

View file

@ -96,8 +96,7 @@ set -e
# Install runc and containerd # Install runc and containerd
RUN ./hack/dockerfile/install-binaries.sh runc-dynamic containerd-dynamic RUN ./hack/dockerfile/install-binaries.sh runc-dynamic containerd-dynamic
EOF EOF
if [[ "$VERSION" == *-dev ]] || [ -n "$(git status --porcelain)" ]; then
if [ "$DOCKER_EXPERIMENTAL" ]; then
echo 'ENV DOCKER_EXPERIMENTAL 1' >> "$DEST/$version/Dockerfile.build" echo 'ENV DOCKER_EXPERIMENTAL 1' >> "$DEST/$version/Dockerfile.build"
fi fi
cat >> "$DEST/$version/Dockerfile.build" <<-EOF cat >> "$DEST/$version/Dockerfile.build" <<-EOF

View file

@ -39,7 +39,7 @@ if [[ "$VERSION" == *-rc* ]]; then
component="testing" component="testing"
fi fi
if [ "$DOCKER_EXPERIMENTAL" ] || [[ "$VERSION" == *-dev ]] || [ -n "$(git status --porcelain)" ]; then if [[ "$VERSION" == *-dev ]] || [ -n "$(git status --porcelain)" ]; then
component="experimental" component="experimental"
fi fi

View file

@ -25,7 +25,7 @@ if [[ "$VERSION" == *-rc* ]]; then
release="testing" release="testing"
fi fi
if [ $DOCKER_EXPERIMENTAL ] || [[ "$VERSION" == *-dev ]] || [ -n "$(git status --porcelain)" ]; then if [[ "$VERSION" == *-dev ]] || [ -n "$(git status --porcelain)" ]; then
release="experimental" release="experimental"
fi fi

View file

@ -266,7 +266,11 @@ func (s *DockerSwarmSuite) AddDaemon(c *check.C, joinSwarm, manager bool) *Swarm
port: defaultSwarmPort + s.portIndex, port: defaultSwarmPort + s.portIndex,
} }
d.listenAddr = fmt.Sprintf("0.0.0.0:%d", d.port) d.listenAddr = fmt.Sprintf("0.0.0.0:%d", d.port)
err := d.StartWithBusybox("--iptables=false", "--swarm-default-advertise-addr=lo") // avoid networking conflicts args := []string{"--iptables=false", "--swarm-default-advertise-addr=lo"} // avoid networking conflicts
if experimentalDaemon {
args = append(args, "--experimental")
}
err := d.StartWithBusybox(args...)
c.Assert(err, check.IsNil) c.Assert(err, check.IsNil)
if joinSwarm == true { if joinSwarm == true {

View file

@ -153,6 +153,9 @@ func (d *Daemon) StartWithLogFile(out *os.File, providedArgs ...string) error {
"--pidfile", fmt.Sprintf("%s/docker.pid", d.folder), "--pidfile", fmt.Sprintf("%s/docker.pid", d.folder),
fmt.Sprintf("--userland-proxy=%t", d.userlandProxy), fmt.Sprintf("--userland-proxy=%t", d.userlandProxy),
) )
if experimentalDaemon {
args = append(args, "--experimental")
}
if !(d.useDefaultHost || d.useDefaultTLSHost) { if !(d.useDefaultHost || d.useDefaultTLSHost) {
args = append(args, []string{"--host", d.sock()}...) args = append(args, []string{"--host", d.sock()}...)
} }

View file

@ -1,4 +1,4 @@
// +build linux, experimental // +build linux
package main package main
@ -17,7 +17,8 @@ var pluginName = "tiborvass/no-remove"
// TestDaemonRestartWithPluginEnabled tests state restore for an enabled plugin // TestDaemonRestartWithPluginEnabled tests state restore for an enabled plugin
func (s *DockerDaemonSuite) TestDaemonRestartWithPluginEnabled(c *check.C) { func (s *DockerDaemonSuite) TestDaemonRestartWithPluginEnabled(c *check.C) {
testRequires(c, Network) testRequires(c, Network, ExperimentalDaemon)
if err := s.d.Start(); err != nil { if err := s.d.Start(); err != nil {
c.Fatalf("Could not start daemon: %v", err) c.Fatalf("Could not start daemon: %v", err)
} }
@ -49,7 +50,8 @@ func (s *DockerDaemonSuite) TestDaemonRestartWithPluginEnabled(c *check.C) {
// TestDaemonRestartWithPluginDisabled tests state restore for a disabled plugin // TestDaemonRestartWithPluginDisabled tests state restore for a disabled plugin
func (s *DockerDaemonSuite) TestDaemonRestartWithPluginDisabled(c *check.C) { func (s *DockerDaemonSuite) TestDaemonRestartWithPluginDisabled(c *check.C) {
testRequires(c, Network) testRequires(c, Network, ExperimentalDaemon)
if err := s.d.Start(); err != nil { if err := s.d.Start(); err != nil {
c.Fatalf("Could not start daemon: %v", err) c.Fatalf("Could not start daemon: %v", err)
} }
@ -79,7 +81,8 @@ func (s *DockerDaemonSuite) TestDaemonRestartWithPluginDisabled(c *check.C) {
// TestDaemonKillLiveRestoreWithPlugins SIGKILLs daemon started with --live-restore. // TestDaemonKillLiveRestoreWithPlugins SIGKILLs daemon started with --live-restore.
// Plugins should continue to run. // Plugins should continue to run.
func (s *DockerDaemonSuite) TestDaemonKillLiveRestoreWithPlugins(c *check.C) { func (s *DockerDaemonSuite) TestDaemonKillLiveRestoreWithPlugins(c *check.C) {
testRequires(c, Network) testRequires(c, Network, ExperimentalDaemon)
if err := s.d.Start("--live-restore"); err != nil { if err := s.d.Start("--live-restore"); err != nil {
c.Fatalf("Could not start daemon: %v", err) c.Fatalf("Could not start daemon: %v", err)
} }
@ -111,7 +114,8 @@ func (s *DockerDaemonSuite) TestDaemonKillLiveRestoreWithPlugins(c *check.C) {
// TestDaemonShutdownLiveRestoreWithPlugins SIGTERMs daemon started with --live-restore. // TestDaemonShutdownLiveRestoreWithPlugins SIGTERMs daemon started with --live-restore.
// Plugins should continue to run. // Plugins should continue to run.
func (s *DockerDaemonSuite) TestDaemonShutdownLiveRestoreWithPlugins(c *check.C) { func (s *DockerDaemonSuite) TestDaemonShutdownLiveRestoreWithPlugins(c *check.C) {
testRequires(c, Network) testRequires(c, Network, ExperimentalDaemon)
if err := s.d.Start("--live-restore"); err != nil { if err := s.d.Start("--live-restore"); err != nil {
c.Fatalf("Could not start daemon: %v", err) c.Fatalf("Could not start daemon: %v", err)
} }
@ -142,7 +146,8 @@ func (s *DockerDaemonSuite) TestDaemonShutdownLiveRestoreWithPlugins(c *check.C)
// TestDaemonShutdownWithPlugins shuts down running plugins. // TestDaemonShutdownWithPlugins shuts down running plugins.
func (s *DockerDaemonSuite) TestDaemonShutdownWithPlugins(c *check.C) { func (s *DockerDaemonSuite) TestDaemonShutdownWithPlugins(c *check.C) {
testRequires(c, Network) testRequires(c, Network, ExperimentalDaemon)
if err := s.d.Start(); err != nil { if err := s.d.Start(); err != nil {
c.Fatalf("Could not start daemon: %v", err) c.Fatalf("Could not start daemon: %v", err)
} }
@ -180,7 +185,8 @@ func (s *DockerDaemonSuite) TestDaemonShutdownWithPlugins(c *check.C) {
// TestVolumePlugin tests volume creation using a plugin. // TestVolumePlugin tests volume creation using a plugin.
func (s *DockerDaemonSuite) TestVolumePlugin(c *check.C) { func (s *DockerDaemonSuite) TestVolumePlugin(c *check.C) {
testRequires(c, Network) testRequires(c, Network, ExperimentalDaemon)
volName := "plugin-volume" volName := "plugin-volume"
volRoot := "/data" volRoot := "/data"
destDir := "/tmp/data/" destDir := "/tmp/data/"

View file

@ -1,21 +1,36 @@
// +build experimental
package main package main
import ( import (
"strings"
"github.com/docker/docker/pkg/integration/checker" "github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check" "github.com/go-check/check"
"strings"
) )
func (s *DockerSuite) TestExperimentalVersion(c *check.C) { func (s *DockerSuite) TestExperimentalVersionTrue(c *check.C) {
testRequires(c, ExperimentalDaemon)
out, _ := dockerCmd(c, "version") out, _ := dockerCmd(c, "version")
for _, line := range strings.Split(out, "\n") { for _, line := range strings.Split(out, "\n") {
if strings.HasPrefix(line, "Experimental (client):") || strings.HasPrefix(line, "Experimental (server):") { if strings.HasPrefix(strings.TrimSpace(line), "Experimental:") {
c.Assert(line, checker.Matches, "*true") c.Assert(line, checker.Matches, "*true")
return
} }
} }
out, _ = dockerCmd(c, "-v") c.Fatal(`"Experimental" not found in version output`)
c.Assert(out, checker.Contains, ", experimental", check.Commentf("docker version did not contain experimental")) }
func (s *DockerSuite) TestExperimentalVersionFalse(c *check.C) {
testRequires(c, NotExperimentalDaemon)
out, _ := dockerCmd(c, "version")
for _, line := range strings.Split(out, "\n") {
if strings.HasPrefix(strings.TrimSpace(line), "Experimental:") {
c.Assert(line, checker.Matches, "*false")
return
}
}
c.Fatal(`"Experimental" not found in version output`)
} }

View file

@ -1,4 +1,3 @@
// +build experimental
// +build !windows // +build !windows
package main package main
@ -287,7 +286,7 @@ func (s *DockerExternalGraphdriverSuite) setUpPlugin(c *check.C, name string, ex
mux.HandleFunc("/GraphDriver.ApplyDiff", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/GraphDriver.ApplyDiff", func(w http.ResponseWriter, r *http.Request) {
s.ec[ext].applydiff++ s.ec[ext].applydiff++
var diff io.Reader = r.Body diff := r.Body
defer r.Body.Close() defer r.Body.Close()
id := r.URL.Query().Get("id") id := r.URL.Query().Get("id")
@ -338,6 +337,8 @@ func (s *DockerExternalGraphdriverSuite) TearDownSuite(c *check.C) {
} }
func (s *DockerExternalGraphdriverSuite) TestExternalGraphDriver(c *check.C) { func (s *DockerExternalGraphdriverSuite) TestExternalGraphDriver(c *check.C) {
testRequires(c, ExperimentalDaemon)
s.testExternalGraphDriver("test-external-graph-driver", "spec", c) s.testExternalGraphDriver("test-external-graph-driver", "spec", c)
s.testExternalGraphDriver("json-external-graph-driver", "json", c) s.testExternalGraphDriver("json-external-graph-driver", "json", c)
} }
@ -388,7 +389,8 @@ func (s *DockerExternalGraphdriverSuite) testExternalGraphDriver(name string, ex
} }
func (s *DockerExternalGraphdriverSuite) TestExternalGraphDriverPull(c *check.C) { func (s *DockerExternalGraphdriverSuite) TestExternalGraphDriverPull(c *check.C) {
testRequires(c, Network) testRequires(c, Network, ExperimentalDaemon)
c.Assert(s.d.Start(), check.IsNil) c.Assert(s.d.Start(), check.IsNil)
out, err := s.d.Cmd("pull", "busybox:latest") out, err := s.d.Cmd("pull", "busybox:latest")

View file

@ -10,7 +10,6 @@ import (
"github.com/docker/docker/pkg/homedir" "github.com/docker/docker/pkg/homedir"
"github.com/docker/docker/pkg/integration/checker" "github.com/docker/docker/pkg/integration/checker"
icmd "github.com/docker/docker/pkg/integration/cmd" icmd "github.com/docker/docker/pkg/integration/cmd"
"github.com/docker/docker/utils"
"github.com/go-check/check" "github.com/go-check/check"
) )
@ -117,7 +116,7 @@ func (s *DockerSuite) TestHelpTextVerify(c *check.C) {
cmdsToTest = append(cmdsToTest, "network ls") cmdsToTest = append(cmdsToTest, "network ls")
cmdsToTest = append(cmdsToTest, "network rm") cmdsToTest = append(cmdsToTest, "network rm")
if utils.ExperimentalBuild() { if experimentalDaemon {
cmdsToTest = append(cmdsToTest, "checkpoint create") cmdsToTest = append(cmdsToTest, "checkpoint create")
cmdsToTest = append(cmdsToTest, "checkpoint ls") cmdsToTest = append(cmdsToTest, "checkpoint ls")
cmdsToTest = append(cmdsToTest, "checkpoint rm") cmdsToTest = append(cmdsToTest, "checkpoint rm")

View file

@ -7,7 +7,6 @@ import (
"strings" "strings"
"github.com/docker/docker/pkg/integration/checker" "github.com/docker/docker/pkg/integration/checker"
"github.com/docker/docker/utils"
"github.com/go-check/check" "github.com/go-check/check"
) )
@ -44,8 +43,10 @@ func (s *DockerSuite) TestInfoEnsureSucceeds(c *check.C) {
stringsToCheck = append(stringsToCheck, "Runtimes:", "Default Runtime: runc") stringsToCheck = append(stringsToCheck, "Runtimes:", "Default Runtime: runc")
} }
if utils.ExperimentalBuild() { if experimentalDaemon {
stringsToCheck = append(stringsToCheck, "Experimental: true") stringsToCheck = append(stringsToCheck, "Experimental: true")
} else {
stringsToCheck = append(stringsToCheck, "Experimental: false")
} }
for _, linePrefix := range stringsToCheck { for _, linePrefix := range stringsToCheck {

View file

@ -1,5 +1,3 @@
// +build experimental
package main package main
import ( import (
@ -11,6 +9,7 @@ import (
) )
func (s *DockerSwarmSuite) TestStackRemove(c *check.C) { func (s *DockerSwarmSuite) TestStackRemove(c *check.C) {
testRequires(c, ExperimentalDaemon)
d := s.AddDaemon(c, true, true) d := s.AddDaemon(c, true, true)
stackArgs := append([]string{"stack", "remove", "UNKNOWN_STACK"}) stackArgs := append([]string{"stack", "remove", "UNKNOWN_STACK"})
@ -21,6 +20,7 @@ func (s *DockerSwarmSuite) TestStackRemove(c *check.C) {
} }
func (s *DockerSwarmSuite) TestStackTasks(c *check.C) { func (s *DockerSwarmSuite) TestStackTasks(c *check.C) {
testRequires(c, ExperimentalDaemon)
d := s.AddDaemon(c, true, true) d := s.AddDaemon(c, true, true)
stackArgs := append([]string{"stack", "ps", "UNKNOWN_STACK"}) stackArgs := append([]string{"stack", "ps", "UNKNOWN_STACK"})
@ -31,6 +31,7 @@ func (s *DockerSwarmSuite) TestStackTasks(c *check.C) {
} }
func (s *DockerSwarmSuite) TestStackServices(c *check.C) { func (s *DockerSwarmSuite) TestStackServices(c *check.C) {
testRequires(c, ExperimentalDaemon)
d := s.AddDaemon(c, true, true) d := s.AddDaemon(c, true, true)
stackArgs := append([]string{"stack", "services", "UNKNOWN_STACK"}) stackArgs := append([]string{"stack", "services", "UNKNOWN_STACK"})
@ -59,6 +60,7 @@ const testDAB = `{
}` }`
func (s *DockerSwarmSuite) TestStackWithDAB(c *check.C) { func (s *DockerSwarmSuite) TestStackWithDAB(c *check.C) {
testRequires(c, ExperimentalDaemon)
// setup // setup
testStackName := "test" testStackName := "test"
testDABFileName := testStackName + ".dab" testDABFileName := testStackName + ".dab"
@ -92,6 +94,7 @@ func (s *DockerSwarmSuite) TestStackWithDAB(c *check.C) {
} }
func (s *DockerSwarmSuite) TestStackWithDABExtension(c *check.C) { func (s *DockerSwarmSuite) TestStackWithDABExtension(c *check.C) {
testRequires(c, ExperimentalDaemon)
// setup // setup
testStackName := "test.dab" testStackName := "test.dab"
testDABFileName := testStackName testDABFileName := testStackName

View file

@ -1,4 +1,4 @@
// +build experimental // +build !windows
package main package main
@ -50,7 +50,8 @@ var (
func (s *DockerNetworkSuite) TestDockerNetworkMacvlanPersistance(c *check.C) { func (s *DockerNetworkSuite) TestDockerNetworkMacvlanPersistance(c *check.C) {
// verify the driver automatically provisions the 802.1q link (dm-dummy0.60) // verify the driver automatically provisions the 802.1q link (dm-dummy0.60)
testRequires(c, DaemonIsLinux, MacvlanKernelSupport, NotUserNamespace, NotArm) testRequires(c, DaemonIsLinux, MacvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
// master dummy interface 'dm' abbreviation represents 'docker macvlan' // master dummy interface 'dm' abbreviation represents 'docker macvlan'
master := "dm-dummy0" master := "dm-dummy0"
// simulate the master link the vlan tagged subinterface parent link will use // simulate the master link the vlan tagged subinterface parent link will use
@ -69,7 +70,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkMacvlanPersistance(c *check.C) {
func (s *DockerNetworkSuite) TestDockerNetworkIpvlanPersistance(c *check.C) { func (s *DockerNetworkSuite) TestDockerNetworkIpvlanPersistance(c *check.C) {
// verify the driver automatically provisions the 802.1q link (di-dummy0.70) // verify the driver automatically provisions the 802.1q link (di-dummy0.70)
testRequires(c, DaemonIsLinux, IpvlanKernelSupport, NotUserNamespace, NotArm) testRequires(c, DaemonIsLinux, IpvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
// master dummy interface 'di' notation represent 'docker ipvlan' // master dummy interface 'di' notation represent 'docker ipvlan'
master := "di-dummy0" master := "di-dummy0"
// simulate the master link the vlan tagged subinterface parent link will use // simulate the master link the vlan tagged subinterface parent link will use
@ -88,7 +89,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkIpvlanPersistance(c *check.C) {
func (s *DockerNetworkSuite) TestDockerNetworkMacvlanSubIntCreate(c *check.C) { func (s *DockerNetworkSuite) TestDockerNetworkMacvlanSubIntCreate(c *check.C) {
// verify the driver automatically provisions the 802.1q link (dm-dummy0.50) // verify the driver automatically provisions the 802.1q link (dm-dummy0.50)
testRequires(c, DaemonIsLinux, MacvlanKernelSupport, NotUserNamespace, NotArm) testRequires(c, DaemonIsLinux, MacvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
// master dummy interface 'dm' abbreviation represents 'docker macvlan' // master dummy interface 'dm' abbreviation represents 'docker macvlan'
master := "dm-dummy0" master := "dm-dummy0"
// simulate the master link the vlan tagged subinterface parent link will use // simulate the master link the vlan tagged subinterface parent link will use
@ -103,7 +104,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkMacvlanSubIntCreate(c *check.C) {
func (s *DockerNetworkSuite) TestDockerNetworkIpvlanSubIntCreate(c *check.C) { func (s *DockerNetworkSuite) TestDockerNetworkIpvlanSubIntCreate(c *check.C) {
// verify the driver automatically provisions the 802.1q link (di-dummy0.50) // verify the driver automatically provisions the 802.1q link (di-dummy0.50)
testRequires(c, DaemonIsLinux, IpvlanKernelSupport, NotUserNamespace, NotArm) testRequires(c, DaemonIsLinux, IpvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
// master dummy interface 'dm' abbreviation represents 'docker ipvlan' // master dummy interface 'dm' abbreviation represents 'docker ipvlan'
master := "di-dummy0" master := "di-dummy0"
// simulate the master link the vlan tagged subinterface parent link will use // simulate the master link the vlan tagged subinterface parent link will use
@ -118,7 +119,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkIpvlanSubIntCreate(c *check.C) {
func (s *DockerNetworkSuite) TestDockerNetworkMacvlanOverlapParent(c *check.C) { func (s *DockerNetworkSuite) TestDockerNetworkMacvlanOverlapParent(c *check.C) {
// verify the same parent interface cannot be used if already in use by an existing network // verify the same parent interface cannot be used if already in use by an existing network
testRequires(c, DaemonIsLinux, MacvlanKernelSupport, NotUserNamespace, NotArm) testRequires(c, DaemonIsLinux, MacvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
// master dummy interface 'dm' abbreviation represents 'docker macvlan' // master dummy interface 'dm' abbreviation represents 'docker macvlan'
master := "dm-dummy0" master := "dm-dummy0"
out, err := createMasterDummy(c, master) out, err := createMasterDummy(c, master)
@ -138,7 +139,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkMacvlanOverlapParent(c *check.C) {
func (s *DockerNetworkSuite) TestDockerNetworkIpvlanOverlapParent(c *check.C) { func (s *DockerNetworkSuite) TestDockerNetworkIpvlanOverlapParent(c *check.C) {
// verify the same parent interface cannot be used if already in use by an existing network // verify the same parent interface cannot be used if already in use by an existing network
testRequires(c, DaemonIsLinux, IpvlanKernelSupport, NotUserNamespace, NotArm) testRequires(c, DaemonIsLinux, IpvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
// master dummy interface 'dm' abbreviation represents 'docker ipvlan' // master dummy interface 'dm' abbreviation represents 'docker ipvlan'
master := "di-dummy0" master := "di-dummy0"
out, err := createMasterDummy(c, master) out, err := createMasterDummy(c, master)
@ -158,7 +159,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkIpvlanOverlapParent(c *check.C) {
func (s *DockerNetworkSuite) TestDockerNetworkMacvlanMultiSubnet(c *check.C) { func (s *DockerNetworkSuite) TestDockerNetworkMacvlanMultiSubnet(c *check.C) {
// create a dual stack multi-subnet Macvlan bridge mode network and validate connectivity between four containers, two on each subnet // create a dual stack multi-subnet Macvlan bridge mode network and validate connectivity between four containers, two on each subnet
testRequires(c, DaemonIsLinux, IPv6, MacvlanKernelSupport, NotUserNamespace, NotArm) testRequires(c, DaemonIsLinux, IPv6, MacvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
dockerCmd(c, "network", "create", "--driver=macvlan", "--ipv6", "--subnet=172.28.100.0/24", "--subnet=172.28.102.0/24", "--gateway=172.28.102.254", dockerCmd(c, "network", "create", "--driver=macvlan", "--ipv6", "--subnet=172.28.100.0/24", "--subnet=172.28.102.0/24", "--gateway=172.28.102.254",
"--subnet=2001:db8:abc2::/64", "--subnet=2001:db8:abc4::/64", "--gateway=2001:db8:abc4::254", "dualstackbridge") "--subnet=2001:db8:abc2::/64", "--subnet=2001:db8:abc4::/64", "--gateway=2001:db8:abc4::254", "dualstackbridge")
// Ensure the network was created // Ensure the network was created
@ -213,7 +214,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkMacvlanMultiSubnet(c *check.C) {
func (s *DockerNetworkSuite) TestDockerNetworkIpvlanL2MultiSubnet(c *check.C) { func (s *DockerNetworkSuite) TestDockerNetworkIpvlanL2MultiSubnet(c *check.C) {
// create a dual stack multi-subnet Ipvlan L2 network and validate connectivity within the subnets, two on each subnet // create a dual stack multi-subnet Ipvlan L2 network and validate connectivity within the subnets, two on each subnet
testRequires(c, DaemonIsLinux, IPv6, IpvlanKernelSupport, NotUserNamespace, NotArm) testRequires(c, DaemonIsLinux, IPv6, IpvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
dockerCmd(c, "network", "create", "--driver=ipvlan", "--ipv6", "--subnet=172.28.200.0/24", "--subnet=172.28.202.0/24", "--gateway=172.28.202.254", dockerCmd(c, "network", "create", "--driver=ipvlan", "--ipv6", "--subnet=172.28.200.0/24", "--subnet=172.28.202.0/24", "--gateway=172.28.202.254",
"--subnet=2001:db8:abc8::/64", "--subnet=2001:db8:abc6::/64", "--gateway=2001:db8:abc6::254", "dualstackl2") "--subnet=2001:db8:abc8::/64", "--subnet=2001:db8:abc6::/64", "--gateway=2001:db8:abc6::254", "dualstackl2")
// Ensure the network was created // Ensure the network was created
@ -267,7 +268,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkIpvlanL2MultiSubnet(c *check.C) {
func (s *DockerNetworkSuite) TestDockerNetworkIpvlanL3MultiSubnet(c *check.C) { func (s *DockerNetworkSuite) TestDockerNetworkIpvlanL3MultiSubnet(c *check.C) {
// create a dual stack multi-subnet Ipvlan L3 network and validate connectivity between all four containers per L3 mode // create a dual stack multi-subnet Ipvlan L3 network and validate connectivity between all four containers per L3 mode
testRequires(c, DaemonIsLinux, IPv6, IpvlanKernelSupport, NotUserNamespace, NotArm, IPv6) testRequires(c, DaemonIsLinux, IPv6, IpvlanKernelSupport, NotUserNamespace, NotArm, IPv6, ExperimentalDaemon)
dockerCmd(c, "network", "create", "--driver=ipvlan", "--ipv6", "--subnet=172.28.10.0/24", "--subnet=172.28.12.0/24", "--gateway=172.28.12.254", dockerCmd(c, "network", "create", "--driver=ipvlan", "--ipv6", "--subnet=172.28.10.0/24", "--subnet=172.28.12.0/24", "--gateway=172.28.12.254",
"--subnet=2001:db8:abc9::/64", "--subnet=2001:db8:abc7::/64", "--gateway=2001:db8:abc7::254", "-o", "ipvlan_mode=l3", "dualstackl3") "--subnet=2001:db8:abc9::/64", "--subnet=2001:db8:abc7::/64", "--gateway=2001:db8:abc7::254", "-o", "ipvlan_mode=l3", "dualstackl3")
// Ensure the network was created // Ensure the network was created
@ -326,7 +327,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkIpvlanL3MultiSubnet(c *check.C) {
func (s *DockerNetworkSuite) TestDockerNetworkIpvlanAddressing(c *check.C) { func (s *DockerNetworkSuite) TestDockerNetworkIpvlanAddressing(c *check.C) {
// Ensure the default gateways, next-hops and default dev devices are properly set // Ensure the default gateways, next-hops and default dev devices are properly set
testRequires(c, DaemonIsLinux, IPv6, IpvlanKernelSupport, NotUserNamespace, NotArm) testRequires(c, DaemonIsLinux, IPv6, IpvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
dockerCmd(c, "network", "create", "--driver=macvlan", "--ipv6", "--subnet=172.28.130.0/24", dockerCmd(c, "network", "create", "--driver=macvlan", "--ipv6", "--subnet=172.28.130.0/24",
"--subnet=2001:db8:abca::/64", "--gateway=2001:db8:abca::254", "-o", "macvlan_mode=bridge", "dualstackbridge") "--subnet=2001:db8:abca::/64", "--gateway=2001:db8:abca::254", "-o", "macvlan_mode=bridge", "dualstackbridge")
assertNwIsAvailable(c, "dualstackbridge") assertNwIsAvailable(c, "dualstackbridge")
@ -372,7 +373,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkIpvlanAddressing(c *check.C) {
func (s *DockerSuite) TestDockerNetworkMacVlanBridgeNilParent(c *check.C) { func (s *DockerSuite) TestDockerNetworkMacVlanBridgeNilParent(c *check.C) {
// macvlan bridge mode - dummy parent interface is provisioned dynamically // macvlan bridge mode - dummy parent interface is provisioned dynamically
testRequires(c, DaemonIsLinux, MacvlanKernelSupport, NotUserNamespace, NotArm) testRequires(c, DaemonIsLinux, MacvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
dockerCmd(c, "network", "create", "--driver=macvlan", "dm-nil-parent") dockerCmd(c, "network", "create", "--driver=macvlan", "dm-nil-parent")
assertNwIsAvailable(c, "dm-nil-parent") assertNwIsAvailable(c, "dm-nil-parent")
@ -389,7 +390,7 @@ func (s *DockerSuite) TestDockerNetworkMacVlanBridgeNilParent(c *check.C) {
func (s *DockerSuite) TestDockerNetworkMacVlanBridgeInternalMode(c *check.C) { func (s *DockerSuite) TestDockerNetworkMacVlanBridgeInternalMode(c *check.C) {
// macvlan bridge mode --internal containers can communicate inside the network but not externally // macvlan bridge mode --internal containers can communicate inside the network but not externally
testRequires(c, DaemonIsLinux, MacvlanKernelSupport, NotUserNamespace, NotArm) testRequires(c, DaemonIsLinux, MacvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
dockerCmd(c, "network", "create", "--driver=macvlan", "--internal", "dm-internal") dockerCmd(c, "network", "create", "--driver=macvlan", "--internal", "dm-internal")
assertNwIsAvailable(c, "dm-internal") assertNwIsAvailable(c, "dm-internal")
nr := getNetworkResource(c, "dm-internal") nr := getNetworkResource(c, "dm-internal")
@ -412,7 +413,7 @@ func (s *DockerSuite) TestDockerNetworkMacVlanBridgeInternalMode(c *check.C) {
func (s *DockerSuite) TestDockerNetworkIpvlanL2NilParent(c *check.C) { func (s *DockerSuite) TestDockerNetworkIpvlanL2NilParent(c *check.C) {
// ipvlan l2 mode - dummy parent interface is provisioned dynamically // ipvlan l2 mode - dummy parent interface is provisioned dynamically
testRequires(c, DaemonIsLinux, IpvlanKernelSupport, NotUserNamespace, NotArm) testRequires(c, DaemonIsLinux, IpvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
dockerCmd(c, "network", "create", "--driver=ipvlan", "di-nil-parent") dockerCmd(c, "network", "create", "--driver=ipvlan", "di-nil-parent")
assertNwIsAvailable(c, "di-nil-parent") assertNwIsAvailable(c, "di-nil-parent")
@ -429,7 +430,7 @@ func (s *DockerSuite) TestDockerNetworkIpvlanL2NilParent(c *check.C) {
func (s *DockerSuite) TestDockerNetworkIpvlanL2InternalMode(c *check.C) { func (s *DockerSuite) TestDockerNetworkIpvlanL2InternalMode(c *check.C) {
// ipvlan l2 mode --internal containers can communicate inside the network but not externally // ipvlan l2 mode --internal containers can communicate inside the network but not externally
testRequires(c, DaemonIsLinux, IpvlanKernelSupport, NotUserNamespace, NotArm) testRequires(c, DaemonIsLinux, IpvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
dockerCmd(c, "network", "create", "--driver=ipvlan", "--internal", "di-internal") dockerCmd(c, "network", "create", "--driver=ipvlan", "--internal", "di-internal")
assertNwIsAvailable(c, "di-internal") assertNwIsAvailable(c, "di-internal")
nr := getNetworkResource(c, "di-internal") nr := getNetworkResource(c, "di-internal")
@ -451,7 +452,7 @@ func (s *DockerSuite) TestDockerNetworkIpvlanL2InternalMode(c *check.C) {
func (s *DockerSuite) TestDockerNetworkIpvlanL3NilParent(c *check.C) { func (s *DockerSuite) TestDockerNetworkIpvlanL3NilParent(c *check.C) {
// ipvlan l3 mode - dummy parent interface is provisioned dynamically // ipvlan l3 mode - dummy parent interface is provisioned dynamically
testRequires(c, DaemonIsLinux, IpvlanKernelSupport, NotUserNamespace, NotArm) testRequires(c, DaemonIsLinux, IpvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
dockerCmd(c, "network", "create", "--driver=ipvlan", "--subnet=172.28.230.0/24", dockerCmd(c, "network", "create", "--driver=ipvlan", "--subnet=172.28.230.0/24",
"--subnet=172.28.220.0/24", "-o", "ipvlan_mode=l3", "di-nil-parent-l3") "--subnet=172.28.220.0/24", "-o", "ipvlan_mode=l3", "di-nil-parent-l3")
assertNwIsAvailable(c, "di-nil-parent-l3") assertNwIsAvailable(c, "di-nil-parent-l3")
@ -469,7 +470,7 @@ func (s *DockerSuite) TestDockerNetworkIpvlanL3NilParent(c *check.C) {
func (s *DockerSuite) TestDockerNetworkIpvlanL3InternalMode(c *check.C) { func (s *DockerSuite) TestDockerNetworkIpvlanL3InternalMode(c *check.C) {
// ipvlan l3 mode --internal containers can communicate inside the network but not externally // ipvlan l3 mode --internal containers can communicate inside the network but not externally
testRequires(c, DaemonIsLinux, IpvlanKernelSupport, NotUserNamespace, NotArm) testRequires(c, DaemonIsLinux, IpvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
dockerCmd(c, "network", "create", "--driver=ipvlan", "--subnet=172.28.230.0/24", dockerCmd(c, "network", "create", "--driver=ipvlan", "--subnet=172.28.230.0/24",
"--subnet=172.28.220.0/24", "-o", "ipvlan_mode=l3", "--internal", "di-internal-l3") "--subnet=172.28.220.0/24", "-o", "ipvlan_mode=l3", "--internal", "di-internal-l3")
assertNwIsAvailable(c, "di-internal-l3") assertNwIsAvailable(c, "di-internal-l3")
@ -492,7 +493,7 @@ func (s *DockerSuite) TestDockerNetworkIpvlanL3InternalMode(c *check.C) {
func (s *DockerSuite) TestDockerNetworkMacVlanExistingParent(c *check.C) { func (s *DockerSuite) TestDockerNetworkMacVlanExistingParent(c *check.C) {
// macvlan bridge mode - empty parent interface containers can reach each other internally but not externally // macvlan bridge mode - empty parent interface containers can reach each other internally but not externally
testRequires(c, DaemonIsLinux, MacvlanKernelSupport, NotUserNamespace, NotArm) testRequires(c, DaemonIsLinux, MacvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
netName := "dm-parent-exists" netName := "dm-parent-exists"
out, err := createMasterDummy(c, "dm-dummy0") out, err := createMasterDummy(c, "dm-dummy0")
//out, err := createVlanInterface(c, "dm-parent", "dm-slave", "macvlan", "bridge") //out, err := createVlanInterface(c, "dm-parent", "dm-slave", "macvlan", "bridge")
@ -512,7 +513,7 @@ func (s *DockerSuite) TestDockerNetworkMacVlanExistingParent(c *check.C) {
func (s *DockerSuite) TestDockerNetworkMacVlanSubinterface(c *check.C) { func (s *DockerSuite) TestDockerNetworkMacVlanSubinterface(c *check.C) {
// macvlan bridge mode - empty parent interface containers can reach each other internally but not externally // macvlan bridge mode - empty parent interface containers can reach each other internally but not externally
testRequires(c, DaemonIsLinux, MacvlanKernelSupport, NotUserNamespace, NotArm) testRequires(c, DaemonIsLinux, MacvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
netName := "dm-subinterface" netName := "dm-subinterface"
out, err := createMasterDummy(c, "dm-dummy0") out, err := createMasterDummy(c, "dm-dummy0")
c.Assert(err, check.IsNil, check.Commentf(out)) c.Assert(err, check.IsNil, check.Commentf(out))

View file

@ -61,6 +61,10 @@ var (
volumesConfigPath string volumesConfigPath string
containerStoragePath string containerStoragePath string
// experimentalDaemon tell whether the main daemon has
// experimental features enabled or not
experimentalDaemon bool
// daemonStorageDriver is held globally so that tests can know the storage // daemonStorageDriver is held globally so that tests can know the storage
// driver of the daemon. This is initialized in docker_utils by sending // driver of the daemon. This is initialized in docker_utils by sending
// a version call to the daemon and examining the response header. // a version call to the daemon and examining the response header.
@ -128,13 +132,15 @@ func init() {
// /info endpoint for the specific root dir // /info endpoint for the specific root dir
dockerBasePath = "/var/lib/docker" dockerBasePath = "/var/lib/docker"
type Info struct { type Info struct {
DockerRootDir string DockerRootDir string
ExperimentalBuild bool
} }
var i Info var i Info
status, b, err := sockRequest("GET", "/info", nil) status, b, err := sockRequest("GET", "/info", nil)
if err == nil && status == 200 { if err == nil && status == 200 {
if err = json.Unmarshal(b, &i); err == nil { if err = json.Unmarshal(b, &i); err == nil {
dockerBasePath = i.DockerRootDir dockerBasePath = i.DockerRootDir
experimentalDaemon = i.ExperimentalBuild
} }
} }
volumesConfigPath = dockerBasePath + "/volumes" volumesConfigPath = dockerBasePath + "/volumes"

View file

@ -9,7 +9,6 @@ import (
"strings" "strings"
"time" "time"
"github.com/docker/docker/utils"
"github.com/go-check/check" "github.com/go-check/check"
) )
@ -31,11 +30,11 @@ var (
"Test requires a Linux daemon", "Test requires a Linux daemon",
} }
ExperimentalDaemon = testRequirement{ ExperimentalDaemon = testRequirement{
func() bool { return utils.ExperimentalBuild() }, func() bool { return experimentalDaemon },
"Test requires an experimental daemon", "Test requires an experimental daemon",
} }
NotExperimentalDaemon = testRequirement{ NotExperimentalDaemon = testRequirement{
func() bool { return !utils.ExperimentalBuild() }, func() bool { return !experimentalDaemon },
"Test requires a non experimental daemon", "Test requires a non experimental daemon",
} }
IsAmd64 = testRequirement{ IsAmd64 = testRequirement{

View file

@ -27,6 +27,7 @@ dockerd - Enable daemon mode
[**--dns-search**[=*[]*]] [**--dns-search**[=*[]*]]
[**--exec-opt**[=*[]*]] [**--exec-opt**[=*[]*]]
[**--exec-root**[=*/var/run/docker*]] [**--exec-root**[=*/var/run/docker*]]
[**--experimental**[=*false*]]
[**--fixed-cidr**[=*FIXED-CIDR*]] [**--fixed-cidr**[=*FIXED-CIDR*]]
[**--fixed-cidr-v6**[=*FIXED-CIDR-V6*]] [**--fixed-cidr-v6**[=*FIXED-CIDR-V6*]]
[**-G**|**--group**[=*docker*]] [**-G**|**--group**[=*docker*]]
@ -146,6 +147,9 @@ format.
**--exec-root**="" **--exec-root**=""
Path to use as the root of the Docker execution state files. Default is `/var/run/docker`. Path to use as the root of the Docker execution state files. Default is `/var/run/docker`.
**--experimental**=""
Enable the daemon experimental features.
**--fixed-cidr**="" **--fixed-cidr**=""
IPv4 subnet for fixed IPs (e.g., 10.20.0.0/16); this subnet must be nested in the bridge subnet (which is defined by \-b or \-\-bip) IPv4 subnet for fixed IPs (e.g., 10.20.0.0/16); this subnet must be nested in the bridge subnet (which is defined by \-b or \-\-bip)

View file

@ -1,5 +1,3 @@
// +build experimental
package plugin package plugin
import ( import (

Some files were not shown because too many files have changed in this diff Show more