Browse Source

Merge pull request #32190 from vieux/cherry-picks-17.04-rc2

cherry picks 17.04.0-rc2
Victor Vieux 8 năm trước cách đây
mục cha
commit
d408b829fb

+ 3 - 0
Makefile

@@ -141,6 +141,9 @@ run: build ## run the docker daemon in a container
 shell: build ## start a shell inside the build env
 	$(DOCKER_RUN_DOCKER) bash
 
+yaml-docs-gen: build ## generate documentation YAML files consumed by docs repo
+	$(DOCKER_RUN_DOCKER) sh -c 'hack/make.sh yaml-docs-generator && ( cd bundles/latest/yaml-docs-generator; mkdir docs; ./yaml-docs-generator --target $$(pwd)/docs )'
+
 test: build ## run the unit, integration and docker-py tests
 	$(DOCKER_RUN_DOCKER) hack/make.sh dynbinary cross test-unit test-integration-cli test-docker-py
 

+ 2 - 2
api/server/router/image/image_routes.go

@@ -253,9 +253,9 @@ func (s *imageRouter) getImagesJSON(ctx context.Context, w http.ResponseWriter,
 		return err
 	}
 
-	version := httputils.VersionFromContext(ctx)
 	filterParam := r.Form.Get("filter")
-	if versions.LessThanOrEqualTo(version, "1.28") && filterParam != "" {
+	// FIXME(vdemeester) This has been deprecated in 1.13, and is target for removal for v17.12
+	if filterParam != "" {
 		imageFilters.Add("reference", filterParam)
 	}
 

+ 4 - 4
api/swagger.yaml

@@ -486,10 +486,10 @@ definitions:
         description: |
           The test to perform. Possible values are:
 
-          - `{}` inherit healthcheck from image or parent image
-          - `{"NONE"}` disable healthcheck
-          - `{"CMD", args...}` exec arguments directly
-          - `{"CMD-SHELL", command}` run command with system's default shell
+          - `[]` inherit healthcheck from image or parent image
+          - `["NONE"]` disable healthcheck
+          - `["CMD", args...]` exec arguments directly
+          - `["CMD-SHELL", command]` run command with system's default shell
         type: "array"
         items:
           type: "string"

+ 1 - 0
cli/command/image/build.go

@@ -305,6 +305,7 @@ func runBuild(dockerCli *command.DockerCli, options buildOptions) error {
 			}
 			return cli.StatusError{Status: jerr.Message, StatusCode: jerr.Code}
 		}
+		return err
 	}
 
 	// Windows: show error message about modified file permissions if the

+ 5 - 0
cli/command/registry/login.go

@@ -35,9 +35,14 @@ func NewLoginCommand(dockerCli *command.DockerCli) *cobra.Command {
 	}
 
 	flags := cmd.Flags()
+
 	flags.StringVarP(&opts.user, "username", "u", "", "Username")
 	flags.StringVarP(&opts.password, "password", "p", "", "Password")
 
+	// Deprecated in 1.11: Should be removed in docker 17.06
+	flags.StringVarP(&opts.email, "email", "e", "", "Email")
+	flags.MarkDeprecated("email", "will be removed in 17.06.")
+
 	return cmd
 }
 

+ 1 - 1
cli/command/stack/deploy_bundlefile.go

