mirror of
				https://github.com/moby/moby.git
				synced 2022-11-09 12:21:53 -05:00 
			
		
		
		
	Make experimental a runtime flag
Signed-off-by: Kenfe-Mickael Laventure <mickael.laventure@gmail.com>
This commit is contained in:
		
							parent
							
								
									0ab13dda66
								
							
						
					
					
						commit
						7781a1bf0f
					
				
					 112 changed files with 782 additions and 979 deletions
				
			
		
							
								
								
									
										29
									
								
								api/server/middleware/experimental.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								api/server/middleware/experimental.go
									
										
									
									
									
										Normal 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)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
// +build experimental
 | 
			
		||||
 | 
			
		||||
package checkpoint
 | 
			
		||||
 | 
			
		||||
import "github.com/docker/docker/api/types"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,3 +26,11 @@ func NewRouter(b Backend, decoder httputils.ContainerDecoder) router.Router {
 | 
			
		|||
func (r *checkpointRouter) Routes() []router.Route {
 | 
			
		||||
	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),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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{}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
// +build experimental
 | 
			
		||||
 | 
			
		||||
package checkpoint
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
// +build experimental
 | 
			
		||||
 | 
			
		||||
package plugin
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,3 +21,16 @@ func NewRouter(b Backend) router.Router {
 | 
			
		|||
func (r *pluginRouter) Routes() []router.Route {
 | 
			
		||||
	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),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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{}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
// +build experimental
 | 
			
		||||
 | 
			
		||||
package plugin
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
// +build experimental
 | 
			
		||||
 | 
			
		||||
package bundlefile
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
// +build experimental
 | 
			
		||||
 | 
			
		||||
package bundlefile
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,13 +1,27 @@
 | 
			
		|||
// +build !experimental
 | 
			
		||||
 | 
			
		||||
package checkpoint
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"github.com/docker/docker/cli"
 | 
			
		||||
	"github.com/docker/docker/cli/command"
 | 
			
		||||
	"github.com/spf13/cobra"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// NewCheckpointCommand returns the `checkpoint` subcommand (only in experimental)
 | 
			
		||||
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
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
// +build experimental
 | 
			
		||||
 | 
			
		||||
package checkpoint
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
// +build experimental
 | 
			
		||||
 | 
			
		||||
package checkpoint
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
// +build experimental
 | 
			
		||||
 | 
			
		||||
package checkpoint
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,6 +19,7 @@ import (
 | 
			
		|||
	dopts "github.com/docker/docker/opts"
 | 
			
		||||
	"github.com/docker/go-connections/sockets"
 | 
			
		||||
	"github.com/docker/go-connections/tlsconfig"
 | 
			
		||||
	"golang.org/x/net/context"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Streams is an interface which exposes the standard input and output streams
 | 
			
		||||
| 
						 | 
				
			
			@ -37,6 +38,21 @@ type DockerCli struct {
 | 
			
		|||
	err             io.Writer
 | 
			
		||||
	keyFile         string
 | 
			
		||||
	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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,8 +24,6 @@ func AddCommands(cmd *cobra.Command, dockerCli *command.DockerCli) {
 | 
			
		|||
	cmd.AddCommand(
 | 
			
		||||
		node.NewNodeCommand(dockerCli),
 | 
			
		||||
		service.NewServiceCommand(dockerCli),
 | 
			
		||||
		stack.NewStackCommand(dockerCli),
 | 
			
		||||
		stack.NewTopLevelDeployCommand(dockerCli),
 | 
			
		||||
		swarm.NewSwarmCommand(dockerCli),
 | 
			
		||||
		container.NewContainerCommand(dockerCli),
 | 
			
		||||
		image.NewImageCommand(dockerCli),
 | 
			
		||||
| 
						 | 
				
			
			@ -72,11 +70,19 @@ func AddCommands(cmd *cobra.Command, dockerCli *command.DockerCli) {
 | 
			
		|||
		hide(image.NewSaveCommand(dockerCli)),
 | 
			
		||||
		hide(image.NewTagCommand(dockerCli)),
 | 
			
		||||
		hide(system.NewInspectCommand(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 {
 | 
			
		||||
	if os.Getenv("DOCKER_HIDE_LEGACY_COMMANDS") == "" {
 | 
			
		||||
		return cmd
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -44,7 +44,9 @@ func NewStartCommand(dockerCli *command.DockerCli) *cobra.Command {
 | 
			
		|||
	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")
 | 
			
		||||
 | 
			
		||||
	addExperimentalStartFlags(flags, &opts)
 | 
			
		||||
	if dockerCli.HasExperimental() {
 | 
			
		||||
		flags.StringVar(&opts.checkpoint, "checkpoint", "", "Restore from this checkpoint")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return cmd
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,8 +0,0 @@
 | 
			
		|||
// +build !experimental
 | 
			
		||||
 | 
			
		||||
package container
 | 
			
		||||
 | 
			
		||||
import "github.com/spf13/pflag"
 | 
			
		||||
 | 
			
		||||
func addExperimentalStartFlags(flags *pflag.FlagSet, opts *startOptions) {
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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")
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,13 +1,33 @@
 | 
			
		|||
// +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 {
 | 
			
		||||
	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
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
// +build experimental
 | 
			
		||||
 | 
			
		||||
package plugin
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
// +build experimental
 | 
			
		||||
 | 
			
		||||
package plugin
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
// +build experimental
 | 
			
		||||
 | 
			
		||||
package plugin
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
// +build experimental
 | 
			
		||||
 | 
			
		||||
package plugin
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
// +build experimental
 | 
			
		||||
 | 
			
		||||
package plugin
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
// +build experimental
 | 
			
		||||
 | 
			
		||||
package plugin
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
// +build experimental
 | 
			
		||||
 | 
			
		||||
package plugin
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
// +build experimental
 | 
			
		||||
 | 
			
		||||
package plugin
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,18 +1,38 @@
 | 
			
		|||
// +build !experimental
 | 
			
		||||
 | 
			
		||||
package stack
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"github.com/docker/docker/cli"
 | 
			
		||||
	"github.com/docker/docker/cli/command"
 | 
			
		||||
	"github.com/spf13/cobra"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// NewStackCommand returns no command
 | 
			
		||||
// NewStackCommand returns a cobra command for `stack` subcommands
 | 
			
		||||
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 {
 | 
			
		||||
	return &cobra.Command{}
 | 
			
		||||
	cmd := newDeployCommand(dockerCli)
 | 
			
		||||
	// Remove the aliases at the top level
 | 
			
		||||
	cmd.Aliases = []string{}
 | 
			
		||||
	return cmd
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
// +build experimental
 | 
			
		||||
 | 
			
		||||
package stack
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
// +build experimental
 | 
			
		||||
 | 
			
		||||
package stack
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
// +build experimental
 | 
			
		||||
 | 
			
		||||
package stack
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
// +build experimental
 | 
			
		||||
 | 
			
		||||
package stack
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
// +build experimental
 | 
			
		||||
 | 
			
		||||
package stack
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
// +build experimental
 | 
			
		||||
 | 
			
		||||
package stack
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
// +build experimental
 | 
			
		||||
 | 
			
		||||
package stack
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
// +build experimental
 | 
			
		||||
 | 
			
		||||
package stack
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 != "" {
 | 
			
		||||
		fmt.Fprintf(dockerCli.Out(), "Cluster Store: %s\n", info.ClusterStore)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,7 +10,6 @@ import (
 | 
			
		|||
	"github.com/docker/docker/cli"
 | 
			
		||||
	"github.com/docker/docker/cli/command"
 | 
			
		||||
	"github.com/docker/docker/dockerversion"
 | 
			
		||||
	"github.com/docker/docker/utils"
 | 
			
		||||
	"github.com/docker/docker/utils/templates"
 | 
			
		||||
	"github.com/spf13/cobra"
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -21,8 +20,7 @@ var versionTemplate = `Client:
 | 
			
		|||
 Go version:   {{.Client.GoVersion}}
 | 
			
		||||
 Git commit:   {{.Client.GitCommit}}
 | 
			
		||||
 Built:        {{.Client.BuildTime}}
 | 
			
		||||
 OS/Arch:      {{.Client.Os}}/{{.Client.Arch}}{{if .Client.Experimental}}
 | 
			
		||||
 Experimental: {{.Client.Experimental}}{{end}}{{if .ServerOK}}
 | 
			
		||||
 OS/Arch:      {{.Client.Os}}/{{.Client.Arch}}{{if .ServerOK}}
 | 
			
		||||
 | 
			
		||||
Server:
 | 
			
		||||
 Version:      {{.Server.Version}}
 | 
			
		||||
| 
						 | 
				
			
			@ -30,8 +28,8 @@ Server:
 | 
			
		|||
 Go version:   {{.Server.GoVersion}}
 | 
			
		||||
 Git commit:   {{.Server.GitCommit}}
 | 
			
		||||
 Built:        {{.Server.BuildTime}}
 | 
			
		||||
 OS/Arch:      {{.Server.Os}}/{{.Server.Arch}}{{if .Server.Experimental}}
 | 
			
		||||
 Experimental: {{.Server.Experimental}}{{end}}{{end}}`
 | 
			
		||||
 OS/Arch:      {{.Server.Os}}/{{.Server.Arch}}
 | 
			
		||||
 Experimental: {{.Server.Experimental}}{{end}}`
 | 
			
		||||
 | 
			
		||||
type versionOptions struct {
 | 
			
		||||
	format string
 | 
			
		||||
| 
						 | 
				
			
			@ -80,7 +78,6 @@ func runVersion(dockerCli *command.DockerCli, opts *versionOptions) error {
 | 
			
		|||
			BuildTime:  dockerversion.BuildTime,
 | 
			
		||||
			Os:         runtime.GOOS,
 | 
			
		||||
			Arch:       runtime.GOARCH,
 | 
			
		||||
			Experimental: utils.ExperimentalBuild(),
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -127,6 +127,7 @@ type SystemAPIClient interface {
 | 
			
		|||
	Info(ctx context.Context) (types.Info, error)
 | 
			
		||||
	RegistryLogin(ctx context.Context, auth types.AuthConfig) (types.AuthResponse, error)
 | 
			
		||||
	DiskUsage(ctx context.Context) (types.DiskUsage, error)
 | 
			
		||||
	Ping(ctx context.Context) (bool, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// VolumeAPIClient defines API client methods for the volumes
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
// +build experimental
 | 
			
		||||
 | 
			
		||||
package client
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			@ -7,9 +5,7 @@ import (
 | 
			
		|||
	"golang.org/x/net/context"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// APIClient is an interface that clients that talk with a docker server must implement.
 | 
			
		||||
type APIClient interface {
 | 
			
		||||
	CommonAPIClient
 | 
			
		||||
type apiClientExperimental interface {
 | 
			
		||||
	CheckpointAPIClient
 | 
			
		||||
	PluginAPIClient
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -32,6 +28,3 @@ type PluginAPIClient interface {
 | 
			
		|||
	PluginSet(ctx context.Context, name string, args []string) error
 | 
			
		||||
	PluginInspectWithRaw(ctx context.Context, name string) (*types.Plugin, []byte, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Ensure that Client always implements APIClient.
 | 
			
		||||
var _ APIClient = &Client{}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,10 +1,9 @@
 | 
			
		|||
// +build !experimental
 | 
			
		||||
 | 
			
		||||
package client
 | 
			
		||||
 | 
			
		||||
// APIClient is an interface that clients that talk with a docker server must implement.
 | 
			
		||||
type APIClient interface {
 | 
			
		||||
	CommonAPIClient
 | 
			
		||||
	apiClientExperimental
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Ensure that Client always implements APIClient.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										19
									
								
								client/ping.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								client/ping.go
									
										
									
									
									
										Normal 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
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
// +build experimental
 | 
			
		||||
 | 
			
		||||
package client
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
// +build experimental
 | 
			
		||||
 | 
			
		||||
package client
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
// +build experimental
 | 
			
		||||
 | 
			
		||||
package client
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
// +build experimental
 | 
			
		||||
 | 
			
		||||
package client
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
// +build experimental
 | 
			
		||||
 | 
			
		||||
package client
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
// +build experimental
 | 
			
		||||
 | 
			
		||||
package client
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
// +build experimental
 | 
			
		||||
 | 
			
		||||
package client
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
// +build experimental
 | 
			
		||||
 | 
			
		||||
package client
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
// +build experimental
 | 
			
		||||
 | 
			
		||||
package client
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
// +build experimental
 | 
			
		||||
 | 
			
		||||
package client
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
// +build experimental
 | 
			
		||||
 | 
			
		||||
package client
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
// +build experimental
 | 
			
		||||
 | 
			
		||||
package client
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
// +build experimental
 | 
			
		||||
 | 
			
		||||
package client
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
// +build experimental
 | 
			
		||||
 | 
			
		||||
package client
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
// +build experimental
 | 
			
		||||
 | 
			
		||||
package client
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -91,12 +91,8 @@ func main() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
func showVersion() {
 | 
			
		||||
	if utils.ExperimentalBuild() {
 | 
			
		||||
		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) {
 | 
			
		||||
	cliflags.SetLogLevel(opts.Common.LogLevel)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -129,7 +129,7 @@ func (cli *DaemonCli) start(opts daemonOptions) (err error) {
 | 
			
		|||
		utils.EnableDebug()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if utils.ExperimentalBuild() {
 | 
			
		||||
	if cli.Config.Experimental {
 | 
			
		||||
		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) {
 | 
			
		||||
	v := cfg.Version
 | 
			
		||||
 | 
			
		||||
	exp := middleware.NewExperimentalMiddleware(cli.d.HasExperimental())
 | 
			
		||||
	s.UseMiddleware(exp)
 | 
			
		||||
 | 
			
		||||
	vm := middleware.NewVersionMiddleware(v, api.DefaultVersion, api.MinVersion)
 | 
			
		||||
	s.UseMiddleware(vm)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,7 +13,6 @@ import (
 | 
			
		|||
	"github.com/docker/docker/dockerversion"
 | 
			
		||||
	"github.com/docker/docker/pkg/reexec"
 | 
			
		||||
	"github.com/docker/docker/pkg/term"
 | 
			
		||||
	"github.com/docker/docker/utils"
 | 
			
		||||
	"github.com/spf13/cobra"
 | 
			
		||||
	"github.com/spf13/pflag"
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -85,12 +84,8 @@ func runDaemon(opts daemonOptions) error {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
func showVersion() {
 | 
			
		||||
	if utils.ExperimentalBuild() {
 | 
			
		||||
		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() {
 | 
			
		||||
	if reexec.Init() {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
// +build experimental
 | 
			
		||||
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			@ -12,5 +10,8 @@ import (
 | 
			
		|||
)
 | 
			
		||||
 | 
			
		||||
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()))
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -153,6 +153,8 @@ type CommonConfig struct {
 | 
			
		|||
 | 
			
		||||
	reloadLock sync.Mutex
 | 
			
		||||
	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
 | 
			
		||||
| 
						 | 
				
			
			@ -187,6 +189,7 @@ func (config *Config) InstallCommonFlags(flags *pflag.FlagSet) {
 | 
			
		|||
	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.BoolVar(&config.Experimental, "experimental", false, "Enable experimental features")
 | 
			
		||||
 | 
			
		||||
	config.MaxConcurrentDownloads = &maxConcurrentDownloads
 | 
			
		||||
	config.MaxConcurrentUploads = &maxConcurrentUploads
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
// +build experimental
 | 
			
		||||
 | 
			
		||||
package daemon
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,10 +0,0 @@
 | 
			
		|||
// +build !experimental
 | 
			
		||||
 | 
			
		||||
package daemon
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/spf13/pflag"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func (config *Config) attachExperimentalFlags(cmd *pflag.FlagSet) {
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -104,6 +104,14 @@ type Daemon struct {
 | 
			
		|||
	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 {
 | 
			
		||||
	var (
 | 
			
		||||
		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.
 | 
			
		||||
	if err := pluginInit(d, config, containerdRemote); err != nil {
 | 
			
		||||
	if err := d.pluginInit(config, containerdRemote); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -775,7 +783,7 @@ func (daemon *Daemon) Shutdown() error {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	// Shutdown plugins after containers. Dont change the order.
 | 
			
		||||
	pluginShutdown()
 | 
			
		||||
	daemon.pluginShutdown()
 | 
			
		||||
 | 
			
		||||
	// trigger libnetwork Stop only if it's initialized
 | 
			
		||||
	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 {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// If no value is set for max-concurrent-downloads we assume it is the default value
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
// +build experimental
 | 
			
		||||
 | 
			
		||||
package daemon
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			@ -12,11 +10,17 @@ func (daemon *Daemon) verifyExperimentalContainerSettings(hostConfig *container.
 | 
			
		|||
	return nil, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func pluginInit(d *Daemon, cfg *Config, remote libcontainerd.Remote) error {
 | 
			
		||||
	return plugin.Init(cfg.Root, d.PluginStore, remote, d.RegistryService, cfg.LiveRestoreEnabled, d.LogPluginEvent)
 | 
			
		||||
func (daemon *Daemon) pluginInit(cfg *Config, remote libcontainerd.Remote) error {
 | 
			
		||||
	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()
 | 
			
		||||
	// Check for a valid manager object. In error conditions, daemon init can fail
 | 
			
		||||
	// and shutdown called, before plugin manager is initialized.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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() {
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
// +build experimental
 | 
			
		||||
 | 
			
		||||
package graphdriver
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
// +build experimental
 | 
			
		||||
 | 
			
		||||
package graphdriver
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -109,7 +109,7 @@ func (daemon *Daemon) SystemInfo() (*types.Info, error) {
 | 
			
		|||
		MemTotal:           meminfo.MemTotal,
 | 
			
		||||
		DockerRootDir:      daemon.configStore.Root,
 | 
			
		||||
		Labels:             daemon.configStore.Labels,
 | 
			
		||||
		ExperimentalBuild:  utils.ExperimentalBuild(),
 | 
			
		||||
		ExperimentalBuild:  daemon.configStore.Experimental,
 | 
			
		||||
		ServerVersion:      dockerversion.Version,
 | 
			
		||||
		ClusterStore:       daemon.configStore.ClusterStore,
 | 
			
		||||
		ClusterAdvertise:   daemon.configStore.ClusterAdvertise,
 | 
			
		||||
| 
						 | 
				
			
			@ -158,7 +158,7 @@ func (daemon *Daemon) SystemVersion() types.Version {
 | 
			
		|||
		Os:           runtime.GOOS,
 | 
			
		||||
		Arch:         runtime.GOARCH,
 | 
			
		||||
		BuildTime:    dockerversion.BuildTime,
 | 
			
		||||
		Experimental: utils.ExperimentalBuild(),
 | 
			
		||||
		Experimental: daemon.configStore.Experimental,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	kernelVersion := "<unknown>"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -157,7 +157,7 @@ This section lists each version from latest to oldest.  Each listing includes a
 | 
			
		|||
* `POST /containers/prune` prunes stopped containers.
 | 
			
		||||
* `POST /images/prune` prunes unused images.
 | 
			
		||||
* `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
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -45,6 +45,7 @@ Options:
 | 
			
		|||
      --dns-search value                      DNS search domains to use (default [])
 | 
			
		||||
      --exec-opt value                        Runtime execution options (default [])
 | 
			
		||||
      --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-v6 string                  IPv6 subnet for fixed IPs
 | 
			
		||||
  -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": [],
 | 
			
		||||
	"exec-opts": [],
 | 
			
		||||
	"exec-root": "",
 | 
			
		||||
	"experimental": false,
 | 
			
		||||
	"storage-driver": "",
 | 
			
		||||
	"storage-opts": [],
 | 
			
		||||
	"labels": [],
 | 
			
		||||
| 
						 | 
				
			
			@ -1195,6 +1197,7 @@ This is a full example of the allowed configuration options on Windows:
 | 
			
		|||
    "dns-opts": [],
 | 
			
		||||
    "dns-search": [],
 | 
			
		||||
    "exec-opts": [],
 | 
			
		||||
    "experimental": false,
 | 
			
		||||
    "storage-driver": "",
 | 
			
		||||
    "storage-opts": [],
 | 
			
		||||
    "labels": [],
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -126,12 +126,6 @@ if [ ! "$GOPATH" ]; then
 | 
			
		|||
	exit 1
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if [ "$DOCKER_EXPERIMENTAL" ]; then
 | 
			
		||||
	echo >&2 '# WARNING! DOCKER_EXPERIMENTAL is set: building experimental features'
 | 
			
		||||
	echo >&2
 | 
			
		||||
	DOCKER_BUILDTAGS+=" experimental"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
DOCKER_BUILDTAGS+=" daemon"
 | 
			
		||||
if ${PKG_CONFIG} 'libsystemd >= 209' 2> /dev/null ; then
 | 
			
		||||
	DOCKER_BUILDTAGS+=" journald"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -50,6 +50,11 @@ if [ "$DOCKER_REMAP_ROOT" ]; then
 | 
			
		|||
	extra_params="--userns-remap $DOCKER_REMAP_ROOT"
 | 
			
		||||
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
 | 
			
		||||
	# Start apparmor if it is enabled
 | 
			
		||||
	if [ -e "/sys/module/apparmor/parameters/enabled" ] && [ "$(cat /sys/module/apparmor/parameters/enabled)" == "Y" ]; then
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -76,10 +76,6 @@ set -e
 | 
			
		|||
			# Install runc and containerd
 | 
			
		||||
			RUN ./hack/dockerfile/install-binaries.sh runc-dynamic containerd-dynamic
 | 
			
		||||
		EOF
 | 
			
		||||
 | 
			
		||||
		if [ "$DOCKER_EXPERIMENTAL" ]; then
 | 
			
		||||
			echo 'ENV DOCKER_EXPERIMENTAL 1' >> "$DEST/$version/Dockerfile.build"
 | 
			
		||||
		fi
 | 
			
		||||
		cat >> "$DEST/$version/Dockerfile.build" <<-EOF
 | 
			
		||||
			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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -96,8 +96,7 @@ set -e
 | 
			
		|||
			# Install runc and containerd
 | 
			
		||||
			RUN ./hack/dockerfile/install-binaries.sh runc-dynamic containerd-dynamic
 | 
			
		||||
		EOF
 | 
			
		||||
 | 
			
		||||
		if [ "$DOCKER_EXPERIMENTAL" ]; then
 | 
			
		||||
		if [[ "$VERSION" == *-dev ]] || [ -n "$(git status --porcelain)" ]; then
 | 
			
		||||
			echo 'ENV DOCKER_EXPERIMENTAL 1' >> "$DEST/$version/Dockerfile.build"
 | 
			
		||||
		fi
 | 
			
		||||
		cat >> "$DEST/$version/Dockerfile.build" <<-EOF
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -39,7 +39,7 @@ if [[ "$VERSION" == *-rc* ]]; then
 | 
			
		|||
	component="testing"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if [ "$DOCKER_EXPERIMENTAL" ] || [[ "$VERSION" == *-dev ]] || [ -n "$(git status --porcelain)" ]; then
 | 
			
		||||
if [[ "$VERSION" == *-dev ]] || [ -n "$(git status --porcelain)" ]; then
 | 
			
		||||
	component="experimental"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,7 +25,7 @@ if [[ "$VERSION" == *-rc* ]]; then
 | 
			
		|||
	release="testing"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if [ $DOCKER_EXPERIMENTAL ] || [[ "$VERSION" == *-dev ]] || [ -n "$(git status --porcelain)" ]; then
 | 
			
		||||
if [[ "$VERSION" == *-dev ]] || [ -n "$(git status --porcelain)" ]; then
 | 
			
		||||
	release="experimental"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -266,7 +266,11 @@ func (s *DockerSwarmSuite) AddDaemon(c *check.C, joinSwarm, manager bool) *Swarm
 | 
			
		|||
		port:   defaultSwarmPort + s.portIndex,
 | 
			
		||||
	}
 | 
			
		||||
	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)
 | 
			
		||||
 | 
			
		||||
	if joinSwarm == true {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -153,6 +153,9 @@ func (d *Daemon) StartWithLogFile(out *os.File, providedArgs ...string) error {
 | 
			
		|||
		"--pidfile", fmt.Sprintf("%s/docker.pid", d.folder),
 | 
			
		||||
		fmt.Sprintf("--userland-proxy=%t", d.userlandProxy),
 | 
			
		||||
	)
 | 
			
		||||
	if experimentalDaemon {
 | 
			
		||||
		args = append(args, "--experimental")
 | 
			
		||||
	}
 | 
			
		||||
	if !(d.useDefaultHost || d.useDefaultTLSHost) {
 | 
			
		||||
		args = append(args, []string{"--host", d.sock()}...)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
// +build linux, experimental
 | 
			
		||||
// +build linux
 | 
			
		||||
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -17,7 +17,8 @@ var pluginName = "tiborvass/no-remove"
 | 
			
		|||
 | 
			
		||||
// TestDaemonRestartWithPluginEnabled tests state restore for an enabled plugin
 | 
			
		||||
func (s *DockerDaemonSuite) TestDaemonRestartWithPluginEnabled(c *check.C) {
 | 
			
		||||
	testRequires(c, Network)
 | 
			
		||||
	testRequires(c, Network, ExperimentalDaemon)
 | 
			
		||||
 | 
			
		||||
	if err := s.d.Start(); err != nil {
 | 
			
		||||
		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
 | 
			
		||||
func (s *DockerDaemonSuite) TestDaemonRestartWithPluginDisabled(c *check.C) {
 | 
			
		||||
	testRequires(c, Network)
 | 
			
		||||
	testRequires(c, Network, ExperimentalDaemon)
 | 
			
		||||
 | 
			
		||||
	if err := s.d.Start(); err != nil {
 | 
			
		||||
		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.
 | 
			
		||||
// Plugins should continue to run.
 | 
			
		||||
func (s *DockerDaemonSuite) TestDaemonKillLiveRestoreWithPlugins(c *check.C) {
 | 
			
		||||
	testRequires(c, Network)
 | 
			
		||||
	testRequires(c, Network, ExperimentalDaemon)
 | 
			
		||||
 | 
			
		||||
	if err := s.d.Start("--live-restore"); err != nil {
 | 
			
		||||
		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.
 | 
			
		||||
// Plugins should continue to run.
 | 
			
		||||
func (s *DockerDaemonSuite) TestDaemonShutdownLiveRestoreWithPlugins(c *check.C) {
 | 
			
		||||
	testRequires(c, Network)
 | 
			
		||||
	testRequires(c, Network, ExperimentalDaemon)
 | 
			
		||||
 | 
			
		||||
	if err := s.d.Start("--live-restore"); err != nil {
 | 
			
		||||
		c.Fatalf("Could not start daemon: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -142,7 +146,8 @@ func (s *DockerDaemonSuite) TestDaemonShutdownLiveRestoreWithPlugins(c *check.C)
 | 
			
		|||
 | 
			
		||||
// TestDaemonShutdownWithPlugins shuts down running plugins.
 | 
			
		||||
func (s *DockerDaemonSuite) TestDaemonShutdownWithPlugins(c *check.C) {
 | 
			
		||||
	testRequires(c, Network)
 | 
			
		||||
	testRequires(c, Network, ExperimentalDaemon)
 | 
			
		||||
 | 
			
		||||
	if err := s.d.Start(); err != nil {
 | 
			
		||||
		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.
 | 
			
		||||
func (s *DockerDaemonSuite) TestVolumePlugin(c *check.C) {
 | 
			
		||||
	testRequires(c, Network)
 | 
			
		||||
	testRequires(c, Network, ExperimentalDaemon)
 | 
			
		||||
 | 
			
		||||
	volName := "plugin-volume"
 | 
			
		||||
	volRoot := "/data"
 | 
			
		||||
	destDir := "/tmp/data/"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,21 +1,36 @@
 | 
			
		|||
// +build experimental
 | 
			
		||||
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/docker/docker/pkg/integration/checker"
 | 
			
		||||
	"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")
 | 
			
		||||
	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")
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	out, _ = dockerCmd(c, "-v")
 | 
			
		||||
	c.Assert(out, checker.Contains, ", experimental", check.Commentf("docker version did not contain experimental"))
 | 
			
		||||
	c.Fatal(`"Experimental" not found in version output`)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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`)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,3 @@
 | 
			
		|||
// +build experimental
 | 
			
		||||
// +build !windows
 | 
			
		||||
 | 
			
		||||
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) {
 | 
			
		||||
		s.ec[ext].applydiff++
 | 
			
		||||
		var diff io.Reader = r.Body
 | 
			
		||||
		diff := r.Body
 | 
			
		||||
		defer r.Body.Close()
 | 
			
		||||
 | 
			
		||||
		id := r.URL.Query().Get("id")
 | 
			
		||||
| 
						 | 
				
			
			@ -338,6 +337,8 @@ func (s *DockerExternalGraphdriverSuite) TearDownSuite(c *check.C) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
func (s *DockerExternalGraphdriverSuite) TestExternalGraphDriver(c *check.C) {
 | 
			
		||||
	testRequires(c, ExperimentalDaemon)
 | 
			
		||||
 | 
			
		||||
	s.testExternalGraphDriver("test-external-graph-driver", "spec", 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) {
 | 
			
		||||
	testRequires(c, Network)
 | 
			
		||||
	testRequires(c, Network, ExperimentalDaemon)
 | 
			
		||||
 | 
			
		||||
	c.Assert(s.d.Start(), check.IsNil)
 | 
			
		||||
 | 
			
		||||
	out, err := s.d.Cmd("pull", "busybox:latest")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,7 +10,6 @@ import (
 | 
			
		|||
	"github.com/docker/docker/pkg/homedir"
 | 
			
		||||
	"github.com/docker/docker/pkg/integration/checker"
 | 
			
		||||
	icmd "github.com/docker/docker/pkg/integration/cmd"
 | 
			
		||||
	"github.com/docker/docker/utils"
 | 
			
		||||
	"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 rm")
 | 
			
		||||
 | 
			
		||||
		if utils.ExperimentalBuild() {
 | 
			
		||||
		if experimentalDaemon {
 | 
			
		||||
			cmdsToTest = append(cmdsToTest, "checkpoint create")
 | 
			
		||||
			cmdsToTest = append(cmdsToTest, "checkpoint ls")
 | 
			
		||||
			cmdsToTest = append(cmdsToTest, "checkpoint rm")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,7 +7,6 @@ import (
 | 
			
		|||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/docker/docker/pkg/integration/checker"
 | 
			
		||||
	"github.com/docker/docker/utils"
 | 
			
		||||
	"github.com/go-check/check"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -44,8 +43,10 @@ func (s *DockerSuite) TestInfoEnsureSucceeds(c *check.C) {
 | 
			
		|||
		stringsToCheck = append(stringsToCheck, "Runtimes:", "Default Runtime: runc")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if utils.ExperimentalBuild() {
 | 
			
		||||
	if experimentalDaemon {
 | 
			
		||||
		stringsToCheck = append(stringsToCheck, "Experimental: true")
 | 
			
		||||
	} else {
 | 
			
		||||
		stringsToCheck = append(stringsToCheck, "Experimental: false")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, linePrefix := range stringsToCheck {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
// +build experimental
 | 
			
		||||
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			@ -11,6 +9,7 @@ import (
 | 
			
		|||
)
 | 
			
		||||
 | 
			
		||||
func (s *DockerSwarmSuite) TestStackRemove(c *check.C) {
 | 
			
		||||
	testRequires(c, ExperimentalDaemon)
 | 
			
		||||
	d := s.AddDaemon(c, true, true)
 | 
			
		||||
 | 
			
		||||
	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) {
 | 
			
		||||
	testRequires(c, ExperimentalDaemon)
 | 
			
		||||
	d := s.AddDaemon(c, true, true)
 | 
			
		||||
 | 
			
		||||
	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) {
 | 
			
		||||
	testRequires(c, ExperimentalDaemon)
 | 
			
		||||
	d := s.AddDaemon(c, true, true)
 | 
			
		||||
 | 
			
		||||
	stackArgs := append([]string{"stack", "services", "UNKNOWN_STACK"})
 | 
			
		||||
| 
						 | 
				
			
			@ -59,6 +60,7 @@ const testDAB = `{
 | 
			
		|||
}`
 | 
			
		||||
 | 
			
		||||
func (s *DockerSwarmSuite) TestStackWithDAB(c *check.C) {
 | 
			
		||||
	testRequires(c, ExperimentalDaemon)
 | 
			
		||||
	// setup
 | 
			
		||||
	testStackName := "test"
 | 
			
		||||
	testDABFileName := testStackName + ".dab"
 | 
			
		||||
| 
						 | 
				
			
			@ -92,6 +94,7 @@ func (s *DockerSwarmSuite) TestStackWithDAB(c *check.C) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
func (s *DockerSwarmSuite) TestStackWithDABExtension(c *check.C) {
 | 
			
		||||
	testRequires(c, ExperimentalDaemon)
 | 
			
		||||
	// setup
 | 
			
		||||
	testStackName := "test.dab"
 | 
			
		||||
	testDABFileName := testStackName
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
// +build experimental
 | 
			
		||||
// +build !windows
 | 
			
		||||
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -50,7 +50,8 @@ var (
 | 
			
		|||
 | 
			
		||||
func (s *DockerNetworkSuite) TestDockerNetworkMacvlanPersistance(c *check.C) {
 | 
			
		||||
	// 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 := "dm-dummy0"
 | 
			
		||||
	// 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) {
 | 
			
		||||
	// 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 := "di-dummy0"
 | 
			
		||||
	// 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) {
 | 
			
		||||
	// 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 := "dm-dummy0"
 | 
			
		||||
	// 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) {
 | 
			
		||||
	// 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 := "di-dummy0"
 | 
			
		||||
	// 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) {
 | 
			
		||||
	// 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 := "dm-dummy0"
 | 
			
		||||
	out, err := createMasterDummy(c, master)
 | 
			
		||||
| 
						 | 
				
			
			@ -138,7 +139,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkMacvlanOverlapParent(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
 | 
			
		||||
	testRequires(c, DaemonIsLinux, IpvlanKernelSupport, NotUserNamespace, NotArm)
 | 
			
		||||
	testRequires(c, DaemonIsLinux, IpvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
 | 
			
		||||
	// master dummy interface 'dm' abbreviation represents 'docker ipvlan'
 | 
			
		||||
	master := "di-dummy0"
 | 
			
		||||
	out, err := createMasterDummy(c, master)
 | 
			
		||||
| 
						 | 
				
			
			@ -158,7 +159,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkIpvlanOverlapParent(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
 | 
			
		||||
	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",
 | 
			
		||||
		"--subnet=2001:db8:abc2::/64", "--subnet=2001:db8:abc4::/64", "--gateway=2001:db8:abc4::254", "dualstackbridge")
 | 
			
		||||
	// Ensure the network was created
 | 
			
		||||
| 
						 | 
				
			
			@ -213,7 +214,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkMacvlanMultiSubnet(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
 | 
			
		||||
	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",
 | 
			
		||||
		"--subnet=2001:db8:abc8::/64", "--subnet=2001:db8:abc6::/64", "--gateway=2001:db8:abc6::254", "dualstackl2")
 | 
			
		||||
	// Ensure the network was created
 | 
			
		||||
| 
						 | 
				
			
			@ -267,7 +268,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkIpvlanL2MultiSubnet(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
 | 
			
		||||
	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",
 | 
			
		||||
		"--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
 | 
			
		||||
| 
						 | 
				
			
			@ -326,7 +327,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkIpvlanL3MultiSubnet(c *check.C) {
 | 
			
		|||
 | 
			
		||||
func (s *DockerNetworkSuite) TestDockerNetworkIpvlanAddressing(c *check.C) {
 | 
			
		||||
	// 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",
 | 
			
		||||
		"--subnet=2001:db8:abca::/64", "--gateway=2001:db8:abca::254", "-o", "macvlan_mode=bridge", "dualstackbridge")
 | 
			
		||||
	assertNwIsAvailable(c, "dualstackbridge")
 | 
			
		||||
| 
						 | 
				
			
			@ -372,7 +373,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkIpvlanAddressing(c *check.C) {
 | 
			
		|||
 | 
			
		||||
func (s *DockerSuite) TestDockerNetworkMacVlanBridgeNilParent(c *check.C) {
 | 
			
		||||
	// 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")
 | 
			
		||||
	assertNwIsAvailable(c, "dm-nil-parent")
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -389,7 +390,7 @@ func (s *DockerSuite) TestDockerNetworkMacVlanBridgeNilParent(c *check.C) {
 | 
			
		|||
 | 
			
		||||
func (s *DockerSuite) TestDockerNetworkMacVlanBridgeInternalMode(c *check.C) {
 | 
			
		||||
	// 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")
 | 
			
		||||
	assertNwIsAvailable(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) {
 | 
			
		||||
	// 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")
 | 
			
		||||
	assertNwIsAvailable(c, "di-nil-parent")
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -429,7 +430,7 @@ func (s *DockerSuite) TestDockerNetworkIpvlanL2NilParent(c *check.C) {
 | 
			
		|||
 | 
			
		||||
func (s *DockerSuite) TestDockerNetworkIpvlanL2InternalMode(c *check.C) {
 | 
			
		||||
	// 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")
 | 
			
		||||
	assertNwIsAvailable(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) {
 | 
			
		||||
	// 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",
 | 
			
		||||
		"--subnet=172.28.220.0/24", "-o", "ipvlan_mode=l3", "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) {
 | 
			
		||||
	// 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",
 | 
			
		||||
		"--subnet=172.28.220.0/24", "-o", "ipvlan_mode=l3", "--internal", "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) {
 | 
			
		||||
	// 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"
 | 
			
		||||
	out, err := createMasterDummy(c, "dm-dummy0")
 | 
			
		||||
	//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) {
 | 
			
		||||
	// 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"
 | 
			
		||||
	out, err := createMasterDummy(c, "dm-dummy0")
 | 
			
		||||
	c.Assert(err, check.IsNil, check.Commentf(out))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -61,6 +61,10 @@ var (
 | 
			
		|||
	volumesConfigPath    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
 | 
			
		||||
	// driver of the daemon. This is initialized in docker_utils by sending
 | 
			
		||||
	// a version call to the daemon and examining the response header.
 | 
			
		||||
| 
						 | 
				
			
			@ -129,12 +133,14 @@ func init() {
 | 
			
		|||
	dockerBasePath = "/var/lib/docker"
 | 
			
		||||
	type Info struct {
 | 
			
		||||
		DockerRootDir     string
 | 
			
		||||
		ExperimentalBuild bool
 | 
			
		||||
	}
 | 
			
		||||
	var i Info
 | 
			
		||||
	status, b, err := sockRequest("GET", "/info", nil)
 | 
			
		||||
	if err == nil && status == 200 {
 | 
			
		||||
		if err = json.Unmarshal(b, &i); err == nil {
 | 
			
		||||
			dockerBasePath = i.DockerRootDir
 | 
			
		||||
			experimentalDaemon = i.ExperimentalBuild
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	volumesConfigPath = dockerBasePath + "/volumes"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,7 +9,6 @@ import (
 | 
			
		|||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/docker/docker/utils"
 | 
			
		||||
	"github.com/go-check/check"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -31,11 +30,11 @@ var (
 | 
			
		|||
		"Test requires a Linux daemon",
 | 
			
		||||
	}
 | 
			
		||||
	ExperimentalDaemon = testRequirement{
 | 
			
		||||
		func() bool { return utils.ExperimentalBuild() },
 | 
			
		||||
		func() bool { return experimentalDaemon },
 | 
			
		||||
		"Test requires an experimental daemon",
 | 
			
		||||
	}
 | 
			
		||||
	NotExperimentalDaemon = testRequirement{
 | 
			
		||||
		func() bool { return !utils.ExperimentalBuild() },
 | 
			
		||||
		func() bool { return !experimentalDaemon },
 | 
			
		||||
		"Test requires a non experimental daemon",
 | 
			
		||||
	}
 | 
			
		||||
	IsAmd64 = testRequirement{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,6 +27,7 @@ dockerd - Enable daemon mode
 | 
			
		|||
[**--dns-search**[=*[]*]]
 | 
			
		||||
[**--exec-opt**[=*[]*]]
 | 
			
		||||
[**--exec-root**[=*/var/run/docker*]]
 | 
			
		||||
[**--experimental**[=*false*]]
 | 
			
		||||
[**--fixed-cidr**[=*FIXED-CIDR*]]
 | 
			
		||||
[**--fixed-cidr-v6**[=*FIXED-CIDR-V6*]]
 | 
			
		||||
[**-G**|**--group**[=*docker*]]
 | 
			
		||||
| 
						 | 
				
			
			@ -146,6 +147,9 @@ format.
 | 
			
		|||
**--exec-root**=""
 | 
			
		||||
  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**=""
 | 
			
		||||
  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)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
// +build experimental
 | 
			
		||||
 | 
			
		||||
package plugin
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
Some files were not shown because too many files have changed in this diff Show more
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue