Browse code

Make dockerd debuggable

Signed-off-by: John Howard <jhoward@microsoft.com>

John Howard authored on 2016/04/24 10:31:57
Showing 47 changed files
... ...
@@ -12,7 +12,8 @@
12 12
 .gopath/
13 13
 autogen/
14 14
 bundles/
15
-docker/docker
15
+cmd/dockerd/dockerd
16
+cmd/docker/docker
16 17
 dockerversion/version_autogen.go
17 18
 docs/AWS_S3_BUCKET
18 19
 docs/GITCOMMIT
19 20
deleted file mode 100644
... ...
@@ -1,38 +0,0 @@
1
-package main
2
-
3
-import (
4
-	"path/filepath"
5
-
6
-	"github.com/docker/docker/cli"
7
-	cliflags "github.com/docker/docker/cli/flags"
8
-	"github.com/docker/docker/cliconfig"
9
-	flag "github.com/docker/docker/pkg/mflag"
10
-	"github.com/docker/docker/utils"
11
-)
12
-
13
-var (
14
-	commonFlags = cliflags.InitCommonFlags()
15
-	clientFlags = &cli.ClientFlags{FlagSet: new(flag.FlagSet), Common: commonFlags}
16
-)
17
-
18
-func init() {
19
-
20
-	client := clientFlags.FlagSet
21
-	client.StringVar(&clientFlags.ConfigDir, []string{"-config"}, cliconfig.ConfigDir(), "Location of client config files")
22
-
23
-	clientFlags.PostParse = func() {
24
-		clientFlags.Common.PostParse()
25
-
26
-		if clientFlags.ConfigDir != "" {
27
-			cliconfig.SetConfigDir(clientFlags.ConfigDir)
28
-		}
29
-
30
-		if clientFlags.Common.TrustKey == "" {
31
-			clientFlags.Common.TrustKey = filepath.Join(cliconfig.ConfigDir(), cliflags.DefaultTrustKeyFile)
32
-		}
33
-
34
-		if clientFlags.Common.Debug {
35
-			utils.EnableDebug()
36
-		}
37
-	}
38
-}
39 1
deleted file mode 100644
... ...
@@ -1,23 +0,0 @@
1
-package main
2
-
3
-import (
4
-	"os"
5
-	"testing"
6
-
7
-	"github.com/Sirupsen/logrus"
8
-	"github.com/docker/docker/utils"
9
-)
10
-
11
-func TestClientDebugEnabled(t *testing.T) {
12
-	defer utils.DisableDebug()
13
-
14
-	clientFlags.Common.FlagSet.Parse([]string{"-D"})
15
-	clientFlags.PostParse()
16
-
17
-	if os.Getenv("DEBUG") != "1" {
18
-		t.Fatal("expected debug enabled, got false")
19
-	}
20
-	if logrus.GetLevel() != logrus.DebugLevel {
21
-		t.Fatalf("expected logrus debug level, got %v", logrus.GetLevel())
22
-	}
23
-}
24 1
deleted file mode 100644
... ...
@@ -1,11 +0,0 @@
1
-package main
2
-
3
-const daemonBinary = "dockerd"
4
-
5
-// DaemonProxy acts as a cli.Handler to proxy calls to the daemon binary
6
-type DaemonProxy struct{}
7
-
8
-// NewDaemonProxy returns a new handler
9
-func NewDaemonProxy() DaemonProxy {
10
-	return DaemonProxy{}
11
-}
12 1
deleted file mode 100644
... ...
@@ -1,37 +0,0 @@
1
-// +build !windows
2
-
3
-package main
4
-
5
-import (
6
-	"os"
7
-	"os/exec"
8
-	"syscall"
9
-)
10
-
11
-// CmdDaemon execs dockerd with the same flags
12
-// TODO: add a deprecation warning?
13
-func (p DaemonProxy) CmdDaemon(args ...string) error {
14
-	// Use os.Args[1:] so that "global" args are passed to dockerd
15
-	args = stripDaemonArg(os.Args[1:])
16
-
17
-	// TODO: check dirname args[0] first
18
-	binaryAbsPath, err := exec.LookPath(daemonBinary)
19
-	if err != nil {
20
-		return err
21
-	}
22
-
23
-	return syscall.Exec(
24
-		binaryAbsPath,
25
-		append([]string{daemonBinary}, args...),
26
-		os.Environ())
27
-}
28
-
29
-// stripDaemonArg removes the `daemon` argument from the list
30
-func stripDaemonArg(args []string) []string {
31
-	for i, arg := range args {
32
-		if arg == "daemon" {
33
-			return append(args[:i], args[i+1:]...)
34
-		}
35
-	}
36
-	return args
37
-}
38 1
deleted file mode 100644
... ...
@@ -1,11 +0,0 @@
1
-package main
2
-
3
-import (
4
-	"fmt"
5
-)
6
-
7
-// CmdDaemon reports on an error on windows, because there is no exec
8
-func (p DaemonProxy) CmdDaemon(args ...string) error {
9
-	return fmt.Errorf(
10
-		"`docker daemon` does not exist on windows. Please run `dockerd` directly")
11
-}
12 1
deleted file mode 100644
... ...
@@ -1,18 +0,0 @@
1
-package main
2
-
3
-import (
4
-	"strings"
5
-	"testing"
6
-)
7
-
8
-func TestCmdDaemon(t *testing.T) {
9
-	proxy := NewDaemonProxy()
10
-	err := proxy.CmdDaemon("--help")
11
-	if err == nil {
12
-		t.Fatal("Expected CmdDaemon to fail in Windows.")
13
-	}
14
-
15
-	if !strings.Contains(err.Error(), "Please run `dockerd`") {
16
-		t.Fatalf("Expected an error about running dockerd, got %s", err)
17
-	}
18
-}
19 1
deleted file mode 100644
... ...
@@ -1,77 +0,0 @@
1
-package main
2
-
3
-import (
4
-	"fmt"
5
-	"os"
6
-
7
-	"github.com/Sirupsen/logrus"
8
-	"github.com/docker/docker/api/client"
9
-	"github.com/docker/docker/cli"
10
-	"github.com/docker/docker/dockerversion"
11
-	flag "github.com/docker/docker/pkg/mflag"
12
-	"github.com/docker/docker/pkg/term"
13
-	"github.com/docker/docker/utils"
14
-)
15
-
16
-func main() {
17
-	// Set terminal emulation based on platform as required.
18
-	stdin, stdout, stderr := term.StdStreams()
19
-
20
-	logrus.SetOutput(stderr)
21
-
22
-	flag.Merge(flag.CommandLine, clientFlags.FlagSet, commonFlags.FlagSet)
23
-
24
-	flag.Usage = func() {
25
-		fmt.Fprint(stdout, "Usage: docker [OPTIONS] COMMAND [arg...]\n       docker [ --help | -v | --version ]\n\n")
26
-		fmt.Fprint(stdout, "A self-sufficient runtime for containers.\n\nOptions:\n")
27
-
28
-		flag.CommandLine.SetOutput(stdout)
29
-		flag.PrintDefaults()
30
-
31
-		help := "\nCommands:\n"
32
-
33
-		for _, cmd := range dockerCommands {
34
-			help += fmt.Sprintf("    %-10.10s%s\n", cmd.Name, cmd.Description)
35
-		}
36
-
37
-		help += "\nRun 'docker COMMAND --help' for more information on a command."
38
-		fmt.Fprintf(stdout, "%s\n", help)
39
-	}
40
-
41
-	flag.Parse()
42
-
43
-	if *flVersion {
44
-		showVersion()
45
-		return
46
-	}
47
-
48
-	if *flHelp {
49
-		// if global flag --help is present, regardless of what other options and commands there are,
50
-		// just print the usage.
51
-		flag.Usage()
52
-		return
53
-	}
54
-
55
-	clientCli := client.NewDockerCli(stdin, stdout, stderr, clientFlags)
56
-
57
-	c := cli.New(clientCli, NewDaemonProxy())
58
-	if err := c.Run(flag.Args()...); err != nil {
59
-		if sterr, ok := err.(cli.StatusError); ok {
60
-			if sterr.Status != "" {
61
-				fmt.Fprintln(stderr, sterr.Status)
62
-				os.Exit(1)
63
-			}
64
-			os.Exit(sterr.StatusCode)
65
-		}
66
-		fmt.Fprintln(stderr, err)
67
-		os.Exit(1)
68
-	}
69
-}
70
-
71
-func showVersion() {
72
-	if utils.ExperimentalBuild() {
73
-		fmt.Printf("Docker version %s, build %s, experimental\n", dockerversion.Version, dockerversion.GitCommit)
74
-	} else {
75
-		fmt.Printf("Docker version %s, build %s\n", dockerversion.Version, dockerversion.GitCommit)
76
-	}
77
-}
78 1
deleted file mode 100644
... ...
@@ -1,5 +0,0 @@
1
-package main
2
-
3
-import (
4
-	_ "github.com/docker/docker/autogen/winresources/docker"
5
-)
6 1
deleted file mode 100644
... ...
@@ -1,30 +0,0 @@
1
-package main
2
-
3
-import (
4
-	"sort"
5
-
6
-	"github.com/docker/docker/cli"
7
-	flag "github.com/docker/docker/pkg/mflag"
8
-)
9
-
10
-var (
11
-	flHelp    = flag.Bool([]string{"h", "-help"}, false, "Print usage")
12
-	flVersion = flag.Bool([]string{"v", "-version"}, false, "Print version information and quit")
13
-)
14
-
15
-type byName []cli.Command
16
-
17
-func (a byName) Len() int           { return len(a) }
18
-func (a byName) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
19
-func (a byName) Less(i, j int) bool { return a[i].Name < a[j].Name }
20
-
21
-var dockerCommands []cli.Command
22
-
23
-// TODO(tiborvass): do not show 'daemon' on client-only binaries
24
-
25
-func init() {
26
-	for _, cmd := range cli.DockerCommands {
27
-		dockerCommands = append(dockerCommands, cmd)
28
-	}
29
-	sort.Sort(byName(dockerCommands))
30
-}
31 1
deleted file mode 100644
... ...
@@ -1,13 +0,0 @@
1
-package main
2
-
3
-import (
4
-	"sort"
5
-	"testing"
6
-)
7
-
8
-// Tests if the subcommands of docker are sorted
9
-func TestDockerSubcommandsAreSorted(t *testing.T) {
10
-	if !sort.IsSorted(byName(dockerCommands)) {
11
-		t.Fatal("Docker subcommands are not in sorted order")
12
-	}
13
-}
14 1
new file mode 100644
... ...
@@ -0,0 +1,38 @@
0
+package main
1
+
2
+import (
3
+	"path/filepath"
4
+
5
+	"github.com/docker/docker/cli"
6
+	cliflags "github.com/docker/docker/cli/flags"
7
+	"github.com/docker/docker/cliconfig"
8
+	flag "github.com/docker/docker/pkg/mflag"
9
+	"github.com/docker/docker/utils"
10
+)
11
+
12
+var (
13
+	commonFlags = cliflags.InitCommonFlags()
14
+	clientFlags = &cli.ClientFlags{FlagSet: new(flag.FlagSet), Common: commonFlags}
15
+)
16
+
17
+func init() {
18
+
19
+	client := clientFlags.FlagSet
20
+	client.StringVar(&clientFlags.ConfigDir, []string{"-config"}, cliconfig.ConfigDir(), "Location of client config files")
21
+
22
+	clientFlags.PostParse = func() {
23
+		clientFlags.Common.PostParse()
24
+
25
+		if clientFlags.ConfigDir != "" {
26
+			cliconfig.SetConfigDir(clientFlags.ConfigDir)
27
+		}
28
+
29
+		if clientFlags.Common.TrustKey == "" {
30
+			clientFlags.Common.TrustKey = filepath.Join(cliconfig.ConfigDir(), cliflags.DefaultTrustKeyFile)
31
+		}
32
+
33
+		if clientFlags.Common.Debug {
34
+			utils.EnableDebug()
35
+		}
36
+	}
37
+}
0 38
new file mode 100644
... ...
@@ -0,0 +1,23 @@
0
+package main
1
+
2
+import (
3
+	"os"
4
+	"testing"
5
+
6
+	"github.com/Sirupsen/logrus"
7
+	"github.com/docker/docker/utils"
8
+)
9
+
10
+func TestClientDebugEnabled(t *testing.T) {
11
+	defer utils.DisableDebug()
12
+
13
+	clientFlags.Common.FlagSet.Parse([]string{"-D"})
14
+	clientFlags.PostParse()
15
+
16
+	if os.Getenv("DEBUG") != "1" {
17
+		t.Fatal("expected debug enabled, got false")
18
+	}
19
+	if logrus.GetLevel() != logrus.DebugLevel {
20
+		t.Fatalf("expected logrus debug level, got %v", logrus.GetLevel())
21
+	}
22
+}
0 23
new file mode 100644
... ...
@@ -0,0 +1,11 @@
0
+package main
1
+
2
+const daemonBinary = "dockerd"
3
+
4
+// DaemonProxy acts as a cli.Handler to proxy calls to the daemon binary
5
+type DaemonProxy struct{}
6
+
7
+// NewDaemonProxy returns a new handler
8
+func NewDaemonProxy() DaemonProxy {
9
+	return DaemonProxy{}
10
+}
0 11
new file mode 100644
... ...
@@ -0,0 +1,37 @@
0
+// +build !windows
1
+
2
+package main
3
+
4
+import (
5
+	"os"
6
+	"os/exec"
7
+	"syscall"
8
+)
9
+
10
+// CmdDaemon execs dockerd with the same flags
11
+// TODO: add a deprecation warning?
12
+func (p DaemonProxy) CmdDaemon(args ...string) error {
13
+	// Use os.Args[1:] so that "global" args are passed to dockerd
14
+	args = stripDaemonArg(os.Args[1:])
15
+
16
+	// TODO: check dirname args[0] first
17
+	binaryAbsPath, err := exec.LookPath(daemonBinary)
18
+	if err != nil {
19
+		return err
20
+	}
21
+
22
+	return syscall.Exec(
23
+		binaryAbsPath,
24
+		append([]string{daemonBinary}, args...),
25
+		os.Environ())
26
+}
27
+
28
+// stripDaemonArg removes the `daemon` argument from the list
29
+func stripDaemonArg(args []string) []string {
30
+	for i, arg := range args {
31
+		if arg == "daemon" {
32
+			return append(args[:i], args[i+1:]...)
33
+		}
34
+	}
35
+	return args
36
+}
0 37
new file mode 100644
... ...
@@ -0,0 +1,11 @@
0
+package main
1
+
2
+import (
3
+	"fmt"
4
+)
5
+
6
+// CmdDaemon reports on an error on windows, because there is no exec
7
+func (p DaemonProxy) CmdDaemon(args ...string) error {
8
+	return fmt.Errorf(
9
+		"`docker daemon` does not exist on windows. Please run `dockerd` directly")
10
+}
0 11
new file mode 100644
... ...
@@ -0,0 +1,18 @@
0
+package main
1
+
2
+import (
3
+	"strings"
4
+	"testing"
5
+)
6
+
7
+func TestCmdDaemon(t *testing.T) {
8
+	proxy := NewDaemonProxy()
9
+	err := proxy.CmdDaemon("--help")
10
+	if err == nil {
11
+		t.Fatal("Expected CmdDaemon to fail in Windows.")
12
+	}
13
+
14
+	if !strings.Contains(err.Error(), "Please run `dockerd`") {
15
+		t.Fatalf("Expected an error about running dockerd, got %s", err)
16
+	}
17
+}
0 18
new file mode 100644
... ...
@@ -0,0 +1,77 @@
0
+package main
1
+
2
+import (
3
+	"fmt"
4
+	"os"
5
+
6
+	"github.com/Sirupsen/logrus"
7
+	"github.com/docker/docker/api/client"
8
+	"github.com/docker/docker/cli"
9
+	"github.com/docker/docker/dockerversion"
10
+	flag "github.com/docker/docker/pkg/mflag"
11
+	"github.com/docker/docker/pkg/term"
12
+	"github.com/docker/docker/utils"
13
+)
14
+
15
+func main() {
16
+	// Set terminal emulation based on platform as required.
17
+	stdin, stdout, stderr := term.StdStreams()
18
+
19
+	logrus.SetOutput(stderr)
20
+
21
+	flag.Merge(flag.CommandLine, clientFlags.FlagSet, commonFlags.FlagSet)
22
+
23
+	flag.Usage = func() {
24
+		fmt.Fprint(stdout, "Usage: docker [OPTIONS] COMMAND [arg...]\n       docker [ --help | -v | --version ]\n\n")
25
+		fmt.Fprint(stdout, "A self-sufficient runtime for containers.\n\nOptions:\n")
26
+
27
+		flag.CommandLine.SetOutput(stdout)
28
+		flag.PrintDefaults()
29
+
30
+		help := "\nCommands:\n"
31
+
32
+		for _, cmd := range dockerCommands {
33
+			help += fmt.Sprintf("    %-10.10s%s\n", cmd.Name, cmd.Description)
34
+		}
35
+
36
+		help += "\nRun 'docker COMMAND --help' for more information on a command."
37
+		fmt.Fprintf(stdout, "%s\n", help)
38
+	}
39
+
40
+	flag.Parse()
41
+
42
+	if *flVersion {
43
+		showVersion()
44
+		return
45
+	}
46
+
47
+	if *flHelp {
48
+		// if global flag --help is present, regardless of what other options and commands there are,
49
+		// just print the usage.
50
+		flag.Usage()
51
+		return
52
+	}
53
+
54
+	clientCli := client.NewDockerCli(stdin, stdout, stderr, clientFlags)
55
+
56
+	c := cli.New(clientCli, NewDaemonProxy())
57
+	if err := c.Run(flag.Args()...); err != nil {
58
+		if sterr, ok := err.(cli.StatusError); ok {
59
+			if sterr.Status != "" {
60
+				fmt.Fprintln(stderr, sterr.Status)
61
+				os.Exit(1)
62
+			}
63
+			os.Exit(sterr.StatusCode)
64
+		}
65
+		fmt.Fprintln(stderr, err)
66
+		os.Exit(1)
67
+	}
68
+}
69
+
70
+func showVersion() {
71
+	if utils.ExperimentalBuild() {
72
+		fmt.Printf("Docker version %s, build %s, experimental\n", dockerversion.Version, dockerversion.GitCommit)
73
+	} else {
74
+		fmt.Printf("Docker version %s, build %s\n", dockerversion.Version, dockerversion.GitCommit)
75
+	}
76
+}
0 77
new file mode 100644
... ...
@@ -0,0 +1,5 @@
0
+package main
1
+
2
+import (
3
+	_ "github.com/docker/docker/autogen/winresources/dockerd"
4
+)
0 5
new file mode 100644
... ...
@@ -0,0 +1,30 @@
0
+package main
1
+
2
+import (
3
+	"sort"
4
+
5
+	"github.com/docker/docker/cli"
6
+	flag "github.com/docker/docker/pkg/mflag"
7
+)
8
+
9
+var (
10
+	flHelp    = flag.Bool([]string{"h", "-help"}, false, "Print usage")
11
+	flVersion = flag.Bool([]string{"v", "-version"}, false, "Print version information and quit")
12
+)
13
+
14
+type byName []cli.Command
15
+
16
+func (a byName) Len() int           { return len(a) }
17
+func (a byName) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
18
+func (a byName) Less(i, j int) bool { return a[i].Name < a[j].Name }
19
+
20
+var dockerCommands []cli.Command
21
+
22
+// TODO(tiborvass): do not show 'daemon' on client-only binaries
23
+
24
+func init() {
25
+	for _, cmd := range cli.DockerCommands {
26
+		dockerCommands = append(dockerCommands, cmd)
27
+	}
28
+	sort.Sort(byName(dockerCommands))
29
+}
0 30
new file mode 100644
... ...
@@ -0,0 +1,13 @@
0
+package main
1
+
2
+import (
3
+	"sort"
4
+	"testing"
5
+)
6
+
7
+// Tests if the subcommands of docker are sorted
8
+func TestDockerSubcommandsAreSorted(t *testing.T) {
9
+	if !sort.IsSorted(byName(dockerCommands)) {
10
+		t.Fatal("Docker subcommands are not in sorted order")
11
+	}
12
+}
0 13
new file mode 100644
... ...
@@ -0,0 +1,3 @@
0
+docker.go contains Docker's main function.
1
+
2
+This file provides first line CLI argument parsing and environment variable setting.
0 3
new file mode 100644
... ...
@@ -0,0 +1,424 @@
0
+package main
1
+
2
+import (
3
+	"crypto/tls"
4
+	"fmt"
5
+	"io"
6
+	"os"
7
+	"path/filepath"
8
+	"runtime"
9
+	"strings"
10
+	"time"
11
+
12
+	"github.com/Sirupsen/logrus"
13
+	"github.com/docker/distribution/uuid"
14
+	"github.com/docker/docker/api"
15
+	apiserver "github.com/docker/docker/api/server"
16
+	"github.com/docker/docker/api/server/middleware"
17
+	"github.com/docker/docker/api/server/router"
18
+	"github.com/docker/docker/api/server/router/build"
19
+	"github.com/docker/docker/api/server/router/container"
20
+	"github.com/docker/docker/api/server/router/image"
21
+	"github.com/docker/docker/api/server/router/network"
22
+	systemrouter "github.com/docker/docker/api/server/router/system"
23
+	"github.com/docker/docker/api/server/router/volume"
24
+	"github.com/docker/docker/builder/dockerfile"
25
+	"github.com/docker/docker/cli"
26
+	cliflags "github.com/docker/docker/cli/flags"
27
+	"github.com/docker/docker/cliconfig"
28
+	"github.com/docker/docker/daemon"
29
+	"github.com/docker/docker/daemon/logger"
30
+	"github.com/docker/docker/dockerversion"
31
+	"github.com/docker/docker/libcontainerd"
32
+	"github.com/docker/docker/opts"
33
+	"github.com/docker/docker/pkg/authorization"
34
+	"github.com/docker/docker/pkg/jsonlog"
35
+	"github.com/docker/docker/pkg/listeners"
36
+	flag "github.com/docker/docker/pkg/mflag"
37
+	"github.com/docker/docker/pkg/pidfile"
38
+	"github.com/docker/docker/pkg/signal"
39
+	"github.com/docker/docker/pkg/system"
40
+	"github.com/docker/docker/registry"
41
+	"github.com/docker/docker/runconfig"
42
+	"github.com/docker/docker/utils"
43
+	"github.com/docker/go-connections/tlsconfig"
44
+)
45
+
46
+const (
47
+	daemonConfigFileFlag = "-config-file"
48
+)
49
+
50
+// DaemonCli represents the daemon CLI.
51
+type DaemonCli struct {
52
+	*daemon.Config
53
+	commonFlags *cli.CommonFlags
54
+	configFile  *string
55
+}
56
+
57
+func presentInHelp(usage string) string { return usage }
58
+func absentFromHelp(string) string      { return "" }
59
+
60
+// NewDaemonCli returns a pre-configured daemon CLI
61
+func NewDaemonCli() *DaemonCli {
62
+	// TODO(tiborvass): remove InstallFlags?
63
+	daemonConfig := new(daemon.Config)
64
+	daemonConfig.LogConfig.Config = make(map[string]string)
65
+	daemonConfig.ClusterOpts = make(map[string]string)
66
+
67
+	if runtime.GOOS != "linux" {
68
+		daemonConfig.V2Only = true
69
+	}
70
+
71
+	daemonConfig.InstallFlags(flag.CommandLine, presentInHelp)
72
+	configFile := flag.CommandLine.String([]string{daemonConfigFileFlag}, defaultDaemonConfigFile, "Daemon configuration file")
73
+	flag.CommandLine.Require(flag.Exact, 0)
74
+
75
+	return &DaemonCli{
76
+		Config:      daemonConfig,
77
+		commonFlags: cliflags.InitCommonFlags(),
78
+		configFile:  configFile,
79
+	}
80
+}
81
+
82
+func migrateKey() (err error) {
83
+	// Migrate trust key if exists at ~/.docker/key.json and owned by current user
84
+	oldPath := filepath.Join(cliconfig.ConfigDir(), cliflags.DefaultTrustKeyFile)
85
+	newPath := filepath.Join(getDaemonConfDir(), cliflags.DefaultTrustKeyFile)
86
+	if _, statErr := os.Stat(newPath); os.IsNotExist(statErr) && currentUserIsOwner(oldPath) {
87
+		defer func() {
88
+			// Ensure old path is removed if no error occurred
89
+			if err == nil {
90
+				err = os.Remove(oldPath)
91
+			} else {
92
+				logrus.Warnf("Key migration failed, key file not removed at %s", oldPath)
93
+				os.Remove(newPath)
94
+			}
95
+		}()
96
+
97
+		if err := system.MkdirAll(getDaemonConfDir(), os.FileMode(0644)); err != nil {
98
+			return fmt.Errorf("Unable to create daemon configuration directory: %s", err)
99
+		}
100
+
101
+		newFile, err := os.OpenFile(newPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
102
+		if err != nil {
103
+			return fmt.Errorf("error creating key file %q: %s", newPath, err)
104
+		}
105
+		defer newFile.Close()
106
+
107
+		oldFile, err := os.Open(oldPath)
108
+		if err != nil {
109
+			return fmt.Errorf("error opening key file %q: %s", oldPath, err)
110
+		}
111
+		defer oldFile.Close()
112
+
113
+		if _, err := io.Copy(newFile, oldFile); err != nil {
114
+			return fmt.Errorf("error copying key: %s", err)
115
+		}
116
+
117
+		logrus.Infof("Migrated key from %s to %s", oldPath, newPath)
118
+	}
119
+
120
+	return nil
121
+}
122
+
123
+func (cli *DaemonCli) start() {
124
+	// warn from uuid package when running the daemon
125
+	uuid.Loggerf = logrus.Warnf
126
+
127
+	flags := flag.CommandLine
128
+	cli.commonFlags.PostParse()
129
+
130
+	if cli.commonFlags.TrustKey == "" {
131
+		cli.commonFlags.TrustKey = filepath.Join(getDaemonConfDir(), cliflags.DefaultTrustKeyFile)
132
+	}
133
+	cliConfig, err := loadDaemonCliConfig(cli.Config, flags, cli.commonFlags, *cli.configFile)
134
+	if err != nil {
135
+		fmt.Fprint(os.Stderr, err)
136
+		os.Exit(1)
137
+	}
138
+	cli.Config = cliConfig
139
+
140
+	if cli.Config.Debug {
141
+		utils.EnableDebug()
142
+	}
143
+
144
+	if utils.ExperimentalBuild() {
145
+		logrus.Warn("Running experimental build")
146
+	}
147
+
148
+	logrus.SetFormatter(&logrus.TextFormatter{
149
+		TimestampFormat: jsonlog.RFC3339NanoFixed,
150
+		DisableColors:   cli.Config.RawLogs,
151
+	})
152
+
153
+	if err := setDefaultUmask(); err != nil {
154
+		logrus.Fatalf("Failed to set umask: %v", err)
155
+	}
156
+
157
+	if len(cli.LogConfig.Config) > 0 {
158
+		if err := logger.ValidateLogOpts(cli.LogConfig.Type, cli.LogConfig.Config); err != nil {
159
+			logrus.Fatalf("Failed to set log opts: %v", err)
160
+		}
161
+	}
162
+
163
+	var pfile *pidfile.PIDFile
164
+	if cli.Pidfile != "" {
165
+		pf, err := pidfile.New(cli.Pidfile)
166
+		if err != nil {
167
+			logrus.Fatalf("Error starting daemon: %v", err)
168
+		}
169
+		pfile = pf
170
+		defer func() {
171
+			if err := pfile.Remove(); err != nil {
172
+				logrus.Error(err)
173
+			}
174
+		}()
175
+	}
176
+
177
+	serverConfig := &apiserver.Config{
178
+		Logging:     true,
179
+		SocketGroup: cli.Config.SocketGroup,
180
+		Version:     dockerversion.Version,
181
+		EnableCors:  cli.Config.EnableCors,
182
+		CorsHeaders: cli.Config.CorsHeaders,
183
+	}
184
+
185
+	if cli.Config.TLS {
186
+		tlsOptions := tlsconfig.Options{
187
+			CAFile:   cli.Config.CommonTLSOptions.CAFile,
188
+			CertFile: cli.Config.CommonTLSOptions.CertFile,
189
+			KeyFile:  cli.Config.CommonTLSOptions.KeyFile,
190
+		}
191
+
192
+		if cli.Config.TLSVerify {
193
+			// server requires and verifies client's certificate
194
+			tlsOptions.ClientAuth = tls.RequireAndVerifyClientCert
195
+		}
196
+		tlsConfig, err := tlsconfig.Server(tlsOptions)
197
+		if err != nil {
198
+			logrus.Fatal(err)
199
+		}
200
+		serverConfig.TLSConfig = tlsConfig
201
+	}
202
+
203
+	if len(cli.Config.Hosts) == 0 {
204
+		cli.Config.Hosts = make([]string, 1)
205
+	}
206
+
207
+	api := apiserver.New(serverConfig)
208
+
209
+	for i := 0; i < len(cli.Config.Hosts); i++ {
210
+		var err error
211
+		if cli.Config.Hosts[i], err = opts.ParseHost(cli.Config.TLS, cli.Config.Hosts[i]); err != nil {
212
+			logrus.Fatalf("error parsing -H %s : %v", cli.Config.Hosts[i], err)
213
+		}
214
+
215
+		protoAddr := cli.Config.Hosts[i]
216
+		protoAddrParts := strings.SplitN(protoAddr, "://", 2)
217
+		if len(protoAddrParts) != 2 {
218
+			logrus.Fatalf("bad format %s, expected PROTO://ADDR", protoAddr)
219
+		}
220
+
221
+		proto := protoAddrParts[0]
222
+		addr := protoAddrParts[1]
223
+
224
+		// It's a bad idea to bind to TCP without tlsverify.
225
+		if proto == "tcp" && (serverConfig.TLSConfig == nil || serverConfig.TLSConfig.ClientAuth != tls.RequireAndVerifyClientCert) {
226
+			logrus.Warn("[!] DON'T BIND ON ANY IP ADDRESS WITHOUT setting -tlsverify IF YOU DON'T KNOW WHAT YOU'RE DOING [!]")
227
+		}
228
+		l, err := listeners.Init(proto, addr, serverConfig.SocketGroup, serverConfig.TLSConfig)
229
+		if err != nil {
230
+			logrus.Fatal(err)
231
+		}
232
+		// If we're binding to a TCP port, make sure that a container doesn't try to use it.
233
+		if proto == "tcp" {
234
+			if err := allocateDaemonPort(addr); err != nil {
235
+				logrus.Fatal(err)
236
+			}
237
+		}
238
+		logrus.Debugf("Listener created for HTTP on %s (%s)", protoAddrParts[0], protoAddrParts[1])
239
+		api.Accept(protoAddrParts[1], l...)
240
+	}
241
+
242
+	if err := migrateKey(); err != nil {
243
+		logrus.Fatal(err)
244
+	}
245
+	cli.TrustKeyPath = cli.commonFlags.TrustKey
246
+
247
+	registryService := registry.NewService(cli.Config.ServiceOptions)
248
+	containerdRemote, err := libcontainerd.New(cli.getLibcontainerdRoot(), cli.getPlatformRemoteOptions()...)
249
+	if err != nil {
250
+		logrus.Fatal(err)
251
+	}
252
+
253
+	d, err := daemon.NewDaemon(cli.Config, registryService, containerdRemote)
254
+	if err != nil {
255
+		if pfile != nil {
256
+			if err := pfile.Remove(); err != nil {
257
+				logrus.Error(err)
258
+			}
259
+		}
260
+		logrus.Fatalf("Error starting daemon: %v", err)
261
+	}
262
+
263
+	logrus.Info("Daemon has completed initialization")
264
+
265
+	logrus.WithFields(logrus.Fields{
266
+		"version":     dockerversion.Version,
267
+		"commit":      dockerversion.GitCommit,
268
+		"graphdriver": d.GraphDriverName(),
269
+	}).Info("Docker daemon")
270
+
271
+	cli.initMiddlewares(api, serverConfig)
272
+	initRouter(api, d)
273
+
274
+	reload := func(config *daemon.Config) {
275
+		if err := d.Reload(config); err != nil {
276
+			logrus.Errorf("Error reconfiguring the daemon: %v", err)
277
+			return
278
+		}
279
+		if config.IsValueSet("debug") {
280
+			debugEnabled := utils.IsDebugEnabled()
281
+			switch {
282
+			case debugEnabled && !config.Debug: // disable debug
283
+				utils.DisableDebug()
284
+				api.DisableProfiler()
285
+			case config.Debug && !debugEnabled: // enable debug
286
+				utils.EnableDebug()
287
+				api.EnableProfiler()
288
+			}
289
+
290
+		}
291
+	}
292
+
293
+	setupConfigReloadTrap(*cli.configFile, flags, reload)
294
+
295
+	// The serve API routine never exits unless an error occurs
296
+	// We need to start it as a goroutine and wait on it so
297
+	// daemon doesn't exit
298
+	serveAPIWait := make(chan error)
299
+	go api.Wait(serveAPIWait)
300
+
301
+	signal.Trap(func() {
302
+		api.Close()
303
+		<-serveAPIWait
304
+		shutdownDaemon(d, 15)
305
+		if pfile != nil {
306
+			if err := pfile.Remove(); err != nil {
307
+				logrus.Error(err)
308
+			}
309
+		}
310
+	})
311
+
312
+	// after the daemon is done setting up we can notify systemd api
313
+	notifySystem()
314
+
315
+	// Daemon is fully initialized and handling API traffic
316
+	// Wait for serve API to complete
317
+	errAPI := <-serveAPIWait
318
+	shutdownDaemon(d, 15)
319
+	containerdRemote.Cleanup()
320
+	if errAPI != nil {
321
+		if pfile != nil {
322
+			if err := pfile.Remove(); err != nil {
323
+				logrus.Error(err)
324
+			}
325
+		}
326
+		logrus.Fatalf("Shutting down due to ServeAPI error: %v", errAPI)
327
+	}
328
+}
329
+
330
+// shutdownDaemon just wraps daemon.Shutdown() to handle a timeout in case
331
+// d.Shutdown() is waiting too long to kill container or worst it's
332
+// blocked there
333
+func shutdownDaemon(d *daemon.Daemon, timeout time.Duration) {
334
+	ch := make(chan struct{})
335
+	go func() {
336
+		d.Shutdown()
337
+		close(ch)
338
+	}()
339
+	select {
340
+	case <-ch:
341
+		logrus.Debug("Clean shutdown succeeded")
342
+	case <-time.After(timeout * time.Second):
343
+		logrus.Error("Force shutdown daemon")
344
+	}
345
+}
346
+
347
+func loadDaemonCliConfig(config *daemon.Config, flags *flag.FlagSet, commonConfig *cli.CommonFlags, configFile string) (*daemon.Config, error) {
348
+	config.Debug = commonConfig.Debug
349
+	config.Hosts = commonConfig.Hosts
350
+	config.LogLevel = commonConfig.LogLevel
351
+	config.TLS = commonConfig.TLS
352
+	config.TLSVerify = commonConfig.TLSVerify
353
+	config.CommonTLSOptions = daemon.CommonTLSOptions{}
354
+
355
+	if commonConfig.TLSOptions != nil {
356
+		config.CommonTLSOptions.CAFile = commonConfig.TLSOptions.CAFile
357
+		config.CommonTLSOptions.CertFile = commonConfig.TLSOptions.CertFile
358
+		config.CommonTLSOptions.KeyFile = commonConfig.TLSOptions.KeyFile
359
+	}
360
+
361
+	if configFile != "" {
362
+		c, err := daemon.MergeDaemonConfigurations(config, flags, configFile)
363
+		if err != nil {
364
+			if flags.IsSet(daemonConfigFileFlag) || !os.IsNotExist(err) {
365
+				return nil, fmt.Errorf("unable to configure the Docker daemon with file %s: %v\n", configFile, err)
366
+			}
367
+		}
368
+		// the merged configuration can be nil if the config file didn't exist.
369
+		// leave the current configuration as it is if when that happens.
370
+		if c != nil {
371
+			config = c
372
+		}
373
+	}
374
+
375
+	// Regardless of whether the user sets it to true or false, if they
376
+	// specify TLSVerify at all then we need to turn on TLS
377
+	if config.IsValueSet(cliflags.TLSVerifyKey) {
378
+		config.TLS = true
379
+	}
380
+
381
+	// ensure that the log level is the one set after merging configurations
382
+	cliflags.SetDaemonLogLevel(config.LogLevel)
383
+
384
+	return config, nil
385
+}
386
+
387
+func initRouter(s *apiserver.Server, d *daemon.Daemon) {
388
+	decoder := runconfig.ContainerDecoder{}
389
+
390
+	routers := []router.Router{
391
+		container.NewRouter(d, decoder),
392
+		image.NewRouter(d, decoder),
393
+		systemrouter.NewRouter(d),
394
+		volume.NewRouter(d),
395
+		build.NewRouter(dockerfile.NewBuildManager(d)),
396
+	}
397
+	if d.NetworkControllerEnabled() {
398
+		routers = append(routers, network.NewRouter(d))
399
+	}
400
+
401
+	s.InitRouter(utils.IsDebugEnabled(), routers...)
402
+}
403
+
404
+func (cli *DaemonCli) initMiddlewares(s *apiserver.Server, cfg *apiserver.Config) {
405
+	v := cfg.Version
406
+
407
+	vm := middleware.NewVersionMiddleware(v, api.DefaultVersion, api.MinVersion)
408
+	s.UseMiddleware(vm)
409
+
410
+	if cfg.EnableCors {
411
+		c := middleware.NewCORSMiddleware(cfg.CorsHeaders)
412
+		s.UseMiddleware(c)
413
+	}
414
+
415
+	u := middleware.NewUserAgentMiddleware(v)
416
+	s.UseMiddleware(u)
417
+
418
+	if len(cli.Config.AuthorizationPlugins) > 0 {
419
+		authZPlugins := authorization.NewPlugins(cli.Config.AuthorizationPlugins)
420
+		handleAuthorization := authorization.NewMiddleware(authZPlugins)
421
+		s.UseMiddleware(handleAuthorization)
422
+	}
423
+}
0 424
new file mode 100644
... ...
@@ -0,0 +1,5 @@
0
+package main
1
+
2
+// notifySystem sends a message to the host when the server is ready to be used
3
+func notifySystem() {
4
+}
0 5
new file mode 100644
... ...
@@ -0,0 +1,11 @@
0
+package main
1
+
2
+import (
3
+	systemdDaemon "github.com/coreos/go-systemd/daemon"
4
+)
5
+
6
+// notifySystem sends a message to the host when the server is ready to be used
7
+func notifySystem() {
8
+	// Tell the init daemon we are accepting requests
9
+	go systemdDaemon.SdNotify("READY=1")
10
+}
0 11
new file mode 100644
... ...
@@ -0,0 +1,294 @@
0
+package main
1
+
2
+import (
3
+	"io/ioutil"
4
+	"os"
5
+	"strings"
6
+	"testing"
7
+
8
+	"github.com/Sirupsen/logrus"
9
+	"github.com/docker/docker/cli"
10
+	"github.com/docker/docker/daemon"
11
+	"github.com/docker/docker/opts"
12
+	"github.com/docker/docker/pkg/mflag"
13
+	"github.com/docker/go-connections/tlsconfig"
14
+)
15
+
16
+func TestLoadDaemonCliConfigWithoutOverriding(t *testing.T) {
17
+	c := &daemon.Config{}
18
+	common := &cli.CommonFlags{
19
+		Debug: true,
20
+	}
21
+
22
+	flags := mflag.NewFlagSet("test", mflag.ContinueOnError)
23
+	loadedConfig, err := loadDaemonCliConfig(c, flags, common, "/tmp/fooobarbaz")
24
+	if err != nil {
25
+		t.Fatal(err)
26
+	}
27
+	if loadedConfig == nil {
28
+		t.Fatalf("expected configuration %v, got nil", c)
29
+	}
30
+	if !loadedConfig.Debug {
31
+		t.Fatalf("expected debug to be copied from the common flags, got false")
32
+	}
33
+}
34
+
35
+func TestLoadDaemonCliConfigWithTLS(t *testing.T) {
36
+	c := &daemon.Config{}
37
+	common := &cli.CommonFlags{
38
+		TLS: true,
39
+		TLSOptions: &tlsconfig.Options{
40
+			CAFile: "/tmp/ca.pem",
41
+		},
42
+	}
43
+
44
+	flags := mflag.NewFlagSet("test", mflag.ContinueOnError)
45
+	loadedConfig, err := loadDaemonCliConfig(c, flags, common, "/tmp/fooobarbaz")
46
+	if err != nil {
47
+		t.Fatal(err)
48
+	}
49
+	if loadedConfig == nil {
50
+		t.Fatalf("expected configuration %v, got nil", c)
51
+	}
52
+	if loadedConfig.CommonTLSOptions.CAFile != "/tmp/ca.pem" {
53
+		t.Fatalf("expected /tmp/ca.pem, got %s: %q", loadedConfig.CommonTLSOptions.CAFile, loadedConfig)
54
+	}
55
+}
56
+
57
+func TestLoadDaemonCliConfigWithConflicts(t *testing.T) {
58
+	c := &daemon.Config{}
59
+	common := &cli.CommonFlags{}
60
+	f, err := ioutil.TempFile("", "docker-config-")
61
+	if err != nil {
62
+		t.Fatal(err)
63
+	}
64
+	configFile := f.Name()
65
+	defer os.Remove(configFile)
66
+
67
+	f.Write([]byte(`{"labels": ["l3=foo"]}`))
68
+	f.Close()
69
+
70
+	var labels []string
71
+
72
+	flags := mflag.NewFlagSet("test", mflag.ContinueOnError)
73
+	flags.String([]string{daemonConfigFileFlag}, "", "")
74
+	flags.Var(opts.NewNamedListOptsRef("labels", &labels, opts.ValidateLabel), []string{"-label"}, "")
75
+
76
+	flags.Set(daemonConfigFileFlag, configFile)
77
+	if err := flags.Set("-label", "l1=bar"); err != nil {
78
+		t.Fatal(err)
79
+	}
80
+	if err := flags.Set("-label", "l2=baz"); err != nil {
81
+		t.Fatal(err)
82
+	}
83
+
84
+	_, err = loadDaemonCliConfig(c, flags, common, configFile)
85
+	if err == nil {
86
+		t.Fatalf("expected configuration error, got nil")
87
+	}
88
+	if !strings.Contains(err.Error(), "labels") {
89
+		t.Fatalf("expected labels conflict, got %v", err)
90
+	}
91
+}
92
+
93
+func TestLoadDaemonCliConfigWithTLSVerify(t *testing.T) {
94
+	c := &daemon.Config{}
95
+	common := &cli.CommonFlags{
96
+		TLSOptions: &tlsconfig.Options{
97
+			CAFile: "/tmp/ca.pem",
98
+		},
99
+	}
100
+
101
+	f, err := ioutil.TempFile("", "docker-config-")
102
+	if err != nil {
103
+		t.Fatal(err)
104
+	}
105
+	configFile := f.Name()
106
+	defer os.Remove(configFile)
107
+
108
+	f.Write([]byte(`{"tlsverify": true}`))
109
+	f.Close()
110
+
111
+	flags := mflag.NewFlagSet("test", mflag.ContinueOnError)
112
+	flags.Bool([]string{"-tlsverify"}, false, "")
113
+	loadedConfig, err := loadDaemonCliConfig(c, flags, common, configFile)
114
+	if err != nil {
115
+		t.Fatal(err)
116
+	}
117
+	if loadedConfig == nil {
118
+		t.Fatalf("expected configuration %v, got nil", c)
119
+	}
120
+
121
+	if !loadedConfig.TLS {
122
+		t.Fatalf("expected TLS enabled, got %q", loadedConfig)
123
+	}
124
+}
125
+
126
+func TestLoadDaemonCliConfigWithExplicitTLSVerifyFalse(t *testing.T) {
127
+	c := &daemon.Config{}
128
+	common := &cli.CommonFlags{
129
+		TLSOptions: &tlsconfig.Options{
130
+			CAFile: "/tmp/ca.pem",
131
+		},
132
+	}
133
+
134
+	f, err := ioutil.TempFile("", "docker-config-")
135
+	if err != nil {
136
+		t.Fatal(err)
137
+	}
138
+	configFile := f.Name()
139
+	defer os.Remove(configFile)
140
+
141
+	f.Write([]byte(`{"tlsverify": false}`))
142
+	f.Close()
143
+
144
+	flags := mflag.NewFlagSet("test", mflag.ContinueOnError)
145
+	flags.Bool([]string{"-tlsverify"}, false, "")
146
+	loadedConfig, err := loadDaemonCliConfig(c, flags, common, configFile)
147
+	if err != nil {
148
+		t.Fatal(err)
149
+	}
150
+	if loadedConfig == nil {
151
+		t.Fatalf("expected configuration %v, got nil", c)
152
+	}
153
+
154
+	if !loadedConfig.TLS {
155
+		t.Fatalf("expected TLS enabled, got %q", loadedConfig)
156
+	}
157
+}
158
+
159
+func TestLoadDaemonCliConfigWithoutTLSVerify(t *testing.T) {
160
+	c := &daemon.Config{}
161
+	common := &cli.CommonFlags{
162
+		TLSOptions: &tlsconfig.Options{
163
+			CAFile: "/tmp/ca.pem",
164
+		},
165
+	}
166
+
167
+	f, err := ioutil.TempFile("", "docker-config-")
168
+	if err != nil {
169
+		t.Fatal(err)
170
+	}
171
+	configFile := f.Name()
172
+	defer os.Remove(configFile)
173
+
174
+	f.Write([]byte(`{}`))
175
+	f.Close()
176
+
177
+	flags := mflag.NewFlagSet("test", mflag.ContinueOnError)
178
+	loadedConfig, err := loadDaemonCliConfig(c, flags, common, configFile)
179
+	if err != nil {
180
+		t.Fatal(err)
181
+	}
182
+	if loadedConfig == nil {
183
+		t.Fatalf("expected configuration %v, got nil", c)
184
+	}
185
+
186
+	if loadedConfig.TLS {
187
+		t.Fatalf("expected TLS disabled, got %q", loadedConfig)
188
+	}
189
+}
190
+
191
+func TestLoadDaemonCliConfigWithLogLevel(t *testing.T) {
192
+	c := &daemon.Config{}
193
+	common := &cli.CommonFlags{}
194
+
195
+	f, err := ioutil.TempFile("", "docker-config-")
196
+	if err != nil {
197
+		t.Fatal(err)
198
+	}
199
+	configFile := f.Name()
200
+	defer os.Remove(configFile)
201
+
202
+	f.Write([]byte(`{"log-level": "warn"}`))
203
+	f.Close()
204
+
205
+	flags := mflag.NewFlagSet("test", mflag.ContinueOnError)
206
+	flags.String([]string{"-log-level"}, "", "")
207
+	loadedConfig, err := loadDaemonCliConfig(c, flags, common, configFile)
208
+	if err != nil {
209
+		t.Fatal(err)
210
+	}
211
+	if loadedConfig == nil {
212
+		t.Fatalf("expected configuration %v, got nil", c)
213
+	}
214
+	if loadedConfig.LogLevel != "warn" {
215
+		t.Fatalf("expected warn log level, got %v", loadedConfig.LogLevel)
216
+	}
217
+
218
+	if logrus.GetLevel() != logrus.WarnLevel {
219
+		t.Fatalf("expected warn log level, got %v", logrus.GetLevel())
220
+	}
221
+}
222
+
223
+func TestLoadDaemonConfigWithEmbeddedOptions(t *testing.T) {
224
+	c := &daemon.Config{}
225
+	common := &cli.CommonFlags{}
226
+
227
+	flags := mflag.NewFlagSet("test", mflag.ContinueOnError)
228
+	flags.String([]string{"-tlscacert"}, "", "")
229
+	flags.String([]string{"-log-driver"}, "", "")
230
+
231
+	f, err := ioutil.TempFile("", "docker-config-")
232
+	if err != nil {
233
+		t.Fatal(err)
234
+	}
235
+	configFile := f.Name()
236
+	defer os.Remove(configFile)
237
+
238
+	f.Write([]byte(`{"tlscacert": "/etc/certs/ca.pem", "log-driver": "syslog"}`))
239
+	f.Close()
240
+
241
+	loadedConfig, err := loadDaemonCliConfig(c, flags, common, configFile)
242
+	if err != nil {
243
+		t.Fatal(err)
244
+	}
245
+	if loadedConfig == nil {
246
+		t.Fatal("expected configuration, got nil")
247
+	}
248
+	if loadedConfig.CommonTLSOptions.CAFile != "/etc/certs/ca.pem" {
249
+		t.Fatalf("expected CA file path /etc/certs/ca.pem, got %v", loadedConfig.CommonTLSOptions.CAFile)
250
+	}
251
+	if loadedConfig.LogConfig.Type != "syslog" {
252
+		t.Fatalf("expected LogConfig type syslog, got %v", loadedConfig.LogConfig.Type)
253
+	}
254
+}
255
+
256
+func TestLoadDaemonConfigWithRegistryOptions(t *testing.T) {
257
+	c := &daemon.Config{}
258
+	common := &cli.CommonFlags{}
259
+	flags := mflag.NewFlagSet("test", mflag.ContinueOnError)
260
+	c.ServiceOptions.InstallCliFlags(flags, absentFromHelp)
261
+
262
+	f, err := ioutil.TempFile("", "docker-config-")
263
+	if err != nil {
264
+		t.Fatal(err)
265
+	}
266
+	configFile := f.Name()
267
+	defer os.Remove(configFile)
268
+
269
+	f.Write([]byte(`{"registry-mirrors": ["https://mirrors.docker.com"], "insecure-registries": ["https://insecure.docker.com"], "disable-legacy-registry": true}`))
270
+	f.Close()
271
+
272
+	loadedConfig, err := loadDaemonCliConfig(c, flags, common, configFile)
273
+	if err != nil {
274
+		t.Fatal(err)
275
+	}
276
+	if loadedConfig == nil {
277
+		t.Fatal("expected configuration, got nil")
278
+	}
279
+
280
+	m := loadedConfig.Mirrors
281
+	if len(m) != 1 {
282
+		t.Fatalf("expected 1 mirror, got %d", len(m))
283
+	}
284
+
285
+	r := loadedConfig.InsecureRegistries
286
+	if len(r) != 1 {
287
+		t.Fatalf("expected 1 insecure registries, got %d", len(r))
288
+	}
289
+
290
+	if !loadedConfig.V2Only {
291
+		t.Fatal("expected disable-legacy-registry to be true, got false")
292
+	}
293
+}
0 294
new file mode 100644
... ...
@@ -0,0 +1,113 @@
0
+// +build !windows
1
+
2
+package main
3
+
4
+import (
5
+	"fmt"
6
+	"net"
7
+	"os"
8
+	"os/signal"
9
+	"path/filepath"
10
+	"strconv"
11
+	"syscall"
12
+
13
+	"github.com/Sirupsen/logrus"
14
+	"github.com/docker/docker/daemon"
15
+	"github.com/docker/docker/libcontainerd"
16
+	"github.com/docker/docker/pkg/mflag"
17
+	"github.com/docker/docker/pkg/system"
18
+	"github.com/docker/libnetwork/portallocator"
19
+)
20
+
21
+const defaultDaemonConfigFile = "/etc/docker/daemon.json"
22
+
23
+// currentUserIsOwner checks whether the current user is the owner of the given
24
+// file.
25
+func currentUserIsOwner(f string) bool {
26
+	if fileInfo, err := system.Stat(f); err == nil && fileInfo != nil {
27
+		if int(fileInfo.UID()) == os.Getuid() {
28
+			return true
29
+		}
30
+	}
31
+	return false
32
+}
33
+
34
+// setDefaultUmask sets the umask to 0022 to avoid problems
35
+// caused by custom umask
36
+func setDefaultUmask() error {
37
+	desiredUmask := 0022
38
+	syscall.Umask(desiredUmask)
39
+	if umask := syscall.Umask(desiredUmask); umask != desiredUmask {
40
+		return fmt.Errorf("failed to set umask: expected %#o, got %#o", desiredUmask, umask)
41
+	}
42
+
43
+	return nil
44
+}
45
+
46
+func getDaemonConfDir() string {
47
+	return "/etc/docker"
48
+}
49
+
50
+// setupConfigReloadTrap configures the USR2 signal to reload the configuration.
51
+func setupConfigReloadTrap(configFile string, flags *mflag.FlagSet, reload func(*daemon.Config)) {
52
+	c := make(chan os.Signal, 1)
53
+	signal.Notify(c, syscall.SIGHUP)
54
+	go func() {
55
+		for range c {
56
+			if err := daemon.ReloadConfiguration(configFile, flags, reload); err != nil {
57
+				logrus.Error(err)
58
+			}
59
+		}
60
+	}()
61
+}
62
+
63
+func (cli *DaemonCli) getPlatformRemoteOptions() []libcontainerd.RemoteOption {
64
+	opts := []libcontainerd.RemoteOption{
65
+		libcontainerd.WithDebugLog(cli.Config.Debug),
66
+	}
67
+	if cli.Config.ContainerdAddr != "" {
68
+		opts = append(opts, libcontainerd.WithRemoteAddr(cli.Config.ContainerdAddr))
69
+	} else {
70
+		opts = append(opts, libcontainerd.WithStartDaemon(true))
71
+	}
72
+	if daemon.UsingSystemd(cli.Config) {
73
+		args := []string{"--systemd-cgroup=true"}
74
+		opts = append(opts, libcontainerd.WithRuntimeArgs(args))
75
+	}
76
+	return opts
77
+}
78
+
79
+// getLibcontainerdRoot gets the root directory for libcontainerd/containerd to
80
+// store their state.
81
+func (cli *DaemonCli) getLibcontainerdRoot() string {
82
+	return filepath.Join(cli.Config.ExecRoot, "libcontainerd")
83
+}
84
+
85
+// allocateDaemonPort ensures that there are no containers
86
+// that try to use any port allocated for the docker server.
87
+func allocateDaemonPort(addr string) error {
88
+	host, port, err := net.SplitHostPort(addr)
89
+	if err != nil {
90
+		return err
91
+	}
92
+
93
+	intPort, err := strconv.Atoi(port)
94
+	if err != nil {
95
+		return err
96
+	}
97
+
98
+	var hostIPs []net.IP
99
+	if parsedIP := net.ParseIP(host); parsedIP != nil {
100
+		hostIPs = append(hostIPs, parsedIP)
101
+	} else if hostIPs, err = net.LookupIP(host); err != nil {
102
+		return fmt.Errorf("failed to lookup %s address in host specification", host)
103
+	}
104
+
105
+	pa := portallocator.Get()
106
+	for _, hostIP := range hostIPs {
107
+		if _, err := pa.RequestPort(hostIP, "tcp", intPort); err != nil {
108
+			return fmt.Errorf("failed to allocate daemon listening port %d (err: %v)", intPort, err)
109
+		}
110
+	}
111
+	return nil
112
+}
0 113
new file mode 100644
... ...
@@ -0,0 +1,212 @@
0
+// +build !windows
1
+
2
+package main
3
+
4
+import (
5
+	"io/ioutil"
6
+	"testing"
7
+
8
+	"github.com/docker/docker/cli"
9
+	"github.com/docker/docker/daemon"
10
+	"github.com/docker/docker/opts"
11
+	"github.com/docker/docker/pkg/mflag"
12
+)
13
+
14
+func TestLoadDaemonCliConfigWithDaemonFlags(t *testing.T) {
15
+	c := &daemon.Config{}
16
+	common := &cli.CommonFlags{
17
+		Debug:    true,
18
+		LogLevel: "info",
19
+	}
20
+
21
+	f, err := ioutil.TempFile("", "docker-config-")
22
+	if err != nil {
23
+		t.Fatal(err)
24
+	}
25
+
26
+	configFile := f.Name()
27
+	f.Write([]byte(`{"log-opts": {"max-size": "1k"}}`))
28
+	f.Close()
29
+
30
+	flags := mflag.NewFlagSet("test", mflag.ContinueOnError)
31
+	flags.String([]string{daemonConfigFileFlag}, "", "")
32
+	flags.BoolVar(&c.EnableSelinuxSupport, []string{"-selinux-enabled"}, true, "")
33
+	flags.StringVar(&c.LogConfig.Type, []string{"-log-driver"}, "json-file", "")
34
+	flags.Var(opts.NewNamedMapOpts("log-opts", c.LogConfig.Config, nil), []string{"-log-opt"}, "")
35
+	flags.Set(daemonConfigFileFlag, configFile)
36
+
37
+	loadedConfig, err := loadDaemonCliConfig(c, flags, common, configFile)
38
+	if err != nil {
39
+		t.Fatal(err)
40
+	}
41
+	if loadedConfig == nil {
42
+		t.Fatalf("expected configuration %v, got nil", c)
43
+	}
44
+	if !loadedConfig.Debug {
45
+		t.Fatalf("expected debug mode, got false")
46
+	}
47
+	if loadedConfig.LogLevel != "info" {
48
+		t.Fatalf("expected info log level, got %v", loadedConfig.LogLevel)
49
+	}
50
+	if !loadedConfig.EnableSelinuxSupport {
51
+		t.Fatalf("expected enabled selinux support, got disabled")
52
+	}
53
+	if loadedConfig.LogConfig.Type != "json-file" {
54
+		t.Fatalf("expected LogConfig type json-file, got %v", loadedConfig.LogConfig.Type)
55
+	}
56
+	if maxSize := loadedConfig.LogConfig.Config["max-size"]; maxSize != "1k" {
57
+		t.Fatalf("expected log max-size `1k`, got %s", maxSize)
58
+	}
59
+}
60
+
61
+func TestLoadDaemonConfigWithNetwork(t *testing.T) {
62
+	c := &daemon.Config{}
63
+	common := &cli.CommonFlags{}
64
+	flags := mflag.NewFlagSet("test", mflag.ContinueOnError)
65
+	flags.String([]string{"-bip"}, "", "")
66
+	flags.String([]string{"-ip"}, "", "")
67
+
68
+	f, err := ioutil.TempFile("", "docker-config-")
69
+	if err != nil {
70
+		t.Fatal(err)
71
+	}
72
+
73
+	configFile := f.Name()
74
+	f.Write([]byte(`{"bip": "127.0.0.2", "ip": "127.0.0.1"}`))
75
+	f.Close()
76
+
77
+	loadedConfig, err := loadDaemonCliConfig(c, flags, common, configFile)
78
+	if err != nil {
79
+		t.Fatal(err)
80
+	}
81
+	if loadedConfig == nil {
82
+		t.Fatalf("expected configuration %v, got nil", c)
83
+	}
84
+	if loadedConfig.IP != "127.0.0.2" {
85
+		t.Fatalf("expected IP 127.0.0.2, got %v", loadedConfig.IP)
86
+	}
87
+	if loadedConfig.DefaultIP.String() != "127.0.0.1" {
88
+		t.Fatalf("expected DefaultIP 127.0.0.1, got %s", loadedConfig.DefaultIP)
89
+	}
90
+}
91
+
92
+func TestLoadDaemonConfigWithMapOptions(t *testing.T) {
93
+	c := &daemon.Config{}
94
+	common := &cli.CommonFlags{}
95
+	flags := mflag.NewFlagSet("test", mflag.ContinueOnError)
96
+
97
+	flags.Var(opts.NewNamedMapOpts("cluster-store-opts", c.ClusterOpts, nil), []string{"-cluster-store-opt"}, "")
98
+	flags.Var(opts.NewNamedMapOpts("log-opts", c.LogConfig.Config, nil), []string{"-log-opt"}, "")
99
+
100
+	f, err := ioutil.TempFile("", "docker-config-")
101
+	if err != nil {
102
+		t.Fatal(err)
103
+	}
104
+
105
+	configFile := f.Name()
106
+	f.Write([]byte(`{
107
+		"cluster-store-opts": {"kv.cacertfile": "/var/lib/docker/discovery_certs/ca.pem"},
108
+		"log-opts": {"tag": "test"}
109
+}`))
110
+	f.Close()
111
+
112
+	loadedConfig, err := loadDaemonCliConfig(c, flags, common, configFile)
113
+	if err != nil {
114
+		t.Fatal(err)
115
+	}
116
+	if loadedConfig == nil {
117
+		t.Fatal("expected configuration, got nil")
118
+	}
119
+	if loadedConfig.ClusterOpts == nil {
120
+		t.Fatal("expected cluster options, got nil")
121
+	}
122
+
123
+	expectedPath := "/var/lib/docker/discovery_certs/ca.pem"
124
+	if caPath := loadedConfig.ClusterOpts["kv.cacertfile"]; caPath != expectedPath {
125
+		t.Fatalf("expected %s, got %s", expectedPath, caPath)
126
+	}
127
+
128
+	if loadedConfig.LogConfig.Config == nil {
129
+		t.Fatal("expected log config options, got nil")
130
+	}
131
+	if tag := loadedConfig.LogConfig.Config["tag"]; tag != "test" {
132
+		t.Fatalf("expected log tag `test`, got %s", tag)
133
+	}
134
+}
135
+
136
+func TestLoadDaemonConfigWithTrueDefaultValues(t *testing.T) {
137
+	c := &daemon.Config{}
138
+	common := &cli.CommonFlags{}
139
+	flags := mflag.NewFlagSet("test", mflag.ContinueOnError)
140
+	flags.BoolVar(&c.EnableUserlandProxy, []string{"-userland-proxy"}, true, "")
141
+
142
+	f, err := ioutil.TempFile("", "docker-config-")
143
+	if err != nil {
144
+		t.Fatal(err)
145
+	}
146
+
147
+	if err := flags.ParseFlags([]string{}, false); err != nil {
148
+		t.Fatal(err)
149
+	}
150
+
151
+	configFile := f.Name()
152
+	f.Write([]byte(`{
153
+		"userland-proxy": false
154
+}`))
155
+	f.Close()
156
+
157
+	loadedConfig, err := loadDaemonCliConfig(c, flags, common, configFile)
158
+	if err != nil {
159
+		t.Fatal(err)
160
+	}
161
+	if loadedConfig == nil {
162
+		t.Fatal("expected configuration, got nil")
163
+	}
164
+
165
+	if loadedConfig.EnableUserlandProxy {
166
+		t.Fatal("expected userland proxy to be disabled, got enabled")
167
+	}
168
+
169
+	// make sure reloading doesn't generate configuration
170
+	// conflicts after normalizing boolean values.
171
+	err = daemon.ReloadConfiguration(configFile, flags, func(reloadedConfig *daemon.Config) {
172
+		if reloadedConfig.EnableUserlandProxy {
173
+			t.Fatal("expected userland proxy to be disabled, got enabled")
174
+		}
175
+	})
176
+	if err != nil {
177
+		t.Fatal(err)
178
+	}
179
+}
180
+
181
+func TestLoadDaemonConfigWithTrueDefaultValuesLeaveDefaults(t *testing.T) {
182
+	c := &daemon.Config{}
183
+	common := &cli.CommonFlags{}
184
+	flags := mflag.NewFlagSet("test", mflag.ContinueOnError)
185
+	flags.BoolVar(&c.EnableUserlandProxy, []string{"-userland-proxy"}, true, "")
186
+
187
+	f, err := ioutil.TempFile("", "docker-config-")
188
+	if err != nil {
189
+		t.Fatal(err)
190
+	}
191
+
192
+	if err := flags.ParseFlags([]string{}, false); err != nil {
193
+		t.Fatal(err)
194
+	}
195
+
196
+	configFile := f.Name()
197
+	f.Write([]byte(`{}`))
198
+	f.Close()
199
+
200
+	loadedConfig, err := loadDaemonCliConfig(c, flags, common, configFile)
201
+	if err != nil {
202
+		t.Fatal(err)
203
+	}
204
+	if loadedConfig == nil {
205
+		t.Fatal("expected configuration, got nil")
206
+	}
207
+
208
+	if !loadedConfig.EnableUserlandProxy {
209
+		t.Fatal("expected userland proxy to be enabled, got disabled")
210
+	}
211
+}
0 212
new file mode 100644
... ...
@@ -0,0 +1,68 @@
0
+package main
1
+
2
+import (
3
+	"fmt"
4
+	"os"
5
+	"syscall"
6
+
7
+	"github.com/Sirupsen/logrus"
8
+	"github.com/docker/docker/daemon"
9
+	"github.com/docker/docker/libcontainerd"
10
+	"github.com/docker/docker/pkg/mflag"
11
+	"github.com/docker/docker/pkg/system"
12
+)
13
+
14
+var defaultDaemonConfigFile = os.Getenv("programdata") + string(os.PathSeparator) + "docker" + string(os.PathSeparator) + "config" + string(os.PathSeparator) + "daemon.json"
15
+
16
+// currentUserIsOwner checks whether the current user is the owner of the given
17
+// file.
18
+func currentUserIsOwner(f string) bool {
19
+	return false
20
+}
21
+
22
+// setDefaultUmask doesn't do anything on windows
23
+func setDefaultUmask() error {
24
+	return nil
25
+}
26
+
27
+func getDaemonConfDir() string {
28
+	return os.Getenv("PROGRAMDATA") + `\docker\config`
29
+}
30
+
31
+// notifySystem sends a message to the host when the server is ready to be used
32
+func notifySystem() {
33
+}
34
+
35
+// setupConfigReloadTrap configures a Win32 event to reload the configuration.
36
+func setupConfigReloadTrap(configFile string, flags *mflag.FlagSet, reload func(*daemon.Config)) {
37
+	go func() {
38
+		sa := syscall.SecurityAttributes{
39
+			Length: 0,
40
+		}
41
+		ev := "Global\\docker-daemon-config-" + fmt.Sprint(os.Getpid())
42
+		if h, _ := system.CreateEvent(&sa, false, false, ev); h != 0 {
43
+			logrus.Debugf("Config reload - waiting signal at %s", ev)
44
+			for {
45
+				syscall.WaitForSingleObject(h, syscall.INFINITE)
46
+				if err := daemon.ReloadConfiguration(configFile, flags, reload); err != nil {
47
+					logrus.Error(err)
48
+				}
49
+			}
50
+		}
51
+	}()
52
+}
53
+
54
+func (cli *DaemonCli) getPlatformRemoteOptions() []libcontainerd.RemoteOption {
55
+	return nil
56
+}
57
+
58
+// getLibcontainerdRoot gets the root directory for libcontainerd to store its
59
+// state. The Windows libcontainerd implementation does not need to write a spec
60
+// or state to disk, so this is a no-op.
61
+func (cli *DaemonCli) getLibcontainerdRoot() string {
62
+	return ""
63
+}
64
+
65
+func allocateDaemonPort(addr string) error {
66
+	return nil
67
+}
0 68
new file mode 100644
... ...
@@ -0,0 +1,68 @@
0
+package main
1
+
2
+import (
3
+	"fmt"
4
+	"os"
5
+
6
+	"github.com/Sirupsen/logrus"
7
+	"github.com/docker/docker/dockerversion"
8
+	flag "github.com/docker/docker/pkg/mflag"
9
+	"github.com/docker/docker/pkg/reexec"
10
+	"github.com/docker/docker/pkg/term"
11
+	"github.com/docker/docker/utils"
12
+)
13
+
14
+var (
15
+	daemonCli = NewDaemonCli()
16
+	flHelp    = flag.Bool([]string{"h", "-help"}, false, "Print usage")
17
+	flVersion = flag.Bool([]string{"v", "-version"}, false, "Print version information and quit")
18
+)
19
+
20
+func main() {
21
+	if reexec.Init() {
22
+		return
23
+	}
24
+
25
+	// Set terminal emulation based on platform as required.
26
+	_, stdout, stderr := term.StdStreams()
27
+
28
+	logrus.SetOutput(stderr)
29
+
30
+	flag.Merge(flag.CommandLine, daemonCli.commonFlags.FlagSet)
31
+
32
+	flag.Usage = func() {
33
+		fmt.Fprint(stdout, "Usage: dockerd [ --help | -v | --version ]\n\n")
34
+		fmt.Fprint(stdout, "A self-sufficient runtime for containers.\n\nOptions:\n")
35
+
36
+		flag.CommandLine.SetOutput(stdout)
37
+		flag.PrintDefaults()
38
+	}
39
+	flag.CommandLine.ShortUsage = func() {
40
+		fmt.Fprint(stderr, "\nUsage:\tdockerd [OPTIONS]\n")
41
+	}
42
+
43
+	if err := flag.CommandLine.ParseFlags(os.Args[1:], false); err != nil {
44
+		os.Exit(1)
45
+	}
46
+
47
+	if *flVersion {
48
+		showVersion()
49
+		return
50
+	}
51
+
52
+	if *flHelp {
53
+		// if global flag --help is present, regardless of what other options and commands there are,
54
+		// just print the usage.
55
+		flag.Usage()
56
+		return
57
+	}
58
+	daemonCli.start()
59
+}
60
+
61
+func showVersion() {
62
+	if utils.ExperimentalBuild() {
63
+		fmt.Printf("Docker version %s, build %s, experimental\n", dockerversion.Version, dockerversion.GitCommit)
64
+	} else {
65
+		fmt.Printf("Docker version %s, build %s\n", dockerversion.Version, dockerversion.GitCommit)
66
+	}
67
+}
0 68
new file mode 100644
... ...
@@ -0,0 +1,5 @@
0
+package main
1
+
2
+import (
3
+	_ "github.com/docker/docker/autogen/winresources/docker"
4
+)
0 5
deleted file mode 100644
... ...
@@ -1,3 +0,0 @@
1
-docker.go contains Docker's main function.
2
-
3
-This file provides first line CLI argument parsing and environment variable setting.
4 1
deleted file mode 100644
... ...
@@ -1,424 +0,0 @@
1
-package main
2
-
3
-import (
4
-	"crypto/tls"
5
-	"fmt"
6
-	"io"
7
-	"os"
8
-	"path/filepath"
9
-	"runtime"
10
-	"strings"
11
-	"time"
12
-
13
-	"github.com/Sirupsen/logrus"
14
-	"github.com/docker/distribution/uuid"
15
-	"github.com/docker/docker/api"
16
-	apiserver "github.com/docker/docker/api/server"
17
-	"github.com/docker/docker/api/server/middleware"
18
-	"github.com/docker/docker/api/server/router"
19
-	"github.com/docker/docker/api/server/router/build"
20
-	"github.com/docker/docker/api/server/router/container"
21
-	"github.com/docker/docker/api/server/router/image"
22
-	"github.com/docker/docker/api/server/router/network"
23
-	systemrouter "github.com/docker/docker/api/server/router/system"
24
-	"github.com/docker/docker/api/server/router/volume"
25
-	"github.com/docker/docker/builder/dockerfile"
26
-	"github.com/docker/docker/cli"
27
-	cliflags "github.com/docker/docker/cli/flags"
28
-	"github.com/docker/docker/cliconfig"
29
-	"github.com/docker/docker/daemon"
30
-	"github.com/docker/docker/daemon/logger"
31
-	"github.com/docker/docker/dockerversion"
32
-	"github.com/docker/docker/libcontainerd"
33
-	"github.com/docker/docker/opts"
34
-	"github.com/docker/docker/pkg/authorization"
35
-	"github.com/docker/docker/pkg/jsonlog"
36
-	"github.com/docker/docker/pkg/listeners"
37
-	flag "github.com/docker/docker/pkg/mflag"
38
-	"github.com/docker/docker/pkg/pidfile"
39
-	"github.com/docker/docker/pkg/signal"
40
-	"github.com/docker/docker/pkg/system"
41
-	"github.com/docker/docker/registry"
42
-	"github.com/docker/docker/runconfig"
43
-	"github.com/docker/docker/utils"
44
-	"github.com/docker/go-connections/tlsconfig"
45
-)
46
-
47
-const (
48
-	daemonConfigFileFlag = "-config-file"
49
-)
50
-
51
-// DaemonCli represents the daemon CLI.
52
-type DaemonCli struct {
53
-	*daemon.Config
54
-	commonFlags *cli.CommonFlags
55
-	configFile  *string
56
-}
57
-
58
-func presentInHelp(usage string) string { return usage }
59
-func absentFromHelp(string) string      { return "" }
60
-
61
-// NewDaemonCli returns a pre-configured daemon CLI
62
-func NewDaemonCli() *DaemonCli {
63
-	// TODO(tiborvass): remove InstallFlags?
64
-	daemonConfig := new(daemon.Config)
65
-	daemonConfig.LogConfig.Config = make(map[string]string)
66
-	daemonConfig.ClusterOpts = make(map[string]string)
67
-
68
-	if runtime.GOOS != "linux" {
69
-		daemonConfig.V2Only = true
70
-	}
71
-
72
-	daemonConfig.InstallFlags(flag.CommandLine, presentInHelp)
73
-	configFile := flag.CommandLine.String([]string{daemonConfigFileFlag}, defaultDaemonConfigFile, "Daemon configuration file")
74
-	flag.CommandLine.Require(flag.Exact, 0)
75
-
76
-	return &DaemonCli{
77
-		Config:      daemonConfig,
78
-		commonFlags: cliflags.InitCommonFlags(),
79
-		configFile:  configFile,
80
-	}
81
-}
82
-
83
-func migrateKey() (err error) {
84
-	// Migrate trust key if exists at ~/.docker/key.json and owned by current user
85
-	oldPath := filepath.Join(cliconfig.ConfigDir(), cliflags.DefaultTrustKeyFile)
86
-	newPath := filepath.Join(getDaemonConfDir(), cliflags.DefaultTrustKeyFile)
87
-	if _, statErr := os.Stat(newPath); os.IsNotExist(statErr) && currentUserIsOwner(oldPath) {
88
-		defer func() {
89
-			// Ensure old path is removed if no error occurred
90
-			if err == nil {
91
-				err = os.Remove(oldPath)
92
-			} else {
93
-				logrus.Warnf("Key migration failed, key file not removed at %s", oldPath)
94
-				os.Remove(newPath)
95
-			}
96
-		}()
97
-
98
-		if err := system.MkdirAll(getDaemonConfDir(), os.FileMode(0644)); err != nil {
99
-			return fmt.Errorf("Unable to create daemon configuration directory: %s", err)
100
-		}
101
-
102
-		newFile, err := os.OpenFile(newPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
103
-		if err != nil {
104
-			return fmt.Errorf("error creating key file %q: %s", newPath, err)
105
-		}
106
-		defer newFile.Close()
107
-
108
-		oldFile, err := os.Open(oldPath)
109
-		if err != nil {
110
-			return fmt.Errorf("error opening key file %q: %s", oldPath, err)
111
-		}
112
-		defer oldFile.Close()
113
-
114
-		if _, err := io.Copy(newFile, oldFile); err != nil {
115
-			return fmt.Errorf("error copying key: %s", err)
116
-		}
117
-
118
-		logrus.Infof("Migrated key from %s to %s", oldPath, newPath)
119
-	}
120
-
121
-	return nil
122
-}
123
-
124
-func (cli *DaemonCli) start() {
125
-	// warn from uuid package when running the daemon
126
-	uuid.Loggerf = logrus.Warnf
127
-
128
-	flags := flag.CommandLine
129
-	cli.commonFlags.PostParse()
130
-
131
-	if cli.commonFlags.TrustKey == "" {
132
-		cli.commonFlags.TrustKey = filepath.Join(getDaemonConfDir(), cliflags.DefaultTrustKeyFile)
133
-	}
134
-	cliConfig, err := loadDaemonCliConfig(cli.Config, flags, cli.commonFlags, *cli.configFile)
135
-	if err != nil {
136
-		fmt.Fprint(os.Stderr, err)
137
-		os.Exit(1)
138
-	}
139
-	cli.Config = cliConfig
140
-
141
-	if cli.Config.Debug {
142
-		utils.EnableDebug()
143
-	}
144
-
145
-	if utils.ExperimentalBuild() {
146
-		logrus.Warn("Running experimental build")
147
-	}
148
-
149
-	logrus.SetFormatter(&logrus.TextFormatter{
150
-		TimestampFormat: jsonlog.RFC3339NanoFixed,
151
-		DisableColors:   cli.Config.RawLogs,
152
-	})
153
-
154
-	if err := setDefaultUmask(); err != nil {
155
-		logrus.Fatalf("Failed to set umask: %v", err)
156
-	}
157
-
158
-	if len(cli.LogConfig.Config) > 0 {
159
-		if err := logger.ValidateLogOpts(cli.LogConfig.Type, cli.LogConfig.Config); err != nil {
160
-			logrus.Fatalf("Failed to set log opts: %v", err)
161
-		}
162
-	}
163
-
164
-	var pfile *pidfile.PIDFile
165
-	if cli.Pidfile != "" {
166
-		pf, err := pidfile.New(cli.Pidfile)
167
-		if err != nil {
168
-			logrus.Fatalf("Error starting daemon: %v", err)
169
-		}
170
-		pfile = pf
171
-		defer func() {
172
-			if err := pfile.Remove(); err != nil {
173
-				logrus.Error(err)
174
-			}
175
-		}()
176
-	}
177
-
178
-	serverConfig := &apiserver.Config{
179
-		Logging:     true,
180
-		SocketGroup: cli.Config.SocketGroup,
181
-		Version:     dockerversion.Version,
182
-		EnableCors:  cli.Config.EnableCors,
183
-		CorsHeaders: cli.Config.CorsHeaders,
184
-	}
185
-
186
-	if cli.Config.TLS {
187
-		tlsOptions := tlsconfig.Options{
188
-			CAFile:   cli.Config.CommonTLSOptions.CAFile,
189
-			CertFile: cli.Config.CommonTLSOptions.CertFile,
190
-			KeyFile:  cli.Config.CommonTLSOptions.KeyFile,
191
-		}
192
-
193
-		if cli.Config.TLSVerify {
194
-			// server requires and verifies client's certificate
195
-			tlsOptions.ClientAuth = tls.RequireAndVerifyClientCert
196
-		}
197
-		tlsConfig, err := tlsconfig.Server(tlsOptions)
198
-		if err != nil {
199
-			logrus.Fatal(err)
200
-		}
201
-		serverConfig.TLSConfig = tlsConfig
202
-	}
203
-
204
-	if len(cli.Config.Hosts) == 0 {
205
-		cli.Config.Hosts = make([]string, 1)
206
-	}
207
-
208
-	api := apiserver.New(serverConfig)
209
-
210
-	for i := 0; i < len(cli.Config.Hosts); i++ {
211
-		var err error
212
-		if cli.Config.Hosts[i], err = opts.ParseHost(cli.Config.TLS, cli.Config.Hosts[i]); err != nil {
213
-			logrus.Fatalf("error parsing -H %s : %v", cli.Config.Hosts[i], err)
214
-		}
215
-
216
-		protoAddr := cli.Config.Hosts[i]
217
-		protoAddrParts := strings.SplitN(protoAddr, "://", 2)
218
-		if len(protoAddrParts) != 2 {
219
-			logrus.Fatalf("bad format %s, expected PROTO://ADDR", protoAddr)
220
-		}
221
-
222
-		proto := protoAddrParts[0]
223
-		addr := protoAddrParts[1]
224
-
225
-		// It's a bad idea to bind to TCP without tlsverify.
226
-		if proto == "tcp" && (serverConfig.TLSConfig == nil || serverConfig.TLSConfig.ClientAuth != tls.RequireAndVerifyClientCert) {
227
-			logrus.Warn("[!] DON'T BIND ON ANY IP ADDRESS WITHOUT setting -tlsverify IF YOU DON'T KNOW WHAT YOU'RE DOING [!]")
228
-		}
229
-		l, err := listeners.Init(proto, addr, serverConfig.SocketGroup, serverConfig.TLSConfig)
230
-		if err != nil {
231
-			logrus.Fatal(err)
232
-		}
233
-		// If we're binding to a TCP port, make sure that a container doesn't try to use it.
234
-		if proto == "tcp" {
235
-			if err := allocateDaemonPort(addr); err != nil {
236
-				logrus.Fatal(err)
237
-			}
238
-		}
239
-		logrus.Debugf("Listener created for HTTP on %s (%s)", protoAddrParts[0], protoAddrParts[1])
240
-		api.Accept(protoAddrParts[1], l...)
241
-	}
242
-
243
-	if err := migrateKey(); err != nil {
244
-		logrus.Fatal(err)
245
-	}
246
-	cli.TrustKeyPath = cli.commonFlags.TrustKey
247
-
248
-	registryService := registry.NewService(cli.Config.ServiceOptions)
249
-	containerdRemote, err := libcontainerd.New(cli.getLibcontainerdRoot(), cli.getPlatformRemoteOptions()...)
250
-	if err != nil {
251
-		logrus.Fatal(err)
252
-	}
253
-
254
-	d, err := daemon.NewDaemon(cli.Config, registryService, containerdRemote)
255
-	if err != nil {
256
-		if pfile != nil {
257
-			if err := pfile.Remove(); err != nil {
258
-				logrus.Error(err)
259
-			}
260
-		}
261
-		logrus.Fatalf("Error starting daemon: %v", err)
262
-	}
263
-
264
-	logrus.Info("Daemon has completed initialization")
265
-
266
-	logrus.WithFields(logrus.Fields{
267
-		"version":     dockerversion.Version,
268
-		"commit":      dockerversion.GitCommit,
269
-		"graphdriver": d.GraphDriverName(),
270
-	}).Info("Docker daemon")
271
-
272
-	cli.initMiddlewares(api, serverConfig)
273
-	initRouter(api, d)
274
-
275
-	reload := func(config *daemon.Config) {
276
-		if err := d.Reload(config); err != nil {
277
-			logrus.Errorf("Error reconfiguring the daemon: %v", err)
278
-			return
279
-		}
280
-		if config.IsValueSet("debug") {
281
-			debugEnabled := utils.IsDebugEnabled()
282
-			switch {
283
-			case debugEnabled && !config.Debug: // disable debug
284
-				utils.DisableDebug()
285
-				api.DisableProfiler()
286
-			case config.Debug && !debugEnabled: // enable debug
287
-				utils.EnableDebug()
288
-				api.EnableProfiler()
289
-			}
290
-
291
-		}
292
-	}
293
-
294
-	setupConfigReloadTrap(*cli.configFile, flags, reload)
295
-
296
-	// The serve API routine never exits unless an error occurs
297
-	// We need to start it as a goroutine and wait on it so
298
-	// daemon doesn't exit
299
-	serveAPIWait := make(chan error)
300
-	go api.Wait(serveAPIWait)
301
-
302
-	signal.Trap(func() {
303
-		api.Close()
304
-		<-serveAPIWait
305
-		shutdownDaemon(d, 15)
306
-		if pfile != nil {
307
-			if err := pfile.Remove(); err != nil {
308
-				logrus.Error(err)
309
-			}
310
-		}
311
-	})
312
-
313
-	// after the daemon is done setting up we can notify systemd api
314
-	notifySystem()
315
-
316
-	// Daemon is fully initialized and handling API traffic
317
-	// Wait for serve API to complete
318
-	errAPI := <-serveAPIWait
319
-	shutdownDaemon(d, 15)
320
-	containerdRemote.Cleanup()
321
-	if errAPI != nil {
322
-		if pfile != nil {
323
-			if err := pfile.Remove(); err != nil {
324
-				logrus.Error(err)
325
-			}
326
-		}
327
-		logrus.Fatalf("Shutting down due to ServeAPI error: %v", errAPI)
328
-	}
329
-}
330
-
331
-// shutdownDaemon just wraps daemon.Shutdown() to handle a timeout in case
332
-// d.Shutdown() is waiting too long to kill container or worst it's
333
-// blocked there
334
-func shutdownDaemon(d *daemon.Daemon, timeout time.Duration) {
335
-	ch := make(chan struct{})
336
-	go func() {
337
-		d.Shutdown()
338
-		close(ch)
339
-	}()
340
-	select {
341
-	case <-ch:
342
-		logrus.Debug("Clean shutdown succeeded")
343
-	case <-time.After(timeout * time.Second):
344
-		logrus.Error("Force shutdown daemon")
345
-	}
346
-}
347
-
348
-func loadDaemonCliConfig(config *daemon.Config, flags *flag.FlagSet, commonConfig *cli.CommonFlags, configFile string) (*daemon.Config, error) {
349
-	config.Debug = commonConfig.Debug
350
-	config.Hosts = commonConfig.Hosts
351
-	config.LogLevel = commonConfig.LogLevel
352
-	config.TLS = commonConfig.TLS
353
-	config.TLSVerify = commonConfig.TLSVerify
354
-	config.CommonTLSOptions = daemon.CommonTLSOptions{}
355
-
356
-	if commonConfig.TLSOptions != nil {
357
-		config.CommonTLSOptions.CAFile = commonConfig.TLSOptions.CAFile
358
-		config.CommonTLSOptions.CertFile = commonConfig.TLSOptions.CertFile
359
-		config.CommonTLSOptions.KeyFile = commonConfig.TLSOptions.KeyFile
360
-	}
361
-
362
-	if configFile != "" {
363
-		c, err := daemon.MergeDaemonConfigurations(config, flags, configFile)
364
-		if err != nil {
365
-			if flags.IsSet(daemonConfigFileFlag) || !os.IsNotExist(err) {
366
-				return nil, fmt.Errorf("unable to configure the Docker daemon with file %s: %v\n", configFile, err)
367
-			}
368
-		}
369
-		// the merged configuration can be nil if the config file didn't exist.
370
-		// leave the current configuration as it is if when that happens.
371
-		if c != nil {
372
-			config = c
373
-		}
374
-	}
375
-
376
-	// Regardless of whether the user sets it to true or false, if they
377
-	// specify TLSVerify at all then we need to turn on TLS
378
-	if config.IsValueSet(cliflags.TLSVerifyKey) {
379
-		config.TLS = true
380
-	}
381
-
382
-	// ensure that the log level is the one set after merging configurations
383
-	cliflags.SetDaemonLogLevel(config.LogLevel)
384
-
385
-	return config, nil
386
-}
387
-
388
-func initRouter(s *apiserver.Server, d *daemon.Daemon) {
389
-	decoder := runconfig.ContainerDecoder{}
390
-
391
-	routers := []router.Router{
392
-		container.NewRouter(d, decoder),
393
-		image.NewRouter(d, decoder),
394
-		systemrouter.NewRouter(d),
395
-		volume.NewRouter(d),
396
-		build.NewRouter(dockerfile.NewBuildManager(d)),
397
-	}
398
-	if d.NetworkControllerEnabled() {
399
-		routers = append(routers, network.NewRouter(d))
400
-	}
401
-
402
-	s.InitRouter(utils.IsDebugEnabled(), routers...)
403
-}
404
-
405
-func (cli *DaemonCli) initMiddlewares(s *apiserver.Server, cfg *apiserver.Config) {
406
-	v := cfg.Version
407
-
408
-	vm := middleware.NewVersionMiddleware(v, api.DefaultVersion, api.MinVersion)
409
-	s.UseMiddleware(vm)
410
-
411
-	if cfg.EnableCors {
412
-		c := middleware.NewCORSMiddleware(cfg.CorsHeaders)
413
-		s.UseMiddleware(c)
414
-	}
415
-
416
-	u := middleware.NewUserAgentMiddleware(v)
417
-	s.UseMiddleware(u)
418
-
419
-	if len(cli.Config.AuthorizationPlugins) > 0 {
420
-		authZPlugins := authorization.NewPlugins(cli.Config.AuthorizationPlugins)
421
-		handleAuthorization := authorization.NewMiddleware(authZPlugins)
422
-		s.UseMiddleware(handleAuthorization)
423
-	}
424
-}
425 1
deleted file mode 100644
... ...
@@ -1,5 +0,0 @@
1
-package main
2
-
3
-// notifySystem sends a message to the host when the server is ready to be used
4
-func notifySystem() {
5
-}
6 1
deleted file mode 100644
... ...
@@ -1,11 +0,0 @@
1
-package main
2
-
3
-import (
4
-	systemdDaemon "github.com/coreos/go-systemd/daemon"
5
-)
6
-
7
-// notifySystem sends a message to the host when the server is ready to be used
8
-func notifySystem() {
9
-	// Tell the init daemon we are accepting requests
10
-	go systemdDaemon.SdNotify("READY=1")
11
-}
12 1
deleted file mode 100644
... ...
@@ -1,294 +0,0 @@
1
-package main
2
-
3
-import (
4
-	"io/ioutil"
5
-	"os"
6
-	"strings"
7
-	"testing"
8
-
9
-	"github.com/Sirupsen/logrus"
10
-	"github.com/docker/docker/cli"
11
-	"github.com/docker/docker/daemon"
12
-	"github.com/docker/docker/opts"
13
-	"github.com/docker/docker/pkg/mflag"
14
-	"github.com/docker/go-connections/tlsconfig"
15
-)
16
-
17
-func TestLoadDaemonCliConfigWithoutOverriding(t *testing.T) {
18
-	c := &daemon.Config{}
19
-	common := &cli.CommonFlags{
20
-		Debug: true,
21
-	}
22
-
23
-	flags := mflag.NewFlagSet("test", mflag.ContinueOnError)
24
-	loadedConfig, err := loadDaemonCliConfig(c, flags, common, "/tmp/fooobarbaz")
25
-	if err != nil {
26
-		t.Fatal(err)
27
-	}
28
-	if loadedConfig == nil {
29
-		t.Fatalf("expected configuration %v, got nil", c)
30
-	}
31
-	if !loadedConfig.Debug {
32
-		t.Fatalf("expected debug to be copied from the common flags, got false")
33
-	}
34
-}
35
-
36
-func TestLoadDaemonCliConfigWithTLS(t *testing.T) {
37
-	c := &daemon.Config{}
38
-	common := &cli.CommonFlags{
39
-		TLS: true,
40
-		TLSOptions: &tlsconfig.Options{
41
-			CAFile: "/tmp/ca.pem",
42
-		},
43
-	}
44
-
45
-	flags := mflag.NewFlagSet("test", mflag.ContinueOnError)
46
-	loadedConfig, err := loadDaemonCliConfig(c, flags, common, "/tmp/fooobarbaz")
47
-	if err != nil {
48
-		t.Fatal(err)
49
-	}
50
-	if loadedConfig == nil {
51
-		t.Fatalf("expected configuration %v, got nil", c)
52
-	}
53
-	if loadedConfig.CommonTLSOptions.CAFile != "/tmp/ca.pem" {
54
-		t.Fatalf("expected /tmp/ca.pem, got %s: %q", loadedConfig.CommonTLSOptions.CAFile, loadedConfig)
55
-	}
56
-}
57
-
58
-func TestLoadDaemonCliConfigWithConflicts(t *testing.T) {
59
-	c := &daemon.Config{}
60
-	common := &cli.CommonFlags{}
61
-	f, err := ioutil.TempFile("", "docker-config-")
62
-	if err != nil {
63
-		t.Fatal(err)
64
-	}
65
-	configFile := f.Name()
66
-	defer os.Remove(configFile)
67
-
68
-	f.Write([]byte(`{"labels": ["l3=foo"]}`))
69
-	f.Close()
70
-
71
-	var labels []string
72
-
73
-	flags := mflag.NewFlagSet("test", mflag.ContinueOnError)
74
-	flags.String([]string{daemonConfigFileFlag}, "", "")
75
-	flags.Var(opts.NewNamedListOptsRef("labels", &labels, opts.ValidateLabel), []string{"-label"}, "")
76
-
77
-	flags.Set(daemonConfigFileFlag, configFile)
78
-	if err := flags.Set("-label", "l1=bar"); err != nil {
79
-		t.Fatal(err)
80
-	}
81
-	if err := flags.Set("-label", "l2=baz"); err != nil {
82
-		t.Fatal(err)
83
-	}
84
-
85
-	_, err = loadDaemonCliConfig(c, flags, common, configFile)
86
-	if err == nil {
87
-		t.Fatalf("expected configuration error, got nil")
88
-	}
89
-	if !strings.Contains(err.Error(), "labels") {
90
-		t.Fatalf("expected labels conflict, got %v", err)
91
-	}
92
-}
93
-
94
-func TestLoadDaemonCliConfigWithTLSVerify(t *testing.T) {
95
-	c := &daemon.Config{}
96
-	common := &cli.CommonFlags{
97
-		TLSOptions: &tlsconfig.Options{
98
-			CAFile: "/tmp/ca.pem",
99
-		},
100
-	}
101
-
102
-	f, err := ioutil.TempFile("", "docker-config-")
103
-	if err != nil {
104
-		t.Fatal(err)
105
-	}
106
-	configFile := f.Name()
107
-	defer os.Remove(configFile)
108
-
109
-	f.Write([]byte(`{"tlsverify": true}`))
110
-	f.Close()
111
-
112
-	flags := mflag.NewFlagSet("test", mflag.ContinueOnError)
113
-	flags.Bool([]string{"-tlsverify"}, false, "")
114
-	loadedConfig, err := loadDaemonCliConfig(c, flags, common, configFile)
115
-	if err != nil {
116
-		t.Fatal(err)
117
-	}
118
-	if loadedConfig == nil {
119
-		t.Fatalf("expected configuration %v, got nil", c)
120
-	}
121
-
122
-	if !loadedConfig.TLS {
123
-		t.Fatalf("expected TLS enabled, got %q", loadedConfig)
124
-	}
125
-}
126
-
127
-func TestLoadDaemonCliConfigWithExplicitTLSVerifyFalse(t *testing.T) {
128
-	c := &daemon.Config{}
129
-	common := &cli.CommonFlags{
130
-		TLSOptions: &tlsconfig.Options{
131
-			CAFile: "/tmp/ca.pem",
132
-		},
133
-	}
134
-
135
-	f, err := ioutil.TempFile("", "docker-config-")
136
-	if err != nil {
137
-		t.Fatal(err)
138
-	}
139
-	configFile := f.Name()
140
-	defer os.Remove(configFile)
141
-
142
-	f.Write([]byte(`{"tlsverify": false}`))
143
-	f.Close()
144
-
145
-	flags := mflag.NewFlagSet("test", mflag.ContinueOnError)
146
-	flags.Bool([]string{"-tlsverify"}, false, "")
147
-	loadedConfig, err := loadDaemonCliConfig(c, flags, common, configFile)
148
-	if err != nil {
149
-		t.Fatal(err)
150
-	}
151
-	if loadedConfig == nil {
152
-		t.Fatalf("expected configuration %v, got nil", c)
153
-	}
154
-
155
-	if !loadedConfig.TLS {
156
-		t.Fatalf("expected TLS enabled, got %q", loadedConfig)
157
-	}
158
-}
159
-
160
-func TestLoadDaemonCliConfigWithoutTLSVerify(t *testing.T) {
161
-	c := &daemon.Config{}
162
-	common := &cli.CommonFlags{
163
-		TLSOptions: &tlsconfig.Options{
164
-			CAFile: "/tmp/ca.pem",
165
-		},
166
-	}
167
-
168
-	f, err := ioutil.TempFile("", "docker-config-")
169
-	if err != nil {
170
-		t.Fatal(err)
171
-	}
172
-	configFile := f.Name()
173
-	defer os.Remove(configFile)
174
-
175
-	f.Write([]byte(`{}`))
176
-	f.Close()
177
-
178
-	flags := mflag.NewFlagSet("test", mflag.ContinueOnError)
179
-	loadedConfig, err := loadDaemonCliConfig(c, flags, common, configFile)
180
-	if err != nil {
181
-		t.Fatal(err)
182
-	}
183
-	if loadedConfig == nil {
184
-		t.Fatalf("expected configuration %v, got nil", c)
185
-	}
186
-
187
-	if loadedConfig.TLS {
188
-		t.Fatalf("expected TLS disabled, got %q", loadedConfig)
189
-	}
190
-}
191
-
192
-func TestLoadDaemonCliConfigWithLogLevel(t *testing.T) {
193
-	c := &daemon.Config{}
194
-	common := &cli.CommonFlags{}
195
-
196
-	f, err := ioutil.TempFile("", "docker-config-")
197
-	if err != nil {
198
-		t.Fatal(err)
199
-	}
200
-	configFile := f.Name()
201
-	defer os.Remove(configFile)
202
-
203
-	f.Write([]byte(`{"log-level": "warn"}`))
204
-	f.Close()
205
-
206
-	flags := mflag.NewFlagSet("test", mflag.ContinueOnError)
207
-	flags.String([]string{"-log-level"}, "", "")
208
-	loadedConfig, err := loadDaemonCliConfig(c, flags, common, configFile)
209
-	if err != nil {
210
-		t.Fatal(err)
211
-	}
212
-	if loadedConfig == nil {
213
-		t.Fatalf("expected configuration %v, got nil", c)
214
-	}
215
-	if loadedConfig.LogLevel != "warn" {
216
-		t.Fatalf("expected warn log level, got %v", loadedConfig.LogLevel)
217
-	}
218
-
219
-	if logrus.GetLevel() != logrus.WarnLevel {
220
-		t.Fatalf("expected warn log level, got %v", logrus.GetLevel())
221
-	}
222
-}
223
-
224
-func TestLoadDaemonConfigWithEmbeddedOptions(t *testing.T) {
225
-	c := &daemon.Config{}
226
-	common := &cli.CommonFlags{}
227
-
228
-	flags := mflag.NewFlagSet("test", mflag.ContinueOnError)
229
-	flags.String([]string{"-tlscacert"}, "", "")
230
-	flags.String([]string{"-log-driver"}, "", "")
231
-
232
-	f, err := ioutil.TempFile("", "docker-config-")
233
-	if err != nil {
234
-		t.Fatal(err)
235
-	}
236
-	configFile := f.Name()
237
-	defer os.Remove(configFile)
238
-
239
-	f.Write([]byte(`{"tlscacert": "/etc/certs/ca.pem", "log-driver": "syslog"}`))
240
-	f.Close()
241
-
242
-	loadedConfig, err := loadDaemonCliConfig(c, flags, common, configFile)
243
-	if err != nil {
244
-		t.Fatal(err)
245
-	}
246
-	if loadedConfig == nil {
247
-		t.Fatal("expected configuration, got nil")
248
-	}
249
-	if loadedConfig.CommonTLSOptions.CAFile != "/etc/certs/ca.pem" {
250
-		t.Fatalf("expected CA file path /etc/certs/ca.pem, got %v", loadedConfig.CommonTLSOptions.CAFile)
251
-	}
252
-	if loadedConfig.LogConfig.Type != "syslog" {
253
-		t.Fatalf("expected LogConfig type syslog, got %v", loadedConfig.LogConfig.Type)
254
-	}
255
-}
256
-
257
-func TestLoadDaemonConfigWithRegistryOptions(t *testing.T) {
258
-	c := &daemon.Config{}
259
-	common := &cli.CommonFlags{}
260
-	flags := mflag.NewFlagSet("test", mflag.ContinueOnError)
261
-	c.ServiceOptions.InstallCliFlags(flags, absentFromHelp)
262
-
263
-	f, err := ioutil.TempFile("", "docker-config-")
264
-	if err != nil {
265
-		t.Fatal(err)
266
-	}
267
-	configFile := f.Name()
268
-	defer os.Remove(configFile)
269
-
270
-	f.Write([]byte(`{"registry-mirrors": ["https://mirrors.docker.com"], "insecure-registries": ["https://insecure.docker.com"], "disable-legacy-registry": true}`))
271
-	f.Close()
272
-
273
-	loadedConfig, err := loadDaemonCliConfig(c, flags, common, configFile)
274
-	if err != nil {
275
-		t.Fatal(err)
276
-	}
277
-	if loadedConfig == nil {
278
-		t.Fatal("expected configuration, got nil")
279
-	}
280
-
281
-	m := loadedConfig.Mirrors
282
-	if len(m) != 1 {
283
-		t.Fatalf("expected 1 mirror, got %d", len(m))
284
-	}
285
-
286
-	r := loadedConfig.InsecureRegistries
287
-	if len(r) != 1 {
288
-		t.Fatalf("expected 1 insecure registries, got %d", len(r))
289
-	}
290
-
291
-	if !loadedConfig.V2Only {
292
-		t.Fatal("expected disable-legacy-registry to be true, got false")
293
-	}
294
-}
295 1
deleted file mode 100644
... ...
@@ -1,113 +0,0 @@
1
-// +build !windows
2
-
3
-package main
4
-
5
-import (
6
-	"fmt"
7
-	"net"
8
-	"os"
9
-	"os/signal"
10
-	"path/filepath"
11
-	"strconv"
12
-	"syscall"
13
-
14
-	"github.com/Sirupsen/logrus"
15
-	"github.com/docker/docker/daemon"
16
-	"github.com/docker/docker/libcontainerd"
17
-	"github.com/docker/docker/pkg/mflag"
18
-	"github.com/docker/docker/pkg/system"
19
-	"github.com/docker/libnetwork/portallocator"
20
-)
21
-
22
-const defaultDaemonConfigFile = "/etc/docker/daemon.json"
23
-
24
-// currentUserIsOwner checks whether the current user is the owner of the given
25
-// file.
26
-func currentUserIsOwner(f string) bool {
27
-	if fileInfo, err := system.Stat(f); err == nil && fileInfo != nil {
28
-		if int(fileInfo.UID()) == os.Getuid() {
29
-			return true
30
-		}
31
-	}
32
-	return false
33
-}
34
-
35
-// setDefaultUmask sets the umask to 0022 to avoid problems
36
-// caused by custom umask
37
-func setDefaultUmask() error {
38
-	desiredUmask := 0022
39
-	syscall.Umask(desiredUmask)
40
-	if umask := syscall.Umask(desiredUmask); umask != desiredUmask {
41
-		return fmt.Errorf("failed to set umask: expected %#o, got %#o", desiredUmask, umask)
42
-	}
43
-
44
-	return nil
45
-}
46
-
47
-func getDaemonConfDir() string {
48
-	return "/etc/docker"
49
-}
50
-
51
-// setupConfigReloadTrap configures the USR2 signal to reload the configuration.
52
-func setupConfigReloadTrap(configFile string, flags *mflag.FlagSet, reload func(*daemon.Config)) {
53
-	c := make(chan os.Signal, 1)
54
-	signal.Notify(c, syscall.SIGHUP)
55
-	go func() {
56
-		for range c {
57
-			if err := daemon.ReloadConfiguration(configFile, flags, reload); err != nil {
58
-				logrus.Error(err)
59
-			}
60
-		}
61
-	}()
62
-}
63
-
64
-func (cli *DaemonCli) getPlatformRemoteOptions() []libcontainerd.RemoteOption {
65
-	opts := []libcontainerd.RemoteOption{
66
-		libcontainerd.WithDebugLog(cli.Config.Debug),
67
-	}
68
-	if cli.Config.ContainerdAddr != "" {
69
-		opts = append(opts, libcontainerd.WithRemoteAddr(cli.Config.ContainerdAddr))
70
-	} else {
71
-		opts = append(opts, libcontainerd.WithStartDaemon(true))
72
-	}
73
-	if daemon.UsingSystemd(cli.Config) {
74
-		args := []string{"--systemd-cgroup=true"}
75
-		opts = append(opts, libcontainerd.WithRuntimeArgs(args))
76
-	}
77
-	return opts
78
-}
79
-
80
-// getLibcontainerdRoot gets the root directory for libcontainerd/containerd to
81
-// store their state.
82
-func (cli *DaemonCli) getLibcontainerdRoot() string {
83
-	return filepath.Join(cli.Config.ExecRoot, "libcontainerd")
84
-}
85
-
86
-// allocateDaemonPort ensures that there are no containers
87
-// that try to use any port allocated for the docker server.
88
-func allocateDaemonPort(addr string) error {
89
-	host, port, err := net.SplitHostPort(addr)
90
-	if err != nil {
91
-		return err
92
-	}
93
-
94
-	intPort, err := strconv.Atoi(port)
95
-	if err != nil {
96
-		return err
97
-	}
98
-
99
-	var hostIPs []net.IP
100
-	if parsedIP := net.ParseIP(host); parsedIP != nil {
101
-		hostIPs = append(hostIPs, parsedIP)
102
-	} else if hostIPs, err = net.LookupIP(host); err != nil {
103
-		return fmt.Errorf("failed to lookup %s address in host specification", host)
104
-	}
105
-
106
-	pa := portallocator.Get()
107
-	for _, hostIP := range hostIPs {
108
-		if _, err := pa.RequestPort(hostIP, "tcp", intPort); err != nil {
109
-			return fmt.Errorf("failed to allocate daemon listening port %d (err: %v)", intPort, err)
110
-		}
111
-	}
112
-	return nil
113
-}
114 1
deleted file mode 100644
... ...
@@ -1,212 +0,0 @@
1
-// +build !windows
2
-
3
-package main
4
-
5
-import (
6
-	"io/ioutil"
7
-	"testing"
8
-
9
-	"github.com/docker/docker/cli"
10
-	"github.com/docker/docker/daemon"
11
-	"github.com/docker/docker/opts"
12
-	"github.com/docker/docker/pkg/mflag"
13
-)
14
-
15
-func TestLoadDaemonCliConfigWithDaemonFlags(t *testing.T) {
16
-	c := &daemon.Config{}
17
-	common := &cli.CommonFlags{
18
-		Debug:    true,
19
-		LogLevel: "info",
20
-	}
21
-
22
-	f, err := ioutil.TempFile("", "docker-config-")
23
-	if err != nil {
24
-		t.Fatal(err)
25
-	}
26
-
27
-	configFile := f.Name()
28
-	f.Write([]byte(`{"log-opts": {"max-size": "1k"}}`))
29
-	f.Close()
30
-
31
-	flags := mflag.NewFlagSet("test", mflag.ContinueOnError)
32
-	flags.String([]string{daemonConfigFileFlag}, "", "")
33
-	flags.BoolVar(&c.EnableSelinuxSupport, []string{"-selinux-enabled"}, true, "")
34
-	flags.StringVar(&c.LogConfig.Type, []string{"-log-driver"}, "json-file", "")
35
-	flags.Var(opts.NewNamedMapOpts("log-opts", c.LogConfig.Config, nil), []string{"-log-opt"}, "")
36
-	flags.Set(daemonConfigFileFlag, configFile)
37
-
38
-	loadedConfig, err := loadDaemonCliConfig(c, flags, common, configFile)
39
-	if err != nil {
40
-		t.Fatal(err)
41
-	}
42
-	if loadedConfig == nil {
43
-		t.Fatalf("expected configuration %v, got nil", c)
44
-	}
45
-	if !loadedConfig.Debug {
46
-		t.Fatalf("expected debug mode, got false")
47
-	}
48
-	if loadedConfig.LogLevel != "info" {
49
-		t.Fatalf("expected info log level, got %v", loadedConfig.LogLevel)
50
-	}
51
-	if !loadedConfig.EnableSelinuxSupport {
52
-		t.Fatalf("expected enabled selinux support, got disabled")
53
-	}
54
-	if loadedConfig.LogConfig.Type != "json-file" {
55
-		t.Fatalf("expected LogConfig type json-file, got %v", loadedConfig.LogConfig.Type)
56
-	}
57
-	if maxSize := loadedConfig.LogConfig.Config["max-size"]; maxSize != "1k" {
58
-		t.Fatalf("expected log max-size `1k`, got %s", maxSize)
59
-	}
60
-}
61
-
62
-func TestLoadDaemonConfigWithNetwork(t *testing.T) {
63
-	c := &daemon.Config{}
64
-	common := &cli.CommonFlags{}
65
-	flags := mflag.NewFlagSet("test", mflag.ContinueOnError)
66
-	flags.String([]string{"-bip"}, "", "")
67
-	flags.String([]string{"-ip"}, "", "")
68
-
69
-	f, err := ioutil.TempFile("", "docker-config-")
70
-	if err != nil {
71
-		t.Fatal(err)
72
-	}
73
-
74
-	configFile := f.Name()
75
-	f.Write([]byte(`{"bip": "127.0.0.2", "ip": "127.0.0.1"}`))
76
-	f.Close()
77
-
78
-	loadedConfig, err := loadDaemonCliConfig(c, flags, common, configFile)
79
-	if err != nil {
80
-		t.Fatal(err)
81
-	}
82
-	if loadedConfig == nil {
83
-		t.Fatalf("expected configuration %v, got nil", c)
84
-	}
85
-	if loadedConfig.IP != "127.0.0.2" {
86
-		t.Fatalf("expected IP 127.0.0.2, got %v", loadedConfig.IP)
87
-	}
88
-	if loadedConfig.DefaultIP.String() != "127.0.0.1" {
89
-		t.Fatalf("expected DefaultIP 127.0.0.1, got %s", loadedConfig.DefaultIP)
90
-	}
91
-}
92
-
93
-func TestLoadDaemonConfigWithMapOptions(t *testing.T) {
94
-	c := &daemon.Config{}
95
-	common := &cli.CommonFlags{}
96
-	flags := mflag.NewFlagSet("test", mflag.ContinueOnError)
97
-
98
-	flags.Var(opts.NewNamedMapOpts("cluster-store-opts", c.ClusterOpts, nil), []string{"-cluster-store-opt"}, "")
99
-	flags.Var(opts.NewNamedMapOpts("log-opts", c.LogConfig.Config, nil), []string{"-log-opt"}, "")
100
-
101
-	f, err := ioutil.TempFile("", "docker-config-")
102
-	if err != nil {
103
-		t.Fatal(err)
104
-	}
105
-
106
-	configFile := f.Name()
107
-	f.Write([]byte(`{
108
-		"cluster-store-opts": {"kv.cacertfile": "/var/lib/docker/discovery_certs/ca.pem"},
109
-		"log-opts": {"tag": "test"}
110
-}`))
111
-	f.Close()
112
-
113
-	loadedConfig, err := loadDaemonCliConfig(c, flags, common, configFile)
114
-	if err != nil {
115
-		t.Fatal(err)
116
-	}
117
-	if loadedConfig == nil {
118
-		t.Fatal("expected configuration, got nil")
119
-	}
120
-	if loadedConfig.ClusterOpts == nil {
121
-		t.Fatal("expected cluster options, got nil")
122
-	}
123
-
124
-	expectedPath := "/var/lib/docker/discovery_certs/ca.pem"
125
-	if caPath := loadedConfig.ClusterOpts["kv.cacertfile"]; caPath != expectedPath {
126
-		t.Fatalf("expected %s, got %s", expectedPath, caPath)
127
-	}
128
-
129
-	if loadedConfig.LogConfig.Config == nil {
130
-		t.Fatal("expected log config options, got nil")
131
-	}
132
-	if tag := loadedConfig.LogConfig.Config["tag"]; tag != "test" {
133
-		t.Fatalf("expected log tag `test`, got %s", tag)
134
-	}
135
-}
136
-
137
-func TestLoadDaemonConfigWithTrueDefaultValues(t *testing.T) {
138
-	c := &daemon.Config{}
139
-	common := &cli.CommonFlags{}
140
-	flags := mflag.NewFlagSet("test", mflag.ContinueOnError)
141
-	flags.BoolVar(&c.EnableUserlandProxy, []string{"-userland-proxy"}, true, "")
142
-
143
-	f, err := ioutil.TempFile("", "docker-config-")
144
-	if err != nil {
145
-		t.Fatal(err)
146
-	}
147
-
148
-	if err := flags.ParseFlags([]string{}, false); err != nil {
149
-		t.Fatal(err)
150
-	}
151
-
152
-	configFile := f.Name()
153
-	f.Write([]byte(`{
154
-		"userland-proxy": false
155
-}`))
156
-	f.Close()
157
-
158
-	loadedConfig, err := loadDaemonCliConfig(c, flags, common, configFile)
159
-	if err != nil {
160
-		t.Fatal(err)
161
-	}
162
-	if loadedConfig == nil {
163
-		t.Fatal("expected configuration, got nil")
164
-	}
165
-
166
-	if loadedConfig.EnableUserlandProxy {
167
-		t.Fatal("expected userland proxy to be disabled, got enabled")
168
-	}
169
-
170
-	// make sure reloading doesn't generate configuration
171
-	// conflicts after normalizing boolean values.
172
-	err = daemon.ReloadConfiguration(configFile, flags, func(reloadedConfig *daemon.Config) {
173
-		if reloadedConfig.EnableUserlandProxy {
174
-			t.Fatal("expected userland proxy to be disabled, got enabled")
175
-		}
176
-	})
177
-	if err != nil {
178
-		t.Fatal(err)
179
-	}
180
-}
181
-
182
-func TestLoadDaemonConfigWithTrueDefaultValuesLeaveDefaults(t *testing.T) {
183
-	c := &daemon.Config{}
184
-	common := &cli.CommonFlags{}
185
-	flags := mflag.NewFlagSet("test", mflag.ContinueOnError)
186
-	flags.BoolVar(&c.EnableUserlandProxy, []string{"-userland-proxy"}, true, "")
187
-
188
-	f, err := ioutil.TempFile("", "docker-config-")
189
-	if err != nil {
190
-		t.Fatal(err)
191
-	}
192
-
193
-	if err := flags.ParseFlags([]string{}, false); err != nil {
194
-		t.Fatal(err)
195
-	}
196
-
197
-	configFile := f.Name()
198
-	f.Write([]byte(`{}`))
199
-	f.Close()
200
-
201
-	loadedConfig, err := loadDaemonCliConfig(c, flags, common, configFile)
202
-	if err != nil {
203
-		t.Fatal(err)
204
-	}
205
-	if loadedConfig == nil {
206
-		t.Fatal("expected configuration, got nil")
207
-	}
208
-
209
-	if !loadedConfig.EnableUserlandProxy {
210
-		t.Fatal("expected userland proxy to be enabled, got disabled")
211
-	}
212
-}
213 1
deleted file mode 100644
... ...
@@ -1,68 +0,0 @@
1
-package main
2
-
3
-import (
4
-	"fmt"
5
-	"os"
6
-	"syscall"
7
-
8
-	"github.com/Sirupsen/logrus"
9
-	"github.com/docker/docker/daemon"
10
-	"github.com/docker/docker/libcontainerd"
11
-	"github.com/docker/docker/pkg/mflag"
12
-	"github.com/docker/docker/pkg/system"
13
-)
14
-
15
-var defaultDaemonConfigFile = os.Getenv("programdata") + string(os.PathSeparator) + "docker" + string(os.PathSeparator) + "config" + string(os.PathSeparator) + "daemon.json"
16
-
17
-// currentUserIsOwner checks whether the current user is the owner of the given
18
-// file.
19
-func currentUserIsOwner(f string) bool {
20
-	return false
21
-}
22
-
23
-// setDefaultUmask doesn't do anything on windows
24
-func setDefaultUmask() error {
25
-	return nil
26
-}
27
-
28
-func getDaemonConfDir() string {
29
-	return os.Getenv("PROGRAMDATA") + `\docker\config`
30
-}
31
-
32
-// notifySystem sends a message to the host when the server is ready to be used
33
-func notifySystem() {
34
-}
35
-
36
-// setupConfigReloadTrap configures a Win32 event to reload the configuration.
37
-func setupConfigReloadTrap(configFile string, flags *mflag.FlagSet, reload func(*daemon.Config)) {
38
-	go func() {
39
-		sa := syscall.SecurityAttributes{
40
-			Length: 0,
41
-		}
42
-		ev := "Global\\docker-daemon-config-" + fmt.Sprint(os.Getpid())
43
-		if h, _ := system.CreateEvent(&sa, false, false, ev); h != 0 {
44
-			logrus.Debugf("Config reload - waiting signal at %s", ev)
45
-			for {
46
-				syscall.WaitForSingleObject(h, syscall.INFINITE)
47
-				if err := daemon.ReloadConfiguration(configFile, flags, reload); err != nil {
48
-					logrus.Error(err)
49
-				}
50
-			}
51
-		}
52
-	}()
53
-}
54
-
55
-func (cli *DaemonCli) getPlatformRemoteOptions() []libcontainerd.RemoteOption {
56
-	return nil
57
-}
58
-
59
-// getLibcontainerdRoot gets the root directory for libcontainerd to store its
60
-// state. The Windows libcontainerd implementation does not need to write a spec
61
-// or state to disk, so this is a no-op.
62
-func (cli *DaemonCli) getLibcontainerdRoot() string {
63
-	return ""
64
-}
65
-
66
-func allocateDaemonPort(addr string) error {
67
-	return nil
68
-}
69 1
deleted file mode 100644
... ...
@@ -1,68 +0,0 @@
1
-package main
2
-
3
-import (
4
-	"fmt"
5
-	"os"
6
-
7
-	"github.com/Sirupsen/logrus"
8
-	"github.com/docker/docker/dockerversion"
9
-	flag "github.com/docker/docker/pkg/mflag"
10
-	"github.com/docker/docker/pkg/reexec"
11
-	"github.com/docker/docker/pkg/term"
12
-	"github.com/docker/docker/utils"
13
-)
14
-
15
-var (
16
-	daemonCli = NewDaemonCli()
17
-	flHelp    = flag.Bool([]string{"h", "-help"}, false, "Print usage")
18
-	flVersion = flag.Bool([]string{"v", "-version"}, false, "Print version information and quit")
19
-)
20
-
21
-func main() {
22
-	if reexec.Init() {
23
-		return
24
-	}
25
-
26
-	// Set terminal emulation based on platform as required.
27
-	_, stdout, stderr := term.StdStreams()
28
-
29
-	logrus.SetOutput(stderr)
30
-
31
-	flag.Merge(flag.CommandLine, daemonCli.commonFlags.FlagSet)
32
-
33
-	flag.Usage = func() {
34
-		fmt.Fprint(stdout, "Usage: dockerd [ --help | -v | --version ]\n\n")
35
-		fmt.Fprint(stdout, "A self-sufficient runtime for containers.\n\nOptions:\n")
36
-
37
-		flag.CommandLine.SetOutput(stdout)
38
-		flag.PrintDefaults()
39
-	}
40
-	flag.CommandLine.ShortUsage = func() {
41
-		fmt.Fprint(stderr, "\nUsage:\tdockerd [OPTIONS]\n")
42
-	}
43
-
44
-	if err := flag.CommandLine.ParseFlags(os.Args[1:], false); err != nil {
45
-		os.Exit(1)
46
-	}
47
-
48
-	if *flVersion {
49
-		showVersion()
50
-		return
51
-	}
52
-
53
-	if *flHelp {
54
-		// if global flag --help is present, regardless of what other options and commands there are,
55
-		// just print the usage.
56
-		flag.Usage()
57
-		return
58
-	}
59
-	daemonCli.start()
60
-}
61
-
62
-func showVersion() {
63
-	if utils.ExperimentalBuild() {
64
-		fmt.Printf("Docker version %s, build %s, experimental\n", dockerversion.Version, dockerversion.GitCommit)
65
-	} else {
66
-		fmt.Printf("Docker version %s, build %s\n", dockerversion.Version, dockerversion.GitCommit)
67
-	}
68
-}
69 1
deleted file mode 100644
... ...
@@ -1,5 +0,0 @@
1
-package main
2
-
3
-import (
4
-	_ "github.com/docker/docker/autogen/winresources/dockerd"
5
-)
... ...
@@ -75,8 +75,8 @@ _dockerfile_env() {
75 75
 
76 76
 clean() {
77 77
 	local packages=(
78
-		"${PROJECT}/docker" # daemon package main
79
-		"${PROJECT}/client" # client package main
78
+		"${PROJECT}/cmd/dockerd" # daemon package main
79
+		"${PROJECT}/cmd/docker" # client package main
80 80
 		"${PROJECT}/integration-cli" # external tests
81 81
 	)
82 82
 	local dockerPlatforms=( ${DOCKER_ENGINE_OSARCH:="linux/amd64"} $(_dockerfile_env DOCKER_CROSSPLATFORMS) )
... ...
@@ -3,6 +3,6 @@ set -e
3 3
 
4 4
 (
5 5
 	export BINARY_SHORT_NAME='docker'
6
-	export SOURCE_PATH='./client'
6
+	export SOURCE_PATH='./cmd/docker'
7 7
 	source "${MAKEDIR}/.binary"
8 8
 )
... ...
@@ -3,7 +3,7 @@ set -e
3 3
 
4 4
 (
5 5
 	export BINARY_SHORT_NAME='dockerd'
6
-	export SOURCE_PATH='./docker'
6
+	export SOURCE_PATH='./cmd/dockerd'
7 7
 	source "${MAKEDIR}/.binary"
8 8
 	copy_containerd "$DEST" 'hash'
9
-)
9
+)
10 10
\ No newline at end of file
... ...
@@ -3,7 +3,7 @@ set -e
3 3
 
4 4
 (
5 5
 	export BINARY_SHORT_NAME='docker'
6
-	export SOURCE_PATH='./client'
6
+	export SOURCE_PATH='./cmd/docker'
7 7
 	export IAMSTATIC='false'
8 8
 	export LDFLAGS_STATIC_DOCKER=''
9 9
 	export BUILDFLAGS=( "${BUILDFLAGS[@]/netgo /}" ) # disable netgo, since we don't need it for a dynamic binary
... ...
@@ -3,7 +3,7 @@ set -e
3 3
 
4 4
 (
5 5
 	export BINARY_SHORT_NAME='dockerd'
6
-	export SOURCE_PATH='./docker'
6
+	export SOURCE_PATH='./cmd/dockerd'
7 7
 	export IAMSTATIC='false'
8 8
 	export LDFLAGS_STATIC_DOCKER=''
9 9
 	export BUILDFLAGS=( "${BUILDFLAGS[@]/netgo /}" ) # disable netgo, since we don't need it for a dynamic binary
... ...
@@ -24,7 +24,7 @@ go build -compiler=gccgo \
24 24
 		-ldl
25 25
 		-pthread
26 26
 	" \
27
-	./docker
27
+	./cmd/dockerd
28 28
 
29 29
 echo "Created binary: $DEST/$BINARY_FULLNAME"
30 30
 ln -sf "$BINARY_FULLNAME" "$DEST/dockerd$BINARY_EXTENSION"
... ...
@@ -42,7 +42,7 @@ go build -compiler=gccgo \
42 42
 		-ldl
43 43
 		-pthread
44 44
 	" \
45
-	./client
45
+	./cmd/docker
46 46
 
47 47
 echo "Created binary: $DEST/$CLIENTBIN_FULLNAME"
48 48
 ln -sf "$CLIENTBIN_FULLNAME" "$DEST/docker$BINARY_EXTENSION"