@@ -46,7 +46,7 @@ func deployBundle(ctx context.Context, dockerCli *command.DockerCli, opts deploy
 		for _, networkName := range service.Networks {
 			nets = append(nets, swarm.NetworkAttachmentConfig{
 				Target:  namespace.Scope(networkName),
-				Aliases: []string{networkName},
+				Aliases: []string{internalName},
 			})
 		}
 

+ 1 - 1
cmd/docker/daemon_unix.go

@@ -24,7 +24,7 @@ func newDaemonCommand() *cobra.Command {
 		RunE: func(cmd *cobra.Command, args []string) error {
 			return runDaemon()
 		},
-		Deprecated: "and will be removed in Docker 1.16. Please run `dockerd` directly.",
+		Deprecated: "and will be removed in Docker 17.12. Please run `dockerd` directly.",
 	}
 	cmd.SetHelpFunc(helpFunc)
 	return cmd

+ 1 - 0
contrib/completion/zsh/_docker

@@ -978,6 +978,7 @@ __docker_image_subcommand() {
         (build)
             _arguments $(__docker_arguments) \
                 $opts_help \
+                "($help)*--add-host=[Add a custom host-to-IP mapping]:host\:ip mapping: " \
                 "($help)*--build-arg=[Build-time variables]:<varname>=<value>: " \
                 "($help)*--cache-from=[Images to consider as cache sources]: :__docker_complete_repositories_with_tags" \
                 "($help -c --cpu-shares)"{-c=,--cpu-shares=}"[CPU shares (relative weight)]:CPU shares:(0 10 100 200 500 800 1000)" \

+ 6 - 2
daemon/attach.go

@@ -36,7 +36,7 @@ func (daemon *Daemon) ContainerAttach(prefixOrName string, c *backend.ContainerA
 	}
 
 	cfg := stream.AttachConfig{
-		UseStdin:   c.UseStdin && container.Config.OpenStdin,
+		UseStdin:   c.UseStdin,
 		UseStdout:  c.UseStdout,
 		UseStderr:  c.UseStderr,
 		TTY:        container.Config.Tty,
@@ -79,7 +79,7 @@ func (daemon *Daemon) ContainerAttachRaw(prefixOrName string, stdin io.ReadClose
 		return err
 	}
 	cfg := stream.AttachConfig{
-		UseStdin:   stdin != nil && container.Config.OpenStdin,
+		UseStdin:   stdin != nil,
 		UseStdout:  stdout != nil,
 		UseStderr:  stderr != nil,
 		TTY:        container.Config.Tty,
@@ -147,6 +147,10 @@ func (daemon *Daemon) containerAttach(c *container.Container, cfg *stream.Attach
 		cfg.Stdin = r
 	}
 
+	if !c.Config.OpenStdin {
+		cfg.Stdin = nil
+	}
+
 	waitChan := make(chan struct{})
 	if c.Config.StdinOnce && !c.Config.Tty {
 		defer func() {

+ 1 - 34
daemon/daemon_windows.go

@@ -6,7 +6,6 @@ import (
 	"path/filepath"
 	"strings"
 	"syscall"
-	"unsafe"
 
 	"github.com/Microsoft/hcsshim"
 	"github.com/Sirupsen/logrus"
@@ -245,7 +244,7 @@ func checkSystem() error {
 		return fmt.Errorf("Failed to load vmcompute.dll. Ensure that the Containers role is installed.")
 	}
 
-	return waitOOBEComplete()
+	return nil
 }
 
 // configureKernelSecuritySupport configures and validate security support for the kernel
@@ -617,35 +616,3 @@ func (daemon *Daemon) verifyVolumesInfo(container *container.Container) error {
 func (daemon *Daemon) setupSeccompProfile() error {
 	return nil
 }
-
-func waitOOBEComplete() error {
-	kernel32 := windows.NewLazySystemDLL("kernel32.dll")
-	registerWaitUntilOOBECompleted := kernel32.NewProc("RegisterWaitUntilOOBECompleted")
-	unregisterWaitUntilOOBECompleted := kernel32.NewProc("UnregisterWaitUntilOOBECompleted")
-
-	callbackChan := make(chan struct{})
-	callbackFunc := func(uintptr) uintptr {
-		close(callbackChan)
-		return 0
-	}
-	callbackFuncPtr := syscall.NewCallback(callbackFunc)
-
-	var callbackHandle syscall.Handle
-	ret, _, err := registerWaitUntilOOBECompleted.Call(callbackFuncPtr, 0, uintptr(unsafe.Pointer(&callbackHandle)))
-	if ret == 0 {
-		if err == errInvalidState {
-			return nil
-		}
-		return fmt.Errorf("failed to register OOBEComplete callback. Error: %v", err)
-	}
-
-	// Wait for the callback when OOBE is finished
-	<-callbackChan
-
-	ret, _, err = unregisterWaitUntilOOBECompleted.Call(uintptr(callbackHandle))
-	if ret == 0 {
-		return fmt.Errorf("failed to unregister OOBEComplete callback. Error: %v", err)
-	}
-
-	return nil
-}

+ 61 - 0
docs/reference/commandline/container.md

@@ -0,0 +1,61 @@
+
+---
+title: "container"
+description: "The container command description and usage"
+keywords: "container"
+---
+
+<!-- This file is maintained within the docker/docker Github
+     repository at https://github.com/docker/docker/. Make all
+     pull requests against that repo. If you see this file in
+     another repository, consider it read-only there, as it will
+     periodically be overwritten by the definitive file. Pull
+     requests which include edits to this file in other repositories
+     will be rejected.
+-->
+
+# container
+
+```markdown
+Usage:  docker container COMMAND
+
+Manage containers
+
+Options:
+      --help   Print usage
+
+Commands:
+  attach      Attach to a running container
+  commit      Create a new image from a container's changes
+  cp          Copy files/folders between a container and the local filesystem
+  create      Create a new container
+  diff        Inspect changes to files or directories on a container's filesystem
+  exec        Run a command in a running container
+  export      Export a container's filesystem as a tar archive
+  inspect     Display detailed information on one or more containers
+  kill        Kill one or more running containers
+  logs        Fetch the logs of a container
+  ls          List containers
+  pause       Pause all processes within one or more containers
+  port        List port mappings or a specific mapping for the container
+  prune       Remove all stopped containers
+  rename      Rename a container
+  restart     Restart one or more containers
+  rm          Remove one or more containers
+  run         Run a command in a new container
+  start       Start one or more stopped containers
+  stats       Display a live stream of container(s) resource usage statistics
+  stop        Stop one or more running containers
+  top         Display the running processes of a container
+  unpause     Unpause all processes within one or more containers
+  update      Update configuration of one or more containers
+  wait        Block until one or more containers stop, then print their exit codes
+
+Run 'docker container COMMAND --help' for more information on a command.
+
+```
+
+## Description
+
+Manage containers.
+

+ 47 - 0
docs/reference/commandline/image.md

@@ -0,0 +1,47 @@
+
+---
+title: "image"
+description: "The image command description and usage"
+keywords: "image"
+---
+
+<!-- This file is maintained within the docker/docker Github
+     repository at https://github.com/docker/docker/. Make all
+     pull requests against that repo. If you see this file in
+     another repository, consider it read-only there, as it will
+     periodically be overwritten by the definitive file. Pull
+     requests which include edits to this file in other repositories
+     will be rejected.
+-->
+
+# image
+
+```markdown
+Usage:  docker image COMMAND
+
+Manage images
+
+Options:
+      --help   Print usage
+
+Commands:
+  build       Build an image from a Dockerfile
+  history     Show the history of an image
+  import      Import the contents from a tarball to create a filesystem image
+  inspect     Display detailed information on one or more images
+  load        Load an image from a tar archive or STDIN
+  ls          List images
+  prune       Remove unused images
+  pull        Pull an image or a repository from a registry
+  push        Push an image or a repository to a registry
+  rm          Remove one or more images
+  save        Save one or more images to a tar archive (streamed to STDOUT by default)
+  tag         Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
+
+Run 'docker image COMMAND --help' for more information on a command.
+
+```
+
+## Description
+
+Manage images.

+ 1 - 1
docs/reference/commandline/load.md

@@ -26,7 +26,7 @@ Options:
                        The tarball may be compressed with gzip, bzip, or xz
   -q, --quiet          Suppress the load output but still outputs the imported images
 ```
-## Descriptino
+## Description
 
 `docker load` loads a tarred repository from a file or the standard input stream.
 It restores both images and tags.

+ 49 - 0
docs/reference/commandline/network.md

@@ -0,0 +1,49 @@
+---
+title: "network"
+description: "The network command description and usage"
+keywords: "network"
+---
+
+<!-- This file is maintained within the docker/docker Github
+     repository at https://github.com/docker/docker/. Make all
+     pull requests against that repo. If you see this file in
+     another repository, consider it read-only there, as it will
+     periodically be overwritten by the definitive file. Pull
+     requests which include edits to this file in other repositories
+     will be rejected.
+-->
+
+# network
+
+```markdown
+Usage:  docker network COMMAND
+
+Manage networks
+
+Options:
+      --help   Print usage
+
+Commands:
+  connect     Connect a container to a network
+  create      Create a network
+  disconnect  Disconnect a container from a network
+  inspect     Display detailed information on one or more networks
+  ls          List networks
+  prune       Remove all unused networks
+  rm          Remove one or more networks
+
+Run 'docker network COMMAND --help' for more information on a command.
+```
+
+## Description
+
+Manage networks. You can use subcommand to create, list, inspect, remove,
+connect and disconnect networks.
+
+## Related commands
+
+* [network create](network_create.md)
+* [network inspect](network_inspect.md)
+* [network list](network_list.md)
+* [network rm](network_rm.md)
+* [network prune](network_prune.md)

+ 42 - 0
docs/reference/commandline/node.md

@@ -0,0 +1,42 @@
+
+---
+title: "node"
+description: "The node command description and usage"
+keywords: "node"
+---
+
+<!-- This file is maintained within the docker/docker Github
+     repository at https://github.com/docker/docker/. Make all
+     pull requests against that repo. If you see this file in
+     another repository, consider it read-only there, as it will
+     periodically be overwritten by the definitive file. Pull
+     requests which include edits to this file in other repositories
+     will be rejected.
+-->
+
+# node
+
+```markdown
+Usage:  docker node COMMAND
+
+Manage Swarm nodes
+
+Options:
+      --help   Print usage
+
+Commands:
+  demote      Demote one or more nodes from manager in the swarm
+  inspect     Display detailed information on one or more nodes
+  ls          List nodes in the swarm
+  promote     Promote one or more nodes to manager in the swarm
+  ps          List tasks running on one or more nodes, defaults to current node
+  rm          Remove one or more nodes from the swarm
+  update      Update a node
+
+Run 'docker node COMMAND --help' for more information on a command.
+```
+
+## Description
+
+Manage nodes.
+

+ 44 - 0
docs/reference/commandline/plugin.md

@@ -0,0 +1,44 @@
+---
+title: "plugin"
+description: "The plugin command description and usage"
+keywords: "plugin"
+---
+
+<!-- This file is maintained within the docker/docker Github
+     repository at https://github.com/docker/docker/. Make all
+     pull requests against that repo. If you see this file in
+     another repository, consider it read-only there, as it will
+     periodically be overwritten by the definitive file. Pull
+     requests which include edits to this file in other repositories
+     will be rejected.
+-->
+
+# plugin
+
+```markdown
+Usage:  docker plugin COMMAND
+
+Manage plugins
+
+Options:
+      --help   Print usage
+
+Commands:
+  create      Create a plugin from a rootfs and configuration. Plugin data directory must contain config.json and rootfs directory.
+  disable     Disable a plugin
+  enable      Enable a plugin
+  inspect     Display detailed information on one or more plugins
+  install     Install a plugin
+  ls          List plugins
+  push        Push a plugin to a registry
+  rm          Remove one or more plugins
+  set         Change settings for a plugin
+  upgrade     Upgrade an existing plugin
+
+Run 'docker plugin COMMAND --help' for more information on a command.
+
+```
+
+## Description
+
+Manage plugins.

+ 45 - 0
docs/reference/commandline/secret.md

@@ -0,0 +1,45 @@
+---
+title: "secret"
+description: "The secret command description and usage"
+keywords: "secret"
+---
+
+<!-- This file is maintained within the docker/docker Github
+     repository at https://github.com/docker/docker/. Make all
+     pull requests against that repo. If you see this file in
+     another repository, consider it read-only there, as it will
+     periodically be overwritten by the definitive file. Pull
+     requests which include edits to this file in other repositories
+     will be rejected.
+-->
+
+# secret
+
+```markdown
+Usage:  docker secret COMMAND
+
+Manage Docker secrets
+
+Options:
+      --help   Print usage
+
+Commands:
+  create      Create a secret from a file or STDIN as content
+  inspect     Display detailed information on one or more secrets
+  ls          List secrets
+  rm          Remove one or more secrets
+
+Run 'docker secret COMMAND --help' for more information on a command.
+
+```
+
+## Description
+
+Manage secrets.
+
+## Related commands
+
+* [secret create](secret_create.md)
+* [secret inspect](secret_inspect.md)
+* [secret list](secret_list.md)
+* [secret rm](secret_rm.md)

+ 42 - 0
docs/reference/commandline/service.md

@@ -0,0 +1,42 @@
+---
+title: "service"
+description: "The service command description and usage"
+keywords: "service"
+---
+
+<!-- This file is maintained within the docker/docker Github
+     repository at https://github.com/docker/docker/. Make all
+     pull requests against that repo. If you see this file in
+     another repository, consider it read-only there, as it will
+     periodically be overwritten by the definitive file. Pull
+     requests which include edits to this file in other repositories
+     will be rejected.
+-->
+
+# service
+
+```markdown
+Usage:  docker service COMMAND
+
+Manage services
+
+Options:
+      --help   Print usage
+
+Commands:
+  create      Create a new service
+  inspect     Display detailed information on one or more services
+  logs        Fetch the logs of a service
+  ls          List services
+  ps          List the tasks of a service
+  rm          Remove one or more services
+  scale       Scale one or multiple replicated services
+  update      Update a service
+
+Run 'docker service COMMAND --help' for more information on a command.
+```
+
+## Description
+
+Manage services.
+

+ 39 - 0
docs/reference/commandline/stack.md

@@ -0,0 +1,39 @@
+---
+title: "stack"
+description: "The stack command description and usage"
+keywords: "stack"
+---
+
+<!-- This file is maintained within the docker/docker Github
+     repository at https://github.com/docker/docker/. Make all
+     pull requests against that repo. If you see this file in
+     another repository, consider it read-only there, as it will
+     periodically be overwritten by the definitive file. Pull
+     requests which include edits to this file in other repositories
+     will be rejected.
+-->
+
+# stack
+
+```markdown
+Usage:  docker stack COMMAND
+
+Manage Docker stacks
+
+Options:
+      --help   Print usage
+
+Commands:
+  deploy      Deploy a new stack or update an existing stack
+  ls          List stacks
+  ps          List the tasks in the stack
+  rm          Remove the stack
+  services    List the services in the stack
+
+Run 'docker stack COMMAND --help' for more information on a command.
+```
+
+## Description
+
+Manage stacks.
+

+ 1 - 1
docs/reference/commandline/stack_ls.md

@@ -27,7 +27,7 @@ Options:
       --help   Print usage
 ```
 
-## Descriptino
+## Description
 
 Lists the stacks.
 

+ 40 - 0
docs/reference/commandline/swarm.md

@@ -0,0 +1,40 @@
+---
+title: "swarm"
+description: "The swarm command description and usage"
+keywords: "swarm"
+---
+
+<!-- This file is maintained within the docker/docker Github
+     repository at https://github.com/docker/docker/. Make all
+     pull requests against that repo. If you see this file in
+     another repository, consider it read-only there, as it will
+     periodically be overwritten by the definitive file. Pull
+     requests which include edits to this file in other repositories
+     will be rejected.
+-->
+
+# swarm
+
+```markdown
+Usage:  docker swarm COMMAND
+
+Manage Swarm
+
+Options:
+      --help   Print usage
+
+Commands:
+  init        Initialize a swarm
+  join        Join a swarm as a node and/or manager
+  join-token  Manage join tokens
+  leave       Leave the swarm
+  unlock      Unlock swarm
+  unlock-key  Manage the unlock key
+  update      Update the swarm
+
+Run 'docker swarm COMMAND --help' for more information on a command.
+```
+
+## Description
+
+Manage the swarm.

+ 37 - 0
docs/reference/commandline/system.md

@@ -0,0 +1,37 @@
+---
+title: "system"
+description: "The system command description and usage"
+keywords: "system"
+---
+
+<!-- This file is maintained within the docker/docker Github
+     repository at https://github.com/docker/docker/. Make all
+     pull requests against that repo. If you see this file in
+     another repository, consider it read-only there, as it will
+     periodically be overwritten by the definitive file. Pull
+     requests which include edits to this file in other repositories
+     will be rejected.
+-->
+
+# system
+
+```markdown
+Usage:  docker system COMMAND
+
+Manage Docker
+
+Options:
+      --help   Print usage
+
+Commands:
+  df          Show docker disk usage
+  events      Get real time events from the server
+  info        Display system-wide information
+  prune       Remove unused data
+
+Run 'docker system COMMAND --help' for more information on a command.
+```
+
+## Description
+
+Manage docker.

+ 48 - 0
docs/reference/commandline/volume.md

@@ -0,0 +1,48 @@
+---
+title: "volume"
+description: "The volume command description and usage"
+keywords: "volume"
+---
+
+<!-- This file is maintained within the docker/docker Github
+     repository at https://github.com/docker/docker/. Make all
+     pull requests against that repo. If you see this file in
+     another repository, consider it read-only there, as it will
+     periodically be overwritten by the definitive file. Pull
+     requests which include edits to this file in other repositories
+     will be rejected.
+-->
+
+# volume
+
+```markdown
+Usage:  docker volume COMMAND
+
+Manage volumes
+
+Options:
+      --help   Print usage
+
+Commands:
+  create      Create a volume
+  inspect     Display detailed information on one or more volumes
+  ls          List volumes
+  prune       Remove all unused volumes
+  rm          Remove one or more volumes
+
+Run 'docker volume COMMAND --help' for more information on a command.
+```
+
+## Description
+
+Manage volumes. You can use subcommand to create, list, inspect, remove
+volumes.
+
+## Related commands
+
+* [volume create](volume_create.md)
+* [volume inspect](volume_inspect.md)
+* [volume list](volume_list.md)
+* [volume rm](volume_rm.md)
+* [volume prune](volume_prune.md)
+* [Understand Data Volumes](https://docs.docker.com/engine/tutorials/dockervolumes/)

+ 4 - 0
docs/yaml/Dockerfile

@@ -0,0 +1,4 @@
+FROM scratch
+COPY docs /docs
+# CMD cannot be nil so we set it to empty string
+CMD  [""]

+ 86 - 0
docs/yaml/generate.go

@@ -0,0 +1,86 @@
+package main
+
+import (
+	"fmt"
+	"io/ioutil"
+	"log"
+	"os"
+	"path/filepath"
+	"strings"
+
+	"github.com/docker/docker/cli/command"
+	"github.com/docker/docker/cli/command/commands"
+	"github.com/docker/docker/pkg/term"
+	"github.com/spf13/cobra"
+	"github.com/spf13/pflag"
+)
+
+const descriptionSourcePath = "docs/reference/commandline/"
+
+func generateCliYaml(opts *options) error {
+	stdin, stdout, stderr := term.StdStreams()
+	dockerCli := command.NewDockerCli(stdin, stdout, stderr)
+	cmd := &cobra.Command{Use: "docker"}
+	commands.AddCommands(cmd, dockerCli)
+	source := filepath.Join(opts.source, descriptionSourcePath)
+	if err := loadLongDescription(cmd, source); err != nil {
+		return err
+	}
+
+	cmd.DisableAutoGenTag = true
+	return GenYamlTree(cmd, opts.target)
+}
+
+func loadLongDescription(cmd *cobra.Command, path ...string) error {
+	for _, cmd := range cmd.Commands() {
+		if cmd.Name() == "" {
+			continue
+		}
+		fullpath := filepath.Join(path[0], strings.Join(append(path[1:], cmd.Name()), "_")+".md")
+
+		if cmd.HasSubCommands() {
+			loadLongDescription(cmd, path[0], cmd.Name())
+		}
+
+		if _, err := os.Stat(fullpath); err != nil {
+			log.Printf("WARN: %s does not exist, skipping\n", fullpath)
+			continue
+		}
+
+		content, err := ioutil.ReadFile(fullpath)
+		if err != nil {
+			return err
+		}
+		description, examples := parseMDContent(string(content))
+		cmd.Long = description
+		cmd.Example = examples
+	}
+	return nil
+}
+
+type options struct {
+	source string
+	target string
+}
+
+func parseArgs() (*options, error) {
+	opts := &options{}
+	cwd, _ := os.Getwd()
+	flags := pflag.NewFlagSet(os.Args[0], pflag.ContinueOnError)
+	flags.StringVar(&opts.source, "root", cwd, "Path to project root")
+	flags.StringVar(&opts.target, "target", "/tmp", "Target path for generated yaml files")
+	err := flags.Parse(os.Args[1:])
+	return opts, err
+}
+
+func main() {
+	opts, err := parseArgs()
+	if err != nil {
+		fmt.Fprintln(os.Stderr, err.Error())
+	}
+	fmt.Printf("Project root: %s\n", opts.source)
+	fmt.Printf("Generating yaml files into %s\n", opts.target)
+	if err := generateCliYaml(opts); err != nil {
+		fmt.Fprintf(os.Stderr, "Failed to generate yaml files: %s\n", err.Error())
+	}
+}

+ 212 - 0
docs/yaml/yaml.go

@@ -0,0 +1,212 @@
+package main
+
+import (
+	"fmt"
+	"io"
+	"os"
+	"path/filepath"
+	"sort"
+	"strings"
+
+	"github.com/spf13/cobra"
+	"github.com/spf13/pflag"
+	"gopkg.in/yaml.v2"
+)
+
+type cmdOption struct {
+	Option       string
+	Shorthand    string `yaml:",omitempty"`
+	DefaultValue string `yaml:"default_value,omitempty"`
+	Description  string `yaml:",omitempty"`
+}
+
+type cmdDoc struct {
+	Name             string      `yaml:"command"`
+	SeeAlso          []string    `yaml:"parent,omitempty"`
+	Version          string      `yaml:"engine_version,omitempty"`
+	Aliases          string      `yaml:",omitempty"`
+	Short            string      `yaml:",omitempty"`
+	Long             string      `yaml:",omitempty"`
+	Usage            string      `yaml:",omitempty"`
+	Pname            string      `yaml:",omitempty"`
+	Plink            string      `yaml:",omitempty"`
+	Cname            []string    `yaml:",omitempty"`
+	Clink            []string    `yaml:",omitempty"`
+	Options          []cmdOption `yaml:",omitempty"`
+	InheritedOptions []cmdOption `yaml:"inherited_options,omitempty"`
+	Example          string      `yaml:"examples,omitempty"`
+}
+
+// GenYamlTree creates yaml structured ref files
+func GenYamlTree(cmd *cobra.Command, dir string) error {
+	identity := func(s string) string { return s }
+	emptyStr := func(s string) string { return "" }
+	return GenYamlTreeCustom(cmd, dir, emptyStr, identity)
+}
+
+// GenYamlTreeCustom creates yaml structured ref files
+func GenYamlTreeCustom(cmd *cobra.Command, dir string, filePrepender, linkHandler func(string) string) error {
+	for _, c := range cmd.Commands() {
+		if !c.IsAvailableCommand() || c.IsHelpCommand() {
+			continue
+		}
+		if err := GenYamlTreeCustom(c, dir, filePrepender, linkHandler); err != nil {
+			return err
+		}
+	}
+
+	basename := strings.Replace(cmd.CommandPath(), " ", "_", -1) + ".yaml"
+	filename := filepath.Join(dir, basename)
+	f, err := os.Create(filename)
+	if err != nil {
+		return err
+	}
+	defer f.Close()
+
+	if _, err := io.WriteString(f, filePrepender(filename)); err != nil {
+		return err
+	}
+	if err := GenYamlCustom(cmd, f, linkHandler); err != nil {
+		return err
+	}
+	return nil
+}
+
+// GenYamlCustom creates custom yaml output
+func GenYamlCustom(cmd *cobra.Command, w io.Writer, linkHandler func(string) string) error {
+	cliDoc := cmdDoc{}
+	cliDoc.Name = cmd.CommandPath()
+
+	// Check experimental: ok := cmd.Tags["experimental"]
+
+	cliDoc.Aliases = strings.Join(cmd.Aliases, ", ")
+	cliDoc.Short = cmd.Short
+	cliDoc.Long = cmd.Long
+	if len(cliDoc.Long) == 0 {
+		cliDoc.Long = cliDoc.Short
+	}
+
+	if cmd.Runnable() {
+		cliDoc.Usage = cmd.UseLine()
+	}
+
+	if len(cmd.Example) > 0 {
+		cliDoc.Example = cmd.Example
+	}
+
+	flags := cmd.NonInheritedFlags()
+	if flags.HasFlags() {
+		cliDoc.Options = genFlagResult(flags)
+	}
+	flags = cmd.InheritedFlags()
+	if flags.HasFlags() {
+		cliDoc.InheritedOptions = genFlagResult(flags)
+	}
+
+	if hasSeeAlso(cmd) {
+		if cmd.HasParent() {
+			parent := cmd.Parent()
+			cliDoc.Pname = parent.CommandPath()
+			link := cliDoc.Pname + ".yaml"
+			cliDoc.Plink = strings.Replace(link, " ", "_", -1)
+			cmd.VisitParents(func(c *cobra.Command) {
+				if c.DisableAutoGenTag {
+					cmd.DisableAutoGenTag = c.DisableAutoGenTag
+				}
+			})
+		}
+
+		children := cmd.Commands()
+		sort.Sort(byName(children))
+
+		for _, child := range children {
+			if !child.IsAvailableCommand() || child.IsHelpCommand() {
+				continue
+			}
+			currentChild := cliDoc.Name + " " + child.Name()
+			cliDoc.Cname = append(cliDoc.Cname, cliDoc.Name+" "+child.Name())
+			link := currentChild + ".yaml"
+			cliDoc.Clink = append(cliDoc.Clink, strings.Replace(link, " ", "_", -1))
+		}
+	}
+
+	final, err := yaml.Marshal(&cliDoc)
+	if err != nil {
+		fmt.Println(err)
+		os.Exit(1)
+	}
+	if _, err := fmt.Fprintln(w, string(final)); err != nil {
+		return err
+	}
+	return nil
+}
+
+func genFlagResult(flags *pflag.FlagSet) []cmdOption {
+	var result []cmdOption
+
+	flags.VisitAll(func(flag *pflag.Flag) {
+		// Todo, when we mark a shorthand is deprecated, but specify an empty message.
+		// The flag.ShorthandDeprecated is empty as the shorthand is deprecated.
+		// Using len(flag.ShorthandDeprecated) > 0 can't handle this, others are ok.
+		if !(len(flag.ShorthandDeprecated) > 0) && len(flag.Shorthand) > 0 {
+			opt := cmdOption{
+				Option:       flag.Name,
+				Shorthand:    flag.Shorthand,
+				DefaultValue: flag.DefValue,
+				Description:  forceMultiLine(flag.Usage),
+			}
+			result = append(result, opt)
+		} else {
+			opt := cmdOption{
+				Option:       flag.Name,
+				DefaultValue: forceMultiLine(flag.DefValue),
+				Description:  forceMultiLine(flag.Usage),
+			}
+			result = append(result, opt)
+		}
+	})
+
+	return result
+}
+
+// Temporary workaround for yaml lib generating incorrect yaml with long strings
+// that do not contain \n.
+func forceMultiLine(s string) string {
+	if len(s) > 60 && !strings.Contains(s, "\n") {
+		s = s + "\n"
+	}
+	return s
+}
+
+// Small duplication for cobra utils
+func hasSeeAlso(cmd *cobra.Command) bool {
+	if cmd.HasParent() {
+		return true
+	}
+	for _, c := range cmd.Commands() {
+		if !c.IsAvailableCommand() || c.IsHelpCommand() {
+			continue
+		}
+		return true
+	}
+	return false
+}
+
+func parseMDContent(mdString string) (description string, examples string) {
+	parsedContent := strings.Split(mdString, "\n## ")
+	for _, s := range parsedContent {
+		if strings.Index(s, "Description") == 0 {
+			description = strings.Trim(s, "Description\n")
+		}
+		if strings.Index(s, "Examples") == 0 {
+			examples = strings.Trim(s, "Examples\n")
+		}
+	}
+	return
+}
+
+type byName []*cobra.Command
+
+func (s byName) Len() int           { return len(s) }
+func (s byName) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
+func (s byName) Less(i, j int) bool { return s[i].Name() < s[j].Name() }

+ 12 - 0
hack/make/yaml-docs-generator

@@ -0,0 +1,12 @@
+#!/usr/bin/env bash
+set -e
+
+[ -z "$KEEPDEST" ] && \
+	rm -rf "$DEST"
+
+(
+	source "${MAKEDIR}/.binary-setup"
+	export BINARY_SHORT_NAME="yaml-docs-generator"
+	export GO_PACKAGE='github.com/docker/docker/docs/yaml'
+	source "${MAKEDIR}/.binary"
+)

+ 19 - 0
hooks/post_build

@@ -0,0 +1,19 @@
+#!/bin/bash
+
+if [ -n "${BUILD_DOCS}" ]; then
+	set -e
+	DOCS_IMAGE=${DOCS_IMAGE:-${IMAGE_NAME}-docs}
+	docker run \
+		--entrypoint '' \
+		--privileged \
+		-e DOCKER_GITCOMMIT=$(git rev-parse --short HEAD) \
+		-v $(pwd)/docs/yaml/docs:/docs \
+		"${IMAGE_NAME}" \
+		sh -c 'hack/make.sh yaml-docs-generator && bundles/latest/yaml-docs-generator/yaml-docs-generator --target /docs'
+
+	(
+		cd docs/yaml
+		docker build -t ${DOCS_IMAGE} .
+		docker push ${DOCS_IMAGE}
+	)
+fi

+ 14 - 0
integration-cli/docker_cli_login_test.go

@@ -28,3 +28,17 @@ func (s *DockerRegistryAuthHtpasswdSuite) TestLoginToPrivateRegistry(c *check.C)
 	// now it's fine
 	dockerCmd(c, "login", "-u", s.reg.Username(), "-p", s.reg.Password(), privateRegistryURL)
 }
+
+func (s *DockerRegistryAuthHtpasswdSuite) TestLoginToPrivateRegistryDeprecatedEmailFlag(c *check.C) {
+	// Test to make sure login still works with the deprecated -e and --email flags
+	// wrong credentials
+	out, _, err := dockerCmdWithError("login", "-u", s.reg.Username(), "-p", "WRONGPASSWORD", "-e", s.reg.Email(), privateRegistryURL)
+	c.Assert(err, checker.NotNil, check.Commentf(out))
+	c.Assert(out, checker.Contains, "401 Unauthorized")
+
+	// now it's fine
+	// -e flag
+	dockerCmd(c, "login", "-u", s.reg.Username(), "-p", s.reg.Password(), "-e", s.reg.Email(), privateRegistryURL)
+	// --email flag
+	dockerCmd(c, "login", "-u", s.reg.Username(), "-p", s.reg.Password(), "--email", s.reg.Email(), privateRegistryURL)
+}

+ 1 - 1
integration-cli/docker_cli_registry_user_agent_test.go

@@ -107,7 +107,7 @@ func (s *DockerRegistrySuite) TestUserAgentPassThrough(c *check.C) {
 	s.d.Cmd("build", "--file", dockerfileName, ".")
 	regexpCheckUA(c, buildUA)
 
-	s.d.Cmd("login", "-u", "richard", "-p", "testtest", loginReg.URL())
+	s.d.Cmd("login", "-u", "richard", "-p", "testtest", "-e", "testuser@testdomain.com", loginReg.URL())
 	regexpCheckUA(c, loginUA)
 
 	s.d.Cmd("pull", pullRepoName)

+ 5 - 0
integration-cli/registry/registry.go

@@ -203,6 +203,11 @@ func (r *V2) Password() string {
 	return r.password
 }
 
+// Email returns the configured email of the server
+func (r *V2) Email() string {
+	return r.email
+}
+
 // Path returns the path where the registry write data
 func (r *V2) Path() string {
 	return filepath.Join(r.dir, "docker", "registry", "v2")