This also moves some cli specific in `cmd/dockerd` as it does not
really belong to the `daemon/config` package.
Signed-off-by: Vincent Demeester <vincent@sbr.pm>
| 1 | 1 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,52 @@ |
| 0 |
+package main |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "github.com/docker/docker/daemon/config" |
|
| 4 |
+ "github.com/docker/docker/opts" |
|
| 5 |
+ "github.com/spf13/pflag" |
|
| 6 |
+) |
|
| 7 |
+ |
|
| 8 |
+const ( |
|
| 9 |
+ // defaultShutdownTimeout is the default shutdown timeout for the daemon |
|
| 10 |
+ defaultShutdownTimeout = 15 |
|
| 11 |
+) |
|
| 12 |
+ |
|
| 13 |
+// installCommonConfigFlags adds flags to the pflag.FlagSet to configure the daemon |
|
| 14 |
+func installCommonConfigFlags(conf *config.Config, flags *pflag.FlagSet) {
|
|
| 15 |
+ var maxConcurrentDownloads, maxConcurrentUploads int |
|
| 16 |
+ |
|
| 17 |
+ conf.ServiceOptions.InstallCliFlags(flags) |
|
| 18 |
+ |
|
| 19 |
+ flags.Var(opts.NewNamedListOptsRef("storage-opts", &conf.GraphOptions, nil), "storage-opt", "Storage driver options")
|
|
| 20 |
+ flags.Var(opts.NewNamedListOptsRef("authorization-plugins", &conf.AuthorizationPlugins, nil), "authorization-plugin", "Authorization plugins to load")
|
|
| 21 |
+ flags.Var(opts.NewNamedListOptsRef("exec-opts", &conf.ExecOptions, nil), "exec-opt", "Runtime execution options")
|
|
| 22 |
+ flags.StringVarP(&conf.Pidfile, "pidfile", "p", defaultPidFile, "Path to use for daemon PID file") |
|
| 23 |
+ flags.StringVarP(&conf.Root, "graph", "g", defaultGraph, "Root of the Docker runtime") |
|
| 24 |
+ flags.BoolVarP(&conf.AutoRestart, "restart", "r", true, "--restart on the daemon has been deprecated in favor of --restart policies on docker run") |
|
| 25 |
+ flags.MarkDeprecated("restart", "Please use a restart policy on docker run")
|
|
| 26 |
+ flags.StringVarP(&conf.GraphDriver, "storage-driver", "s", "", "Storage driver to use") |
|
| 27 |
+ flags.IntVar(&conf.Mtu, "mtu", 0, "Set the containers network MTU") |
|
| 28 |
+ flags.BoolVar(&conf.RawLogs, "raw-logs", false, "Full timestamps without ANSI coloring") |
|
| 29 |
+ // FIXME: why the inconsistency between "hosts" and "sockets"? |
|
| 30 |
+ flags.Var(opts.NewListOptsRef(&conf.DNS, opts.ValidateIPAddress), "dns", "DNS server to use") |
|
| 31 |
+ flags.Var(opts.NewNamedListOptsRef("dns-opts", &conf.DNSOptions, nil), "dns-opt", "DNS options to use")
|
|
| 32 |
+ flags.Var(opts.NewListOptsRef(&conf.DNSSearch, opts.ValidateDNSSearch), "dns-search", "DNS search domains to use") |
|
| 33 |
+ flags.Var(opts.NewNamedListOptsRef("labels", &conf.Labels, opts.ValidateLabel), "label", "Set key=value labels to the daemon")
|
|
| 34 |
+ flags.StringVar(&conf.LogConfig.Type, "log-driver", "json-file", "Default driver for container logs") |
|
| 35 |
+ flags.Var(opts.NewNamedMapOpts("log-opts", conf.LogConfig.Config, nil), "log-opt", "Default log driver options for containers")
|
|
| 36 |
+ flags.StringVar(&conf.ClusterAdvertise, "cluster-advertise", "", "Address or interface name to advertise") |
|
| 37 |
+ flags.StringVar(&conf.ClusterStore, "cluster-store", "", "URL of the distributed storage backend") |
|
| 38 |
+ flags.Var(opts.NewNamedMapOpts("cluster-store-opts", conf.ClusterOpts, nil), "cluster-store-opt", "Set cluster store options")
|
|
| 39 |
+ flags.StringVar(&conf.CorsHeaders, "api-cors-header", "", "Set CORS headers in the Engine API") |
|
| 40 |
+ flags.IntVar(&maxConcurrentDownloads, "max-concurrent-downloads", config.DefaultMaxConcurrentDownloads, "Set the max concurrent downloads for each pull") |
|
| 41 |
+ flags.IntVar(&maxConcurrentUploads, "max-concurrent-uploads", config.DefaultMaxConcurrentUploads, "Set the max concurrent uploads for each push") |
|
| 42 |
+ flags.IntVar(&conf.ShutdownTimeout, "shutdown-timeout", defaultShutdownTimeout, "Set the default shutdown timeout") |
|
| 43 |
+ |
|
| 44 |
+ flags.StringVar(&conf.SwarmDefaultAdvertiseAddr, "swarm-default-advertise-addr", "", "Set default address or interface for swarm advertised address") |
|
| 45 |
+ flags.BoolVar(&conf.Experimental, "experimental", false, "Enable experimental features") |
|
| 46 |
+ |
|
| 47 |
+ flags.StringVar(&conf.MetricsAddress, "metrics-addr", "", "Set default address and port to serve the metrics api on") |
|
| 48 |
+ |
|
| 49 |
+ conf.MaxConcurrentDownloads = &maxConcurrentDownloads |
|
| 50 |
+ conf.MaxConcurrentUploads = &maxConcurrentUploads |
|
| 51 |
+} |
| 0 | 52 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,34 @@ |
| 0 |
+// +build solaris linux freebsd |
|
| 1 |
+ |
|
| 2 |
+package main |
|
| 3 |
+ |
|
| 4 |
+import ( |
|
| 5 |
+ "github.com/docker/docker/api/types" |
|
| 6 |
+ "github.com/docker/docker/daemon/config" |
|
| 7 |
+ "github.com/docker/docker/opts" |
|
| 8 |
+ "github.com/spf13/pflag" |
|
| 9 |
+) |
|
| 10 |
+ |
|
| 11 |
+var ( |
|
| 12 |
+ defaultPidFile = "/var/run/docker.pid" |
|
| 13 |
+ defaultGraph = "/var/lib/docker" |
|
| 14 |
+ defaultExecRoot = "/var/run/docker" |
|
| 15 |
+) |
|
| 16 |
+ |
|
| 17 |
+// installUnixConfigFlags adds command-line options to the top-level flag parser for |
|
| 18 |
+// the current process that are common across Unix platforms. |
|
| 19 |
+func installUnixConfigFlags(conf *config.Config, flags *pflag.FlagSet) {
|
|
| 20 |
+ conf.Runtimes = make(map[string]types.Runtime) |
|
| 21 |
+ |
|
| 22 |
+ flags.StringVarP(&conf.SocketGroup, "group", "G", "docker", "Group for the unix socket") |
|
| 23 |
+ flags.StringVar(&conf.BridgeConfig.IP, "bip", "", "Specify network bridge IP") |
|
| 24 |
+ flags.StringVarP(&conf.BridgeConfig.Iface, "bridge", "b", "", "Attach containers to a network bridge") |
|
| 25 |
+ flags.StringVar(&conf.BridgeConfig.FixedCIDR, "fixed-cidr", "", "IPv4 subnet for fixed IPs") |
|
| 26 |
+ flags.Var(opts.NewIPOpt(&conf.BridgeConfig.DefaultGatewayIPv4, ""), "default-gateway", "Container default gateway IPv4 address") |
|
| 27 |
+ flags.Var(opts.NewIPOpt(&conf.BridgeConfig.DefaultGatewayIPv6, ""), "default-gateway-v6", "Container default gateway IPv6 address") |
|
| 28 |
+ flags.BoolVar(&conf.BridgeConfig.InterContainerCommunication, "icc", true, "Enable inter-container communication") |
|
| 29 |
+ flags.Var(opts.NewIPOpt(&conf.BridgeConfig.DefaultIP, "0.0.0.0"), "ip", "Default IP when binding container ports") |
|
| 30 |
+ flags.Var(opts.NewNamedRuntimeOpt("runtimes", &conf.Runtimes, config.StockRuntimeName), "add-runtime", "Register an additional OCI compatible runtime")
|
|
| 31 |
+ flags.StringVar(&conf.DefaultRuntime, "default-runtime", config.StockRuntimeName, "Default OCI runtime for containers") |
|
| 32 |
+ |
|
| 33 |
+} |
| 0 | 9 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,19 @@ |
| 0 |
+package main |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "github.com/docker/docker/daemon/config" |
|
| 4 |
+ runconfigopts "github.com/docker/docker/runconfig/opts" |
|
| 5 |
+ units "github.com/docker/go-units" |
|
| 6 |
+ "github.com/spf13/pflag" |
|
| 7 |
+) |
|
| 8 |
+ |
|
| 9 |
+// installConfigFlags adds flags to the pflag.FlagSet to configure the daemon |
|
| 10 |
+func installConfigFlags(conf *config.Config, flags *pflag.FlagSet) {
|
|
| 11 |
+ // First handle install flags which are consistent cross-platform |
|
| 12 |
+ installCommonConfigFlags(conf, flags) |
|
| 13 |
+ |
|
| 14 |
+ // Then install flags common to unix platforms |
|
| 15 |
+ installUnixConfigFlags(conf, flags) |
|
| 16 |
+ |
|
| 17 |
+ attachExperimentalFlags(conf, flags) |
|
| 18 |
+} |
| 0 | 19 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,51 @@ |
| 0 |
+// +build linux,!solaris freebsd,!solaris |
|
| 1 |
+ |
|
| 2 |
+package main |
|
| 3 |
+ |
|
| 4 |
+import ( |
|
| 5 |
+ "github.com/docker/docker/daemon/config" |
|
| 6 |
+ "github.com/docker/docker/opts" |
|
| 7 |
+ units "github.com/docker/go-units" |
|
| 8 |
+ "github.com/spf13/pflag" |
|
| 9 |
+) |
|
| 10 |
+ |
|
| 11 |
+// installConfigFlags adds flags to the pflag.FlagSet to configure the daemon |
|
| 12 |
+func installConfigFlags(conf *config.Config, flags *pflag.FlagSet) {
|
|
| 13 |
+ // First handle install flags which are consistent cross-platform |
|
| 14 |
+ installCommonConfigFlags(conf, flags) |
|
| 15 |
+ |
|
| 16 |
+ // Then install flags common to unix platforms |
|
| 17 |
+ installUnixConfigFlags(conf, flags) |
|
| 18 |
+ |
|
| 19 |
+ conf.Ulimits = make(map[string]*units.Ulimit) |
|
| 20 |
+ |
|
| 21 |
+ // Set default value for `--default-shm-size` |
|
| 22 |
+ conf.ShmSize = opts.MemBytes(config.DefaultShmSize) |
|
| 23 |
+ |
|
| 24 |
+ // Then platform-specific install flags |
|
| 25 |
+ flags.BoolVar(&conf.EnableSelinuxSupport, "selinux-enabled", false, "Enable selinux support") |
|
| 26 |
+ flags.Var(opts.NewUlimitOpt(&conf.Ulimits), "default-ulimit", "Default ulimits for containers") |
|
| 27 |
+ flags.BoolVar(&conf.BridgeConfig.EnableIPTables, "iptables", true, "Enable addition of iptables rules") |
|
| 28 |
+ flags.BoolVar(&conf.BridgeConfig.EnableIPForward, "ip-forward", true, "Enable net.ipv4.ip_forward") |
|
| 29 |
+ flags.BoolVar(&conf.BridgeConfig.EnableIPMasq, "ip-masq", true, "Enable IP masquerading") |
|
| 30 |
+ flags.BoolVar(&conf.BridgeConfig.EnableIPv6, "ipv6", false, "Enable IPv6 networking") |
|
| 31 |
+ flags.StringVar(&conf.ExecRoot, "exec-root", defaultExecRoot, "Root directory for execution state files") |
|
| 32 |
+ flags.StringVar(&conf.BridgeConfig.FixedCIDRv6, "fixed-cidr-v6", "", "IPv6 subnet for fixed IPs") |
|
| 33 |
+ flags.BoolVar(&conf.BridgeConfig.EnableUserlandProxy, "userland-proxy", true, "Use userland proxy for loopback traffic") |
|
| 34 |
+ flags.StringVar(&conf.BridgeConfig.UserlandProxyPath, "userland-proxy-path", "", "Path to the userland proxy binary") |
|
| 35 |
+ flags.BoolVar(&conf.EnableCors, "api-enable-cors", false, "Enable CORS headers in the Engine API, this is deprecated by --api-cors-header") |
|
| 36 |
+ flags.MarkDeprecated("api-enable-cors", "Please use --api-cors-header")
|
|
| 37 |
+ flags.StringVar(&conf.CgroupParent, "cgroup-parent", "", "Set parent cgroup for all containers") |
|
| 38 |
+ flags.StringVar(&conf.RemappedRoot, "userns-remap", "", "User/Group setting for user namespaces") |
|
| 39 |
+ flags.StringVar(&conf.ContainerdAddr, "containerd", "", "Path to containerd socket") |
|
| 40 |
+ flags.BoolVar(&conf.LiveRestoreEnabled, "live-restore", false, "Enable live restore of docker when containers are still running") |
|
| 41 |
+ flags.IntVar(&conf.OOMScoreAdjust, "oom-score-adjust", -500, "Set the oom_score_adj for the daemon") |
|
| 42 |
+ flags.BoolVar(&conf.Init, "init", false, "Run an init in the container to forward signals and reap processes") |
|
| 43 |
+ flags.StringVar(&conf.InitPath, "init-path", "", "Path to the docker-init binary") |
|
| 44 |
+ flags.Int64Var(&conf.CPURealtimePeriod, "cpu-rt-period", 0, "Limit the CPU real-time period in microseconds") |
|
| 45 |
+ flags.Int64Var(&conf.CPURealtimeRuntime, "cpu-rt-runtime", 0, "Limit the CPU real-time runtime in microseconds") |
|
| 46 |
+ flags.StringVar(&conf.SeccompProfile, "seccomp-profile", "", "Path to seccomp profile") |
|
| 47 |
+ flags.Var(&conf.ShmSize, "default-shm-size", "Default shm size for containers") |
|
| 48 |
+ |
|
| 49 |
+ attachExperimentalFlags(conf, flags) |
|
| 50 |
+} |
| 0 | 51 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,32 @@ |
| 0 |
+// +build linux,!solaris freebsd,!solaris |
|
| 1 |
+ |
|
| 2 |
+package main |
|
| 3 |
+ |
|
| 4 |
+import ( |
|
| 5 |
+ "runtime" |
|
| 6 |
+ "testing" |
|
| 7 |
+ |
|
| 8 |
+ "github.com/docker/docker/daemon/config" |
|
| 9 |
+ "github.com/docker/docker/pkg/testutil/assert" |
|
| 10 |
+ "github.com/spf13/pflag" |
|
| 11 |
+) |
|
| 12 |
+ |
|
| 13 |
+func TestDaemonParseShmSize(t *testing.T) {
|
|
| 14 |
+ if runtime.GOOS == "solaris" {
|
|
| 15 |
+ t.Skip("ShmSize not supported on Solaris\n")
|
|
| 16 |
+ } |
|
| 17 |
+ flags := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
|
| 18 |
+ |
|
| 19 |
+ conf := &config.Config{}
|
|
| 20 |
+ installConfigFlags(conf, flags) |
|
| 21 |
+ // By default `--default-shm-size=64M` |
|
| 22 |
+ expectedValue := 64 * 1024 * 1024 |
|
| 23 |
+ if conf.ShmSize.Value() != int64(expectedValue) {
|
|
| 24 |
+ t.Fatalf("expected default shm size %d, got %d", expectedValue, conf.ShmSize.Value())
|
|
| 25 |
+ } |
|
| 26 |
+ assert.NilError(t, flags.Set("default-shm-size", "128M"))
|
|
| 27 |
+ expectedValue = 128 * 1024 * 1024 |
|
| 28 |
+ if conf.ShmSize.Value() != int64(expectedValue) {
|
|
| 29 |
+ t.Fatalf("expected default shm size %d, got %d", expectedValue, conf.ShmSize.Value())
|
|
| 30 |
+ } |
|
| 31 |
+} |
| 0 | 32 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,25 @@ |
| 0 |
+package main |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "os" |
|
| 4 |
+ "path/filepath" |
|
| 5 |
+ |
|
| 6 |
+ "github.com/docker/docker/daemon/config" |
|
| 7 |
+ "github.com/spf13/pflag" |
|
| 8 |
+) |
|
| 9 |
+ |
|
| 10 |
+var ( |
|
| 11 |
+ defaultPidFile string |
|
| 12 |
+ defaultGraph = filepath.Join(os.Getenv("programdata"), "docker")
|
|
| 13 |
+) |
|
| 14 |
+ |
|
| 15 |
+// installConfigFlags adds flags to the pflag.FlagSet to configure the daemon |
|
| 16 |
+func installConfigFlags(conf *config.Config, flags *pflag.FlagSet) {
|
|
| 17 |
+ // First handle install flags which are consistent cross-platform |
|
| 18 |
+ installCommonConfigFlags(conf, flags) |
|
| 19 |
+ |
|
| 20 |
+ // Then platform-specific install flags. |
|
| 21 |
+ flags.StringVar(&conf.BridgeConfig.FixedCIDR, "fixed-cidr", "", "IPv4 subnet for fixed IPs") |
|
| 22 |
+ flags.StringVarP(&conf.BridgeConfig.Iface, "bridge", "b", "", "Attach containers to a virtual switch") |
|
| 23 |
+ flags.StringVarP(&conf.SocketGroup, "group", "G", "", "Users or groups that can access the named pipe") |
|
| 24 |
+} |
| ... | ... |
@@ -31,6 +31,7 @@ import ( |
| 31 | 31 |
cliflags "github.com/docker/docker/cli/flags" |
| 32 | 32 |
"github.com/docker/docker/daemon" |
| 33 | 33 |
"github.com/docker/docker/daemon/cluster" |
| 34 |
+ "github.com/docker/docker/daemon/config" |
|
| 34 | 35 |
"github.com/docker/docker/daemon/logger" |
| 35 | 36 |
"github.com/docker/docker/dockerversion" |
| 36 | 37 |
"github.com/docker/docker/libcontainerd" |
| ... | ... |
@@ -54,7 +55,7 @@ const ( |
| 54 | 54 |
|
| 55 | 55 |
// DaemonCli represents the daemon CLI. |
| 56 | 56 |
type DaemonCli struct {
|
| 57 |
- *daemon.Config |
|
| 57 |
+ *config.Config |
|
| 58 | 58 |
configFile *string |
| 59 | 59 |
flags *pflag.FlagSet |
| 60 | 60 |
|
| ... | ... |
@@ -68,7 +69,7 @@ func NewDaemonCli() *DaemonCli {
|
| 68 | 68 |
return &DaemonCli{}
|
| 69 | 69 |
} |
| 70 | 70 |
|
| 71 |
-func migrateKey(config *daemon.Config) (err error) {
|
|
| 71 |
+func migrateKey(config *config.Config) (err error) {
|
|
| 72 | 72 |
// No migration necessary on Windows |
| 73 | 73 |
if runtime.GOOS == "windows" {
|
| 74 | 74 |
return nil |
| ... | ... |
@@ -335,7 +336,7 @@ func (cli *DaemonCli) start(opts daemonOptions) (err error) {
|
| 335 | 335 |
} |
| 336 | 336 |
|
| 337 | 337 |
func (cli *DaemonCli) reloadConfig() {
|
| 338 |
- reload := func(config *daemon.Config) {
|
|
| 338 |
+ reload := func(config *config.Config) {
|
|
| 339 | 339 |
|
| 340 | 340 |
// Revalidate and reload the authorization plugins |
| 341 | 341 |
if err := validateAuthzPlugins(config.AuthorizationPlugins, cli.d.PluginStore); err != nil {
|
| ... | ... |
@@ -363,7 +364,7 @@ func (cli *DaemonCli) reloadConfig() {
|
| 363 | 363 |
} |
| 364 | 364 |
} |
| 365 | 365 |
|
| 366 |
- if err := daemon.ReloadConfiguration(*cli.configFile, cli.flags, reload); err != nil {
|
|
| 366 |
+ if err := config.Reload(*cli.configFile, cli.flags, reload); err != nil {
|
|
| 367 | 367 |
logrus.Error(err) |
| 368 | 368 |
} |
| 369 | 369 |
} |
| ... | ... |
@@ -395,24 +396,24 @@ func shutdownDaemon(d *daemon.Daemon) {
|
| 395 | 395 |
} |
| 396 | 396 |
} |
| 397 | 397 |
|
| 398 |
-func loadDaemonCliConfig(opts daemonOptions) (*daemon.Config, error) {
|
|
| 399 |
- config := opts.daemonConfig |
|
| 398 |
+func loadDaemonCliConfig(opts daemonOptions) (*config.Config, error) {
|
|
| 399 |
+ conf := opts.daemonConfig |
|
| 400 | 400 |
flags := opts.flags |
| 401 |
- config.Debug = opts.common.Debug |
|
| 402 |
- config.Hosts = opts.common.Hosts |
|
| 403 |
- config.LogLevel = opts.common.LogLevel |
|
| 404 |
- config.TLS = opts.common.TLS |
|
| 405 |
- config.TLSVerify = opts.common.TLSVerify |
|
| 406 |
- config.CommonTLSOptions = daemon.CommonTLSOptions{}
|
|
| 401 |
+ conf.Debug = opts.common.Debug |
|
| 402 |
+ conf.Hosts = opts.common.Hosts |
|
| 403 |
+ conf.LogLevel = opts.common.LogLevel |
|
| 404 |
+ conf.TLS = opts.common.TLS |
|
| 405 |
+ conf.TLSVerify = opts.common.TLSVerify |
|
| 406 |
+ conf.CommonTLSOptions = config.CommonTLSOptions{}
|
|
| 407 | 407 |
|
| 408 | 408 |
if opts.common.TLSOptions != nil {
|
| 409 |
- config.CommonTLSOptions.CAFile = opts.common.TLSOptions.CAFile |
|
| 410 |
- config.CommonTLSOptions.CertFile = opts.common.TLSOptions.CertFile |
|
| 411 |
- config.CommonTLSOptions.KeyFile = opts.common.TLSOptions.KeyFile |
|
| 409 |
+ conf.CommonTLSOptions.CAFile = opts.common.TLSOptions.CAFile |
|
| 410 |
+ conf.CommonTLSOptions.CertFile = opts.common.TLSOptions.CertFile |
|
| 411 |
+ conf.CommonTLSOptions.KeyFile = opts.common.TLSOptions.KeyFile |
|
| 412 | 412 |
} |
| 413 | 413 |
|
| 414 | 414 |
if opts.configFile != "" {
|
| 415 |
- c, err := daemon.MergeDaemonConfigurations(config, flags, opts.configFile) |
|
| 415 |
+ c, err := config.MergeDaemonConfigurations(conf, flags, opts.configFile) |
|
| 416 | 416 |
if err != nil {
|
| 417 | 417 |
if flags.Changed(flagDaemonConfigFile) || !os.IsNotExist(err) {
|
| 418 | 418 |
return nil, fmt.Errorf("unable to configure the Docker daemon with file %s: %v\n", opts.configFile, err)
|
| ... | ... |
@@ -421,11 +422,11 @@ func loadDaemonCliConfig(opts daemonOptions) (*daemon.Config, error) {
|
| 421 | 421 |
// the merged configuration can be nil if the config file didn't exist. |
| 422 | 422 |
// leave the current configuration as it is if when that happens. |
| 423 | 423 |
if c != nil {
|
| 424 |
- config = c |
|
| 424 |
+ conf = c |
|
| 425 | 425 |
} |
| 426 | 426 |
} |
| 427 | 427 |
|
| 428 |
- if err := daemon.ValidateConfiguration(config); err != nil {
|
|
| 428 |
+ if err := config.Validate(conf); err != nil {
|
|
| 429 | 429 |
return nil, err |
| 430 | 430 |
} |
| 431 | 431 |
|
| ... | ... |
@@ -442,20 +443,20 @@ func loadDaemonCliConfig(opts daemonOptions) (*daemon.Config, error) {
|
| 442 | 442 |
// } |
| 443 | 443 |
// config.Labels = newLabels |
| 444 | 444 |
// |
| 445 |
- if _, err := daemon.GetConflictFreeLabels(config.Labels); err != nil {
|
|
| 445 |
+ if _, err := config.GetConflictFreeLabels(conf.Labels); err != nil {
|
|
| 446 | 446 |
logrus.Warnf("Engine labels with duplicate keys and conflicting values have been deprecated: %s", err)
|
| 447 | 447 |
} |
| 448 | 448 |
|
| 449 | 449 |
// Regardless of whether the user sets it to true or false, if they |
| 450 | 450 |
// specify TLSVerify at all then we need to turn on TLS |
| 451 |
- if config.IsValueSet(cliflags.FlagTLSVerify) {
|
|
| 452 |
- config.TLS = true |
|
| 451 |
+ if conf.IsValueSet(cliflags.FlagTLSVerify) {
|
|
| 452 |
+ conf.TLS = true |
|
| 453 | 453 |
} |
| 454 | 454 |
|
| 455 | 455 |
// ensure that the log level is the one set after merging configurations |
| 456 |
- cliflags.SetLogLevel(config.LogLevel) |
|
| 456 |
+ cliflags.SetLogLevel(conf.LogLevel) |
|
| 457 | 457 |
|
| 458 |
- return config, nil |
|
| 458 |
+ return conf, nil |
|
| 459 | 459 |
} |
| 460 | 460 |
|
| 461 | 461 |
func initRouter(s *apiserver.Server, d *daemon.Daemon, c *cluster.Cluster) {
|
| ... | ... |
@@ -5,7 +5,7 @@ import ( |
| 5 | 5 |
|
| 6 | 6 |
"github.com/Sirupsen/logrus" |
| 7 | 7 |
cliflags "github.com/docker/docker/cli/flags" |
| 8 |
- "github.com/docker/docker/daemon" |
|
| 8 |
+ "github.com/docker/docker/daemon/config" |
|
| 9 | 9 |
"github.com/docker/docker/pkg/testutil/assert" |
| 10 | 10 |
"github.com/docker/docker/pkg/testutil/tempfile" |
| 11 | 11 |
"github.com/spf13/pflag" |
| ... | ... |
@@ -13,12 +13,12 @@ import ( |
| 13 | 13 |
|
| 14 | 14 |
func defaultOptions(configFile string) daemonOptions {
|
| 15 | 15 |
opts := daemonOptions{
|
| 16 |
- daemonConfig: &daemon.Config{},
|
|
| 16 |
+ daemonConfig: &config.Config{},
|
|
| 17 | 17 |
flags: &pflag.FlagSet{},
|
| 18 | 18 |
common: cliflags.NewCommonOptions(), |
| 19 | 19 |
} |
| 20 | 20 |
opts.common.InstallFlags(opts.flags) |
| 21 |
- opts.daemonConfig.InstallFlags(opts.flags) |
|
| 21 |
+ installConfigFlags(opts.daemonConfig, opts.flags) |
|
| 22 | 22 |
opts.flags.StringVar(&opts.configFile, flagDaemonConfigFile, defaultDaemonConfigFile, "") |
| 23 | 23 |
opts.configFile = configFile |
| 24 | 24 |
return opts |
| ... | ... |
@@ -6,10 +6,11 @@ |
| 6 | 6 |
package main |
| 7 | 7 |
|
| 8 | 8 |
import ( |
| 9 |
- "github.com/docker/docker/daemon" |
|
| 9 |
+ "testing" |
|
| 10 |
+ |
|
| 11 |
+ "github.com/docker/docker/daemon/config" |
|
| 10 | 12 |
"github.com/docker/docker/pkg/testutil/assert" |
| 11 | 13 |
"github.com/docker/docker/pkg/testutil/tempfile" |
| 12 |
- "testing" |
|
| 13 | 14 |
) |
| 14 | 15 |
|
| 15 | 16 |
func TestLoadDaemonCliConfigWithDaemonFlags(t *testing.T) {
|
| ... | ... |
@@ -82,10 +83,10 @@ func TestLoadDaemonConfigWithTrueDefaultValues(t *testing.T) {
|
| 82 | 82 |
|
| 83 | 83 |
// make sure reloading doesn't generate configuration |
| 84 | 84 |
// conflicts after normalizing boolean values. |
| 85 |
- reload := func(reloadedConfig *daemon.Config) {
|
|
| 85 |
+ reload := func(reloadedConfig *config.Config) {
|
|
| 86 | 86 |
assert.Equal(t, reloadedConfig.EnableUserlandProxy, false) |
| 87 | 87 |
} |
| 88 |
- assert.NilError(t, daemon.ReloadConfiguration(opts.configFile, opts.flags, reload)) |
|
| 88 |
+ assert.NilError(t, config.Reload(opts.configFile, opts.flags, reload)) |
|
| 89 | 89 |
} |
| 90 | 90 |
|
| 91 | 91 |
func TestLoadDaemonConfigWithTrueDefaultValuesLeaveDefaults(t *testing.T) {
|
| ... | ... |
@@ -9,7 +9,7 @@ import ( |
| 9 | 9 |
"github.com/Sirupsen/logrus" |
| 10 | 10 |
"github.com/docker/docker/cli" |
| 11 | 11 |
cliflags "github.com/docker/docker/cli/flags" |
| 12 |
- "github.com/docker/docker/daemon" |
|
| 12 |
+ "github.com/docker/docker/daemon/config" |
|
| 13 | 13 |
"github.com/docker/docker/dockerversion" |
| 14 | 14 |
"github.com/docker/docker/pkg/reexec" |
| 15 | 15 |
"github.com/docker/docker/pkg/term" |
| ... | ... |
@@ -20,14 +20,14 @@ import ( |
| 20 | 20 |
type daemonOptions struct {
|
| 21 | 21 |
version bool |
| 22 | 22 |
configFile string |
| 23 |
- daemonConfig *daemon.Config |
|
| 23 |
+ daemonConfig *config.Config |
|
| 24 | 24 |
common *cliflags.CommonOptions |
| 25 | 25 |
flags *pflag.FlagSet |
| 26 | 26 |
} |
| 27 | 27 |
|
| 28 | 28 |
func newDaemonCommand() *cobra.Command {
|
| 29 | 29 |
opts := daemonOptions{
|
| 30 |
- daemonConfig: daemon.NewConfig(), |
|
| 30 |
+ daemonConfig: config.New(), |
|
| 31 | 31 |
common: cliflags.NewCommonOptions(), |
| 32 | 32 |
} |
| 33 | 33 |
|
| ... | ... |
@@ -48,7 +48,7 @@ func newDaemonCommand() *cobra.Command {
|
| 48 | 48 |
flags.BoolVarP(&opts.version, "version", "v", false, "Print version information and quit") |
| 49 | 49 |
flags.StringVar(&opts.configFile, flagDaemonConfigFile, defaultDaemonConfigFile, "Daemon configuration file") |
| 50 | 50 |
opts.common.InstallFlags(flags) |
| 51 |
- opts.daemonConfig.InstallFlags(flags) |
|
| 51 |
+ installConfigFlags(opts.daemonConfig, flags) |
|
| 52 | 52 |
installServiceFlags(flags) |
| 53 | 53 |
|
| 54 | 54 |
return cmd |
| 55 | 55 |
deleted file mode 100644 |
| ... | ... |
@@ -1,539 +0,0 @@ |
| 1 |
-package daemon |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "bytes" |
|
| 5 |
- "encoding/json" |
|
| 6 |
- "errors" |
|
| 7 |
- "fmt" |
|
| 8 |
- "io" |
|
| 9 |
- "io/ioutil" |
|
| 10 |
- "runtime" |
|
| 11 |
- "sort" |
|
| 12 |
- "strings" |
|
| 13 |
- "sync" |
|
| 14 |
- |
|
| 15 |
- "github.com/Sirupsen/logrus" |
|
| 16 |
- "github.com/docker/docker/opts" |
|
| 17 |
- "github.com/docker/docker/pkg/discovery" |
|
| 18 |
- "github.com/docker/docker/registry" |
|
| 19 |
- "github.com/imdario/mergo" |
|
| 20 |
- "github.com/spf13/pflag" |
|
| 21 |
-) |
|
| 22 |
- |
|
| 23 |
-const ( |
|
| 24 |
- // defaultMaxConcurrentDownloads is the default value for |
|
| 25 |
- // maximum number of downloads that |
|
| 26 |
- // may take place at a time for each pull. |
|
| 27 |
- defaultMaxConcurrentDownloads = 3 |
|
| 28 |
- // defaultMaxConcurrentUploads is the default value for |
|
| 29 |
- // maximum number of uploads that |
|
| 30 |
- // may take place at a time for each push. |
|
| 31 |
- defaultMaxConcurrentUploads = 5 |
|
| 32 |
- // stockRuntimeName is the reserved name/alias used to represent the |
|
| 33 |
- // OCI runtime being shipped with the docker daemon package. |
|
| 34 |
- stockRuntimeName = "runc" |
|
| 35 |
-) |
|
| 36 |
- |
|
| 37 |
-const ( |
|
| 38 |
- defaultNetworkMtu = 1500 |
|
| 39 |
- disableNetworkBridge = "none" |
|
| 40 |
-) |
|
| 41 |
- |
|
| 42 |
-const ( |
|
| 43 |
- defaultShutdownTimeout = 15 |
|
| 44 |
-) |
|
| 45 |
- |
|
| 46 |
-// flatOptions contains configuration keys |
|
| 47 |
-// that MUST NOT be parsed as deep structures. |
|
| 48 |
-// Use this to differentiate these options |
|
| 49 |
-// with others like the ones in CommonTLSOptions. |
|
| 50 |
-var flatOptions = map[string]bool{
|
|
| 51 |
- "cluster-store-opts": true, |
|
| 52 |
- "log-opts": true, |
|
| 53 |
- "runtimes": true, |
|
| 54 |
- "default-ulimits": true, |
|
| 55 |
-} |
|
| 56 |
- |
|
| 57 |
-// LogConfig represents the default log configuration. |
|
| 58 |
-// It includes json tags to deserialize configuration from a file |
|
| 59 |
-// using the same names that the flags in the command line use. |
|
| 60 |
-type LogConfig struct {
|
|
| 61 |
- Type string `json:"log-driver,omitempty"` |
|
| 62 |
- Config map[string]string `json:"log-opts,omitempty"` |
|
| 63 |
-} |
|
| 64 |
- |
|
| 65 |
-// commonBridgeConfig stores all the platform-common bridge driver specific |
|
| 66 |
-// configuration. |
|
| 67 |
-type commonBridgeConfig struct {
|
|
| 68 |
- Iface string `json:"bridge,omitempty"` |
|
| 69 |
- FixedCIDR string `json:"fixed-cidr,omitempty"` |
|
| 70 |
-} |
|
| 71 |
- |
|
| 72 |
-// CommonTLSOptions defines TLS configuration for the daemon server. |
|
| 73 |
-// It includes json tags to deserialize configuration from a file |
|
| 74 |
-// using the same names that the flags in the command line use. |
|
| 75 |
-type CommonTLSOptions struct {
|
|
| 76 |
- CAFile string `json:"tlscacert,omitempty"` |
|
| 77 |
- CertFile string `json:"tlscert,omitempty"` |
|
| 78 |
- KeyFile string `json:"tlskey,omitempty"` |
|
| 79 |
-} |
|
| 80 |
- |
|
| 81 |
-// CommonConfig defines the configuration of a docker daemon which is |
|
| 82 |
-// common across platforms. |
|
| 83 |
-// It includes json tags to deserialize configuration from a file |
|
| 84 |
-// using the same names that the flags in the command line use. |
|
| 85 |
-type CommonConfig struct {
|
|
| 86 |
- AuthorizationPlugins []string `json:"authorization-plugins,omitempty"` // AuthorizationPlugins holds list of authorization plugins |
|
| 87 |
- AutoRestart bool `json:"-"` |
|
| 88 |
- Context map[string][]string `json:"-"` |
|
| 89 |
- DisableBridge bool `json:"-"` |
|
| 90 |
- DNS []string `json:"dns,omitempty"` |
|
| 91 |
- DNSOptions []string `json:"dns-opts,omitempty"` |
|
| 92 |
- DNSSearch []string `json:"dns-search,omitempty"` |
|
| 93 |
- ExecOptions []string `json:"exec-opts,omitempty"` |
|
| 94 |
- GraphDriver string `json:"storage-driver,omitempty"` |
|
| 95 |
- GraphOptions []string `json:"storage-opts,omitempty"` |
|
| 96 |
- Labels []string `json:"labels,omitempty"` |
|
| 97 |
- Mtu int `json:"mtu,omitempty"` |
|
| 98 |
- Pidfile string `json:"pidfile,omitempty"` |
|
| 99 |
- RawLogs bool `json:"raw-logs,omitempty"` |
|
| 100 |
- Root string `json:"graph,omitempty"` |
|
| 101 |
- SocketGroup string `json:"group,omitempty"` |
|
| 102 |
- TrustKeyPath string `json:"-"` |
|
| 103 |
- CorsHeaders string `json:"api-cors-header,omitempty"` |
|
| 104 |
- EnableCors bool `json:"api-enable-cors,omitempty"` |
|
| 105 |
- |
|
| 106 |
- // LiveRestoreEnabled determines whether we should keep containers |
|
| 107 |
- // alive upon daemon shutdown/start |
|
| 108 |
- LiveRestoreEnabled bool `json:"live-restore,omitempty"` |
|
| 109 |
- |
|
| 110 |
- // ClusterStore is the storage backend used for the cluster information. It is used by both |
|
| 111 |
- // multihost networking (to store networks and endpoints information) and by the node discovery |
|
| 112 |
- // mechanism. |
|
| 113 |
- ClusterStore string `json:"cluster-store,omitempty"` |
|
| 114 |
- |
|
| 115 |
- // ClusterOpts is used to pass options to the discovery package for tuning libkv settings, such |
|
| 116 |
- // as TLS configuration settings. |
|
| 117 |
- ClusterOpts map[string]string `json:"cluster-store-opts,omitempty"` |
|
| 118 |
- |
|
| 119 |
- // ClusterAdvertise is the network endpoint that the Engine advertises for the purpose of node |
|
| 120 |
- // discovery. This should be a 'host:port' combination on which that daemon instance is |
|
| 121 |
- // reachable by other hosts. |
|
| 122 |
- ClusterAdvertise string `json:"cluster-advertise,omitempty"` |
|
| 123 |
- |
|
| 124 |
- // MaxConcurrentDownloads is the maximum number of downloads that |
|
| 125 |
- // may take place at a time for each pull. |
|
| 126 |
- MaxConcurrentDownloads *int `json:"max-concurrent-downloads,omitempty"` |
|
| 127 |
- |
|
| 128 |
- // MaxConcurrentUploads is the maximum number of uploads that |
|
| 129 |
- // may take place at a time for each push. |
|
| 130 |
- MaxConcurrentUploads *int `json:"max-concurrent-uploads,omitempty"` |
|
| 131 |
- |
|
| 132 |
- // ShutdownTimeout is the timeout value (in seconds) the daemon will wait for the container |
|
| 133 |
- // to stop when daemon is being shutdown |
|
| 134 |
- ShutdownTimeout int `json:"shutdown-timeout,omitempty"` |
|
| 135 |
- |
|
| 136 |
- Debug bool `json:"debug,omitempty"` |
|
| 137 |
- Hosts []string `json:"hosts,omitempty"` |
|
| 138 |
- LogLevel string `json:"log-level,omitempty"` |
|
| 139 |
- TLS bool `json:"tls,omitempty"` |
|
| 140 |
- TLSVerify bool `json:"tlsverify,omitempty"` |
|
| 141 |
- |
|
| 142 |
- // Embedded structs that allow config |
|
| 143 |
- // deserialization without the full struct. |
|
| 144 |
- CommonTLSOptions |
|
| 145 |
- |
|
| 146 |
- // SwarmDefaultAdvertiseAddr is the default host/IP or network interface |
|
| 147 |
- // to use if a wildcard address is specified in the ListenAddr value |
|
| 148 |
- // given to the /swarm/init endpoint and no advertise address is |
|
| 149 |
- // specified. |
|
| 150 |
- SwarmDefaultAdvertiseAddr string `json:"swarm-default-advertise-addr"` |
|
| 151 |
- MetricsAddress string `json:"metrics-addr"` |
|
| 152 |
- |
|
| 153 |
- LogConfig |
|
| 154 |
- bridgeConfig // bridgeConfig holds bridge network specific configuration. |
|
| 155 |
- registry.ServiceOptions |
|
| 156 |
- |
|
| 157 |
- reloadLock sync.Mutex |
|
| 158 |
- valuesSet map[string]interface{}
|
|
| 159 |
- |
|
| 160 |
- Experimental bool `json:"experimental"` // Experimental indicates whether experimental features should be exposed or not |
|
| 161 |
-} |
|
| 162 |
- |
|
| 163 |
-// InstallCommonFlags adds flags to the pflag.FlagSet to configure the daemon |
|
| 164 |
-func (config *Config) InstallCommonFlags(flags *pflag.FlagSet) {
|
|
| 165 |
- var maxConcurrentDownloads, maxConcurrentUploads int |
|
| 166 |
- |
|
| 167 |
- config.ServiceOptions.InstallCliFlags(flags) |
|
| 168 |
- |
|
| 169 |
- flags.Var(opts.NewNamedListOptsRef("storage-opts", &config.GraphOptions, nil), "storage-opt", "Storage driver options")
|
|
| 170 |
- flags.Var(opts.NewNamedListOptsRef("authorization-plugins", &config.AuthorizationPlugins, nil), "authorization-plugin", "Authorization plugins to load")
|
|
| 171 |
- flags.Var(opts.NewNamedListOptsRef("exec-opts", &config.ExecOptions, nil), "exec-opt", "Runtime execution options")
|
|
| 172 |
- flags.StringVarP(&config.Pidfile, "pidfile", "p", defaultPidFile, "Path to use for daemon PID file") |
|
| 173 |
- flags.StringVarP(&config.Root, "graph", "g", defaultGraph, "Root of the Docker runtime") |
|
| 174 |
- flags.BoolVarP(&config.AutoRestart, "restart", "r", true, "--restart on the daemon has been deprecated in favor of --restart policies on docker run") |
|
| 175 |
- flags.MarkDeprecated("restart", "Please use a restart policy on docker run")
|
|
| 176 |
- flags.StringVarP(&config.GraphDriver, "storage-driver", "s", "", "Storage driver to use") |
|
| 177 |
- flags.IntVar(&config.Mtu, "mtu", 0, "Set the containers network MTU") |
|
| 178 |
- flags.BoolVar(&config.RawLogs, "raw-logs", false, "Full timestamps without ANSI coloring") |
|
| 179 |
- // FIXME: why the inconsistency between "hosts" and "sockets"? |
|
| 180 |
- flags.Var(opts.NewListOptsRef(&config.DNS, opts.ValidateIPAddress), "dns", "DNS server to use") |
|
| 181 |
- flags.Var(opts.NewNamedListOptsRef("dns-opts", &config.DNSOptions, nil), "dns-opt", "DNS options to use")
|
|
| 182 |
- flags.Var(opts.NewListOptsRef(&config.DNSSearch, opts.ValidateDNSSearch), "dns-search", "DNS search domains to use") |
|
| 183 |
- flags.Var(opts.NewNamedListOptsRef("labels", &config.Labels, opts.ValidateLabel), "label", "Set key=value labels to the daemon")
|
|
| 184 |
- flags.StringVar(&config.LogConfig.Type, "log-driver", "json-file", "Default driver for container logs") |
|
| 185 |
- flags.Var(opts.NewNamedMapOpts("log-opts", config.LogConfig.Config, nil), "log-opt", "Default log driver options for containers")
|
|
| 186 |
- flags.StringVar(&config.ClusterAdvertise, "cluster-advertise", "", "Address or interface name to advertise") |
|
| 187 |
- flags.StringVar(&config.ClusterStore, "cluster-store", "", "URL of the distributed storage backend") |
|
| 188 |
- flags.Var(opts.NewNamedMapOpts("cluster-store-opts", config.ClusterOpts, nil), "cluster-store-opt", "Set cluster store options")
|
|
| 189 |
- flags.StringVar(&config.CorsHeaders, "api-cors-header", "", "Set CORS headers in the Engine API") |
|
| 190 |
- flags.IntVar(&maxConcurrentDownloads, "max-concurrent-downloads", defaultMaxConcurrentDownloads, "Set the max concurrent downloads for each pull") |
|
| 191 |
- flags.IntVar(&maxConcurrentUploads, "max-concurrent-uploads", defaultMaxConcurrentUploads, "Set the max concurrent uploads for each push") |
|
| 192 |
- flags.IntVar(&config.ShutdownTimeout, "shutdown-timeout", defaultShutdownTimeout, "Set the default shutdown timeout") |
|
| 193 |
- |
|
| 194 |
- flags.StringVar(&config.SwarmDefaultAdvertiseAddr, "swarm-default-advertise-addr", "", "Set default address or interface for swarm advertised address") |
|
| 195 |
- flags.BoolVar(&config.Experimental, "experimental", false, "Enable experimental features") |
|
| 196 |
- |
|
| 197 |
- flags.StringVar(&config.MetricsAddress, "metrics-addr", "", "Set default address and port to serve the metrics api on") |
|
| 198 |
- |
|
| 199 |
- config.MaxConcurrentDownloads = &maxConcurrentDownloads |
|
| 200 |
- config.MaxConcurrentUploads = &maxConcurrentUploads |
|
| 201 |
-} |
|
| 202 |
- |
|
| 203 |
-// IsValueSet returns true if a configuration value |
|
| 204 |
-// was explicitly set in the configuration file. |
|
| 205 |
-func (config *Config) IsValueSet(name string) bool {
|
|
| 206 |
- if config.valuesSet == nil {
|
|
| 207 |
- return false |
|
| 208 |
- } |
|
| 209 |
- _, ok := config.valuesSet[name] |
|
| 210 |
- return ok |
|
| 211 |
-} |
|
| 212 |
- |
|
| 213 |
-// NewConfig returns a new fully initialized Config struct |
|
| 214 |
-func NewConfig() *Config {
|
|
| 215 |
- config := Config{}
|
|
| 216 |
- config.LogConfig.Config = make(map[string]string) |
|
| 217 |
- config.ClusterOpts = make(map[string]string) |
|
| 218 |
- |
|
| 219 |
- if runtime.GOOS != "linux" {
|
|
| 220 |
- config.V2Only = true |
|
| 221 |
- } |
|
| 222 |
- return &config |
|
| 223 |
-} |
|
| 224 |
- |
|
| 225 |
-func parseClusterAdvertiseSettings(clusterStore, clusterAdvertise string) (string, error) {
|
|
| 226 |
- if runtime.GOOS == "solaris" && (clusterAdvertise != "" || clusterStore != "") {
|
|
| 227 |
- return "", errors.New("Cluster Advertise Settings not supported on Solaris")
|
|
| 228 |
- } |
|
| 229 |
- if clusterAdvertise == "" {
|
|
| 230 |
- return "", errDiscoveryDisabled |
|
| 231 |
- } |
|
| 232 |
- if clusterStore == "" {
|
|
| 233 |
- return "", errors.New("invalid cluster configuration. --cluster-advertise must be accompanied by --cluster-store configuration")
|
|
| 234 |
- } |
|
| 235 |
- |
|
| 236 |
- advertise, err := discovery.ParseAdvertise(clusterAdvertise) |
|
| 237 |
- if err != nil {
|
|
| 238 |
- return "", fmt.Errorf("discovery advertise parsing failed (%v)", err)
|
|
| 239 |
- } |
|
| 240 |
- return advertise, nil |
|
| 241 |
-} |
|
| 242 |
- |
|
| 243 |
-// GetConflictFreeLabels validates Labels for conflict |
|
| 244 |
-// In swarm the duplicates for labels are removed |
|
| 245 |
-// so we only take same values here, no conflict values |
|
| 246 |
-// If the key-value is the same we will only take the last label |
|
| 247 |
-func GetConflictFreeLabels(labels []string) ([]string, error) {
|
|
| 248 |
- labelMap := map[string]string{}
|
|
| 249 |
- for _, label := range labels {
|
|
| 250 |
- stringSlice := strings.SplitN(label, "=", 2) |
|
| 251 |
- if len(stringSlice) > 1 {
|
|
| 252 |
- // If there is a conflict we will return an error |
|
| 253 |
- if v, ok := labelMap[stringSlice[0]]; ok && v != stringSlice[1] {
|
|
| 254 |
- return nil, fmt.Errorf("conflict labels for %s=%s and %s=%s", stringSlice[0], stringSlice[1], stringSlice[0], v)
|
|
| 255 |
- } |
|
| 256 |
- labelMap[stringSlice[0]] = stringSlice[1] |
|
| 257 |
- } |
|
| 258 |
- } |
|
| 259 |
- |
|
| 260 |
- newLabels := []string{}
|
|
| 261 |
- for k, v := range labelMap {
|
|
| 262 |
- newLabels = append(newLabels, fmt.Sprintf("%s=%s", k, v))
|
|
| 263 |
- } |
|
| 264 |
- return newLabels, nil |
|
| 265 |
-} |
|
| 266 |
- |
|
| 267 |
-// ReloadConfiguration reads the configuration in the host and reloads the daemon and server. |
|
| 268 |
-func ReloadConfiguration(configFile string, flags *pflag.FlagSet, reload func(*Config)) error {
|
|
| 269 |
- logrus.Infof("Got signal to reload configuration, reloading from: %s", configFile)
|
|
| 270 |
- newConfig, err := getConflictFreeConfiguration(configFile, flags) |
|
| 271 |
- if err != nil {
|
|
| 272 |
- return err |
|
| 273 |
- } |
|
| 274 |
- |
|
| 275 |
- if err := ValidateConfiguration(newConfig); err != nil {
|
|
| 276 |
- return fmt.Errorf("file configuration validation failed (%v)", err)
|
|
| 277 |
- } |
|
| 278 |
- |
|
| 279 |
- // Labels of the docker engine used to allow multiple values associated with the same key. |
|
| 280 |
- // This is deprecated in 1.13, and, be removed after 3 release cycles. |
|
| 281 |
- // The following will check the conflict of labels, and report a warning for deprecation. |
|
| 282 |
- // |
|
| 283 |
- // TODO: After 3 release cycles (1.16) an error will be returned, and labels will be |
|
| 284 |
- // sanitized to consolidate duplicate key-value pairs (config.Labels = newLabels): |
|
| 285 |
- // |
|
| 286 |
- // newLabels, err := GetConflictFreeLabels(newConfig.Labels) |
|
| 287 |
- // if err != nil {
|
|
| 288 |
- // return err |
|
| 289 |
- // } |
|
| 290 |
- // newConfig.Labels = newLabels |
|
| 291 |
- // |
|
| 292 |
- if _, err := GetConflictFreeLabels(newConfig.Labels); err != nil {
|
|
| 293 |
- logrus.Warnf("Engine labels with duplicate keys and conflicting values have been deprecated: %s", err)
|
|
| 294 |
- } |
|
| 295 |
- |
|
| 296 |
- reload(newConfig) |
|
| 297 |
- return nil |
|
| 298 |
-} |
|
| 299 |
- |
|
| 300 |
-// boolValue is an interface that boolean value flags implement |
|
| 301 |
-// to tell the command line how to make -name equivalent to -name=true. |
|
| 302 |
-type boolValue interface {
|
|
| 303 |
- IsBoolFlag() bool |
|
| 304 |
-} |
|
| 305 |
- |
|
| 306 |
-// MergeDaemonConfigurations reads a configuration file, |
|
| 307 |
-// loads the file configuration in an isolated structure, |
|
| 308 |
-// and merges the configuration provided from flags on top |
|
| 309 |
-// if there are no conflicts. |
|
| 310 |
-func MergeDaemonConfigurations(flagsConfig *Config, flags *pflag.FlagSet, configFile string) (*Config, error) {
|
|
| 311 |
- fileConfig, err := getConflictFreeConfiguration(configFile, flags) |
|
| 312 |
- if err != nil {
|
|
| 313 |
- return nil, err |
|
| 314 |
- } |
|
| 315 |
- |
|
| 316 |
- if err := ValidateConfiguration(fileConfig); err != nil {
|
|
| 317 |
- return nil, fmt.Errorf("file configuration validation failed (%v)", err)
|
|
| 318 |
- } |
|
| 319 |
- |
|
| 320 |
- // merge flags configuration on top of the file configuration |
|
| 321 |
- if err := mergo.Merge(fileConfig, flagsConfig); err != nil {
|
|
| 322 |
- return nil, err |
|
| 323 |
- } |
|
| 324 |
- |
|
| 325 |
- // We need to validate again once both fileConfig and flagsConfig |
|
| 326 |
- // have been merged |
|
| 327 |
- if err := ValidateConfiguration(fileConfig); err != nil {
|
|
| 328 |
- return nil, fmt.Errorf("file configuration validation failed (%v)", err)
|
|
| 329 |
- } |
|
| 330 |
- |
|
| 331 |
- return fileConfig, nil |
|
| 332 |
-} |
|
| 333 |
- |
|
| 334 |
-// getConflictFreeConfiguration loads the configuration from a JSON file. |
|
| 335 |
-// It compares that configuration with the one provided by the flags, |
|
| 336 |
-// and returns an error if there are conflicts. |
|
| 337 |
-func getConflictFreeConfiguration(configFile string, flags *pflag.FlagSet) (*Config, error) {
|
|
| 338 |
- b, err := ioutil.ReadFile(configFile) |
|
| 339 |
- if err != nil {
|
|
| 340 |
- return nil, err |
|
| 341 |
- } |
|
| 342 |
- |
|
| 343 |
- var config Config |
|
| 344 |
- var reader io.Reader |
|
| 345 |
- if flags != nil {
|
|
| 346 |
- var jsonConfig map[string]interface{}
|
|
| 347 |
- reader = bytes.NewReader(b) |
|
| 348 |
- if err := json.NewDecoder(reader).Decode(&jsonConfig); err != nil {
|
|
| 349 |
- return nil, err |
|
| 350 |
- } |
|
| 351 |
- |
|
| 352 |
- configSet := configValuesSet(jsonConfig) |
|
| 353 |
- |
|
| 354 |
- if err := findConfigurationConflicts(configSet, flags); err != nil {
|
|
| 355 |
- return nil, err |
|
| 356 |
- } |
|
| 357 |
- |
|
| 358 |
- // Override flag values to make sure the values set in the config file with nullable values, like `false`, |
|
| 359 |
- // are not overridden by default truthy values from the flags that were not explicitly set. |
|
| 360 |
- // See https://github.com/docker/docker/issues/20289 for an example. |
|
| 361 |
- // |
|
| 362 |
- // TODO: Rewrite configuration logic to avoid same issue with other nullable values, like numbers. |
|
| 363 |
- namedOptions := make(map[string]interface{})
|
|
| 364 |
- for key, value := range configSet {
|
|
| 365 |
- f := flags.Lookup(key) |
|
| 366 |
- if f == nil { // ignore named flags that don't match
|
|
| 367 |
- namedOptions[key] = value |
|
| 368 |
- continue |
|
| 369 |
- } |
|
| 370 |
- |
|
| 371 |
- if _, ok := f.Value.(boolValue); ok {
|
|
| 372 |
- f.Value.Set(fmt.Sprintf("%v", value))
|
|
| 373 |
- } |
|
| 374 |
- } |
|
| 375 |
- if len(namedOptions) > 0 {
|
|
| 376 |
- // set also default for mergeVal flags that are boolValue at the same time. |
|
| 377 |
- flags.VisitAll(func(f *pflag.Flag) {
|
|
| 378 |
- if opt, named := f.Value.(opts.NamedOption); named {
|
|
| 379 |
- v, set := namedOptions[opt.Name()] |
|
| 380 |
- _, boolean := f.Value.(boolValue) |
|
| 381 |
- if set && boolean {
|
|
| 382 |
- f.Value.Set(fmt.Sprintf("%v", v))
|
|
| 383 |
- } |
|
| 384 |
- } |
|
| 385 |
- }) |
|
| 386 |
- } |
|
| 387 |
- |
|
| 388 |
- config.valuesSet = configSet |
|
| 389 |
- } |
|
| 390 |
- |
|
| 391 |
- reader = bytes.NewReader(b) |
|
| 392 |
- err = json.NewDecoder(reader).Decode(&config) |
|
| 393 |
- return &config, err |
|
| 394 |
-} |
|
| 395 |
- |
|
| 396 |
-// configValuesSet returns the configuration values explicitly set in the file. |
|
| 397 |
-func configValuesSet(config map[string]interface{}) map[string]interface{} {
|
|
| 398 |
- flatten := make(map[string]interface{})
|
|
| 399 |
- for k, v := range config {
|
|
| 400 |
- if m, isMap := v.(map[string]interface{}); isMap && !flatOptions[k] {
|
|
| 401 |
- for km, vm := range m {
|
|
| 402 |
- flatten[km] = vm |
|
| 403 |
- } |
|
| 404 |
- continue |
|
| 405 |
- } |
|
| 406 |
- |
|
| 407 |
- flatten[k] = v |
|
| 408 |
- } |
|
| 409 |
- return flatten |
|
| 410 |
-} |
|
| 411 |
- |
|
| 412 |
-// findConfigurationConflicts iterates over the provided flags searching for |
|
| 413 |
-// duplicated configurations and unknown keys. It returns an error with all the conflicts if |
|
| 414 |
-// it finds any. |
|
| 415 |
-func findConfigurationConflicts(config map[string]interface{}, flags *pflag.FlagSet) error {
|
|
| 416 |
- // 1. Search keys from the file that we don't recognize as flags. |
|
| 417 |
- unknownKeys := make(map[string]interface{})
|
|
| 418 |
- for key, value := range config {
|
|
| 419 |
- if flag := flags.Lookup(key); flag == nil {
|
|
| 420 |
- unknownKeys[key] = value |
|
| 421 |
- } |
|
| 422 |
- } |
|
| 423 |
- |
|
| 424 |
- // 2. Discard values that implement NamedOption. |
|
| 425 |
- // Their configuration name differs from their flag name, like `labels` and `label`. |
|
| 426 |
- if len(unknownKeys) > 0 {
|
|
| 427 |
- unknownNamedConflicts := func(f *pflag.Flag) {
|
|
| 428 |
- if namedOption, ok := f.Value.(opts.NamedOption); ok {
|
|
| 429 |
- if _, valid := unknownKeys[namedOption.Name()]; valid {
|
|
| 430 |
- delete(unknownKeys, namedOption.Name()) |
|
| 431 |
- } |
|
| 432 |
- } |
|
| 433 |
- } |
|
| 434 |
- flags.VisitAll(unknownNamedConflicts) |
|
| 435 |
- } |
|
| 436 |
- |
|
| 437 |
- if len(unknownKeys) > 0 {
|
|
| 438 |
- var unknown []string |
|
| 439 |
- for key := range unknownKeys {
|
|
| 440 |
- unknown = append(unknown, key) |
|
| 441 |
- } |
|
| 442 |
- return fmt.Errorf("the following directives don't match any configuration option: %s", strings.Join(unknown, ", "))
|
|
| 443 |
- } |
|
| 444 |
- |
|
| 445 |
- var conflicts []string |
|
| 446 |
- printConflict := func(name string, flagValue, fileValue interface{}) string {
|
|
| 447 |
- return fmt.Sprintf("%s: (from flag: %v, from file: %v)", name, flagValue, fileValue)
|
|
| 448 |
- } |
|
| 449 |
- |
|
| 450 |
- // 3. Search keys that are present as a flag and as a file option. |
|
| 451 |
- duplicatedConflicts := func(f *pflag.Flag) {
|
|
| 452 |
- // search option name in the json configuration payload if the value is a named option |
|
| 453 |
- if namedOption, ok := f.Value.(opts.NamedOption); ok {
|
|
| 454 |
- if optsValue, ok := config[namedOption.Name()]; ok {
|
|
| 455 |
- conflicts = append(conflicts, printConflict(namedOption.Name(), f.Value.String(), optsValue)) |
|
| 456 |
- } |
|
| 457 |
- } else {
|
|
| 458 |
- // search flag name in the json configuration payload |
|
| 459 |
- for _, name := range []string{f.Name, f.Shorthand} {
|
|
| 460 |
- if value, ok := config[name]; ok {
|
|
| 461 |
- conflicts = append(conflicts, printConflict(name, f.Value.String(), value)) |
|
| 462 |
- break |
|
| 463 |
- } |
|
| 464 |
- } |
|
| 465 |
- } |
|
| 466 |
- } |
|
| 467 |
- |
|
| 468 |
- flags.Visit(duplicatedConflicts) |
|
| 469 |
- |
|
| 470 |
- if len(conflicts) > 0 {
|
|
| 471 |
- return fmt.Errorf("the following directives are specified both as a flag and in the configuration file: %s", strings.Join(conflicts, ", "))
|
|
| 472 |
- } |
|
| 473 |
- return nil |
|
| 474 |
-} |
|
| 475 |
- |
|
| 476 |
-// ValidateConfiguration validates some specific configs. |
|
| 477 |
-// such as config.DNS, config.Labels, config.DNSSearch, |
|
| 478 |
-// as well as config.MaxConcurrentDownloads, config.MaxConcurrentUploads. |
|
| 479 |
-func ValidateConfiguration(config *Config) error {
|
|
| 480 |
- // validate DNS |
|
| 481 |
- for _, dns := range config.DNS {
|
|
| 482 |
- if _, err := opts.ValidateIPAddress(dns); err != nil {
|
|
| 483 |
- return err |
|
| 484 |
- } |
|
| 485 |
- } |
|
| 486 |
- |
|
| 487 |
- // validate DNSSearch |
|
| 488 |
- for _, dnsSearch := range config.DNSSearch {
|
|
| 489 |
- if _, err := opts.ValidateDNSSearch(dnsSearch); err != nil {
|
|
| 490 |
- return err |
|
| 491 |
- } |
|
| 492 |
- } |
|
| 493 |
- |
|
| 494 |
- // validate Labels |
|
| 495 |
- for _, label := range config.Labels {
|
|
| 496 |
- if _, err := opts.ValidateLabel(label); err != nil {
|
|
| 497 |
- return err |
|
| 498 |
- } |
|
| 499 |
- } |
|
| 500 |
- |
|
| 501 |
- // validate MaxConcurrentDownloads |
|
| 502 |
- if config.IsValueSet("max-concurrent-downloads") && config.MaxConcurrentDownloads != nil && *config.MaxConcurrentDownloads < 0 {
|
|
| 503 |
- return fmt.Errorf("invalid max concurrent downloads: %d", *config.MaxConcurrentDownloads)
|
|
| 504 |
- } |
|
| 505 |
- |
|
| 506 |
- // validate MaxConcurrentUploads |
|
| 507 |
- if config.IsValueSet("max-concurrent-uploads") && config.MaxConcurrentUploads != nil && *config.MaxConcurrentUploads < 0 {
|
|
| 508 |
- return fmt.Errorf("invalid max concurrent uploads: %d", *config.MaxConcurrentUploads)
|
|
| 509 |
- } |
|
| 510 |
- |
|
| 511 |
- // validate that "default" runtime is not reset |
|
| 512 |
- if runtimes := config.GetAllRuntimes(); len(runtimes) > 0 {
|
|
| 513 |
- if _, ok := runtimes[stockRuntimeName]; ok {
|
|
| 514 |
- return fmt.Errorf("runtime name '%s' is reserved", stockRuntimeName)
|
|
| 515 |
- } |
|
| 516 |
- } |
|
| 517 |
- |
|
| 518 |
- if defaultRuntime := config.GetDefaultRuntimeName(); defaultRuntime != "" && defaultRuntime != stockRuntimeName {
|
|
| 519 |
- runtimes := config.GetAllRuntimes() |
|
| 520 |
- if _, ok := runtimes[defaultRuntime]; !ok {
|
|
| 521 |
- return fmt.Errorf("specified default runtime '%s' does not exist", defaultRuntime)
|
|
| 522 |
- } |
|
| 523 |
- } |
|
| 524 |
- |
|
| 525 |
- return nil |
|
| 526 |
-} |
|
| 527 |
- |
|
| 528 |
-// GetAuthorizationPlugins returns daemon's sorted authorization plugins |
|
| 529 |
-func (config *Config) GetAuthorizationPlugins() []string {
|
|
| 530 |
- config.reloadLock.Lock() |
|
| 531 |
- defer config.reloadLock.Unlock() |
|
| 532 |
- |
|
| 533 |
- authPlugins := make([]string, 0, len(config.AuthorizationPlugins)) |
|
| 534 |
- for _, p := range config.AuthorizationPlugins {
|
|
| 535 |
- authPlugins = append(authPlugins, p) |
|
| 536 |
- } |
|
| 537 |
- sort.Strings(authPlugins) |
|
| 538 |
- return authPlugins |
|
| 539 |
-} |
| 540 | 1 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,516 @@ |
| 0 |
+package config |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "bytes" |
|
| 4 |
+ "encoding/json" |
|
| 5 |
+ "errors" |
|
| 6 |
+ "fmt" |
|
| 7 |
+ "io" |
|
| 8 |
+ "io/ioutil" |
|
| 9 |
+ "reflect" |
|
| 10 |
+ "runtime" |
|
| 11 |
+ "sort" |
|
| 12 |
+ "strings" |
|
| 13 |
+ "sync" |
|
| 14 |
+ |
|
| 15 |
+ "github.com/Sirupsen/logrus" |
|
| 16 |
+ daemondiscovery "github.com/docker/docker/daemon/discovery" |
|
| 17 |
+ "github.com/docker/docker/opts" |
|
| 18 |
+ "github.com/docker/docker/pkg/discovery" |
|
| 19 |
+ "github.com/docker/docker/registry" |
|
| 20 |
+ "github.com/imdario/mergo" |
|
| 21 |
+ "github.com/spf13/pflag" |
|
| 22 |
+) |
|
| 23 |
+ |
|
| 24 |
+const ( |
|
| 25 |
+ // DefaultMaxConcurrentDownloads is the default value for |
|
| 26 |
+ // maximum number of downloads that |
|
| 27 |
+ // may take place at a time for each pull. |
|
| 28 |
+ DefaultMaxConcurrentDownloads = 3 |
|
| 29 |
+ // DefaultMaxConcurrentUploads is the default value for |
|
| 30 |
+ // maximum number of uploads that |
|
| 31 |
+ // may take place at a time for each push. |
|
| 32 |
+ DefaultMaxConcurrentUploads = 5 |
|
| 33 |
+ // StockRuntimeName is the reserved name/alias used to represent the |
|
| 34 |
+ // OCI runtime being shipped with the docker daemon package. |
|
| 35 |
+ StockRuntimeName = "runc" |
|
| 36 |
+ // DefaultShmSize is the default value for container's shm size |
|
| 37 |
+ DefaultShmSize = int64(67108864) |
|
| 38 |
+ // DefaultNetworkMtu is the default value for network MTU |
|
| 39 |
+ DefaultNetworkMtu = 1500 |
|
| 40 |
+ // DisableNetworkBridge is the default value of the option to disable network bridge |
|
| 41 |
+ DisableNetworkBridge = "none" |
|
| 42 |
+) |
|
| 43 |
+ |
|
| 44 |
+// flatOptions contains configuration keys |
|
| 45 |
+// that MUST NOT be parsed as deep structures. |
|
| 46 |
+// Use this to differentiate these options |
|
| 47 |
+// with others like the ones in CommonTLSOptions. |
|
| 48 |
+var flatOptions = map[string]bool{
|
|
| 49 |
+ "cluster-store-opts": true, |
|
| 50 |
+ "log-opts": true, |
|
| 51 |
+ "runtimes": true, |
|
| 52 |
+ "default-ulimits": true, |
|
| 53 |
+} |
|
| 54 |
+ |
|
| 55 |
+// LogConfig represents the default log configuration. |
|
| 56 |
+// It includes json tags to deserialize configuration from a file |
|
| 57 |
+// using the same names that the flags in the command line use. |
|
| 58 |
+type LogConfig struct {
|
|
| 59 |
+ Type string `json:"log-driver,omitempty"` |
|
| 60 |
+ Config map[string]string `json:"log-opts,omitempty"` |
|
| 61 |
+} |
|
| 62 |
+ |
|
| 63 |
+// commonBridgeConfig stores all the platform-common bridge driver specific |
|
| 64 |
+// configuration. |
|
| 65 |
+type commonBridgeConfig struct {
|
|
| 66 |
+ Iface string `json:"bridge,omitempty"` |
|
| 67 |
+ FixedCIDR string `json:"fixed-cidr,omitempty"` |
|
| 68 |
+} |
|
| 69 |
+ |
|
| 70 |
+// CommonTLSOptions defines TLS configuration for the daemon server. |
|
| 71 |
+// It includes json tags to deserialize configuration from a file |
|
| 72 |
+// using the same names that the flags in the command line use. |
|
| 73 |
+type CommonTLSOptions struct {
|
|
| 74 |
+ CAFile string `json:"tlscacert,omitempty"` |
|
| 75 |
+ CertFile string `json:"tlscert,omitempty"` |
|
| 76 |
+ KeyFile string `json:"tlskey,omitempty"` |
|
| 77 |
+} |
|
| 78 |
+ |
|
| 79 |
+// CommonConfig defines the configuration of a docker daemon which is |
|
| 80 |
+// common across platforms. |
|
| 81 |
+// It includes json tags to deserialize configuration from a file |
|
| 82 |
+// using the same names that the flags in the command line use. |
|
| 83 |
+type CommonConfig struct {
|
|
| 84 |
+ AuthorizationPlugins []string `json:"authorization-plugins,omitempty"` // AuthorizationPlugins holds list of authorization plugins |
|
| 85 |
+ AutoRestart bool `json:"-"` |
|
| 86 |
+ Context map[string][]string `json:"-"` |
|
| 87 |
+ DisableBridge bool `json:"-"` |
|
| 88 |
+ DNS []string `json:"dns,omitempty"` |
|
| 89 |
+ DNSOptions []string `json:"dns-opts,omitempty"` |
|
| 90 |
+ DNSSearch []string `json:"dns-search,omitempty"` |
|
| 91 |
+ ExecOptions []string `json:"exec-opts,omitempty"` |
|
| 92 |
+ GraphDriver string `json:"storage-driver,omitempty"` |
|
| 93 |
+ GraphOptions []string `json:"storage-opts,omitempty"` |
|
| 94 |
+ Labels []string `json:"labels,omitempty"` |
|
| 95 |
+ Mtu int `json:"mtu,omitempty"` |
|
| 96 |
+ Pidfile string `json:"pidfile,omitempty"` |
|
| 97 |
+ RawLogs bool `json:"raw-logs,omitempty"` |
|
| 98 |
+ Root string `json:"graph,omitempty"` |
|
| 99 |
+ SocketGroup string `json:"group,omitempty"` |
|
| 100 |
+ TrustKeyPath string `json:"-"` |
|
| 101 |
+ CorsHeaders string `json:"api-cors-header,omitempty"` |
|
| 102 |
+ EnableCors bool `json:"api-enable-cors,omitempty"` |
|
| 103 |
+ |
|
| 104 |
+ // LiveRestoreEnabled determines whether we should keep containers |
|
| 105 |
+ // alive upon daemon shutdown/start |
|
| 106 |
+ LiveRestoreEnabled bool `json:"live-restore,omitempty"` |
|
| 107 |
+ |
|
| 108 |
+ // ClusterStore is the storage backend used for the cluster information. It is used by both |
|
| 109 |
+ // multihost networking (to store networks and endpoints information) and by the node discovery |
|
| 110 |
+ // mechanism. |
|
| 111 |
+ ClusterStore string `json:"cluster-store,omitempty"` |
|
| 112 |
+ |
|
| 113 |
+ // ClusterOpts is used to pass options to the discovery package for tuning libkv settings, such |
|
| 114 |
+ // as TLS configuration settings. |
|
| 115 |
+ ClusterOpts map[string]string `json:"cluster-store-opts,omitempty"` |
|
| 116 |
+ |
|
| 117 |
+ // ClusterAdvertise is the network endpoint that the Engine advertises for the purpose of node |
|
| 118 |
+ // discovery. This should be a 'host:port' combination on which that daemon instance is |
|
| 119 |
+ // reachable by other hosts. |
|
| 120 |
+ ClusterAdvertise string `json:"cluster-advertise,omitempty"` |
|
| 121 |
+ |
|
| 122 |
+ // MaxConcurrentDownloads is the maximum number of downloads that |
|
| 123 |
+ // may take place at a time for each pull. |
|
| 124 |
+ MaxConcurrentDownloads *int `json:"max-concurrent-downloads,omitempty"` |
|
| 125 |
+ |
|
| 126 |
+ // MaxConcurrentUploads is the maximum number of uploads that |
|
| 127 |
+ // may take place at a time for each push. |
|
| 128 |
+ MaxConcurrentUploads *int `json:"max-concurrent-uploads,omitempty"` |
|
| 129 |
+ |
|
| 130 |
+ // ShutdownTimeout is the timeout value (in seconds) the daemon will wait for the container |
|
| 131 |
+ // to stop when daemon is being shutdown |
|
| 132 |
+ ShutdownTimeout int `json:"shutdown-timeout,omitempty"` |
|
| 133 |
+ |
|
| 134 |
+ Debug bool `json:"debug,omitempty"` |
|
| 135 |
+ Hosts []string `json:"hosts,omitempty"` |
|
| 136 |
+ LogLevel string `json:"log-level,omitempty"` |
|
| 137 |
+ TLS bool `json:"tls,omitempty"` |
|
| 138 |
+ TLSVerify bool `json:"tlsverify,omitempty"` |
|
| 139 |
+ |
|
| 140 |
+ // Embedded structs that allow config |
|
| 141 |
+ // deserialization without the full struct. |
|
| 142 |
+ CommonTLSOptions |
|
| 143 |
+ |
|
| 144 |
+ // SwarmDefaultAdvertiseAddr is the default host/IP or network interface |
|
| 145 |
+ // to use if a wildcard address is specified in the ListenAddr value |
|
| 146 |
+ // given to the /swarm/init endpoint and no advertise address is |
|
| 147 |
+ // specified. |
|
| 148 |
+ SwarmDefaultAdvertiseAddr string `json:"swarm-default-advertise-addr"` |
|
| 149 |
+ MetricsAddress string `json:"metrics-addr"` |
|
| 150 |
+ |
|
| 151 |
+ LogConfig |
|
| 152 |
+ BridgeConfig // bridgeConfig holds bridge network specific configuration. |
|
| 153 |
+ registry.ServiceOptions |
|
| 154 |
+ |
|
| 155 |
+ sync.Mutex |
|
| 156 |
+ // FIXME(vdemeester) This part is not that clear and is mainly dependent on cli flags |
|
| 157 |
+ // It should probably be handled outside this package. |
|
| 158 |
+ ValuesSet map[string]interface{}
|
|
| 159 |
+ |
|
| 160 |
+ Experimental bool `json:"experimental"` // Experimental indicates whether experimental features should be exposed or not |
|
| 161 |
+} |
|
| 162 |
+ |
|
| 163 |
+// IsValueSet returns true if a configuration value |
|
| 164 |
+// was explicitly set in the configuration file. |
|
| 165 |
+func (conf *Config) IsValueSet(name string) bool {
|
|
| 166 |
+ if conf.ValuesSet == nil {
|
|
| 167 |
+ return false |
|
| 168 |
+ } |
|
| 169 |
+ _, ok := conf.ValuesSet[name] |
|
| 170 |
+ return ok |
|
| 171 |
+} |
|
| 172 |
+ |
|
| 173 |
+// New returns a new fully initialized Config struct |
|
| 174 |
+func New() *Config {
|
|
| 175 |
+ config := Config{}
|
|
| 176 |
+ config.LogConfig.Config = make(map[string]string) |
|
| 177 |
+ config.ClusterOpts = make(map[string]string) |
|
| 178 |
+ |
|
| 179 |
+ if runtime.GOOS != "linux" {
|
|
| 180 |
+ config.V2Only = true |
|
| 181 |
+ } |
|
| 182 |
+ return &config |
|
| 183 |
+} |
|
| 184 |
+ |
|
| 185 |
+// ParseClusterAdvertiseSettings parses the specified advertise settings |
|
| 186 |
+func ParseClusterAdvertiseSettings(clusterStore, clusterAdvertise string) (string, error) {
|
|
| 187 |
+ if runtime.GOOS == "solaris" && (clusterAdvertise != "" || clusterStore != "") {
|
|
| 188 |
+ return "", errors.New("Cluster Advertise Settings not supported on Solaris")
|
|
| 189 |
+ } |
|
| 190 |
+ if clusterAdvertise == "" {
|
|
| 191 |
+ return "", daemondiscovery.ErrDiscoveryDisabled |
|
| 192 |
+ } |
|
| 193 |
+ if clusterStore == "" {
|
|
| 194 |
+ return "", errors.New("invalid cluster configuration. --cluster-advertise must be accompanied by --cluster-store configuration")
|
|
| 195 |
+ } |
|
| 196 |
+ |
|
| 197 |
+ advertise, err := discovery.ParseAdvertise(clusterAdvertise) |
|
| 198 |
+ if err != nil {
|
|
| 199 |
+ return "", fmt.Errorf("discovery advertise parsing failed (%v)", err)
|
|
| 200 |
+ } |
|
| 201 |
+ return advertise, nil |
|
| 202 |
+} |
|
| 203 |
+ |
|
| 204 |
+// GetConflictFreeLabels validates Labels for conflict |
|
| 205 |
+// In swarm the duplicates for labels are removed |
|
| 206 |
+// so we only take same values here, no conflict values |
|
| 207 |
+// If the key-value is the same we will only take the last label |
|
| 208 |
+func GetConflictFreeLabels(labels []string) ([]string, error) {
|
|
| 209 |
+ labelMap := map[string]string{}
|
|
| 210 |
+ for _, label := range labels {
|
|
| 211 |
+ stringSlice := strings.SplitN(label, "=", 2) |
|
| 212 |
+ if len(stringSlice) > 1 {
|
|
| 213 |
+ // If there is a conflict we will return an error |
|
| 214 |
+ if v, ok := labelMap[stringSlice[0]]; ok && v != stringSlice[1] {
|
|
| 215 |
+ return nil, fmt.Errorf("conflict labels for %s=%s and %s=%s", stringSlice[0], stringSlice[1], stringSlice[0], v)
|
|
| 216 |
+ } |
|
| 217 |
+ labelMap[stringSlice[0]] = stringSlice[1] |
|
| 218 |
+ } |
|
| 219 |
+ } |
|
| 220 |
+ |
|
| 221 |
+ newLabels := []string{}
|
|
| 222 |
+ for k, v := range labelMap {
|
|
| 223 |
+ newLabels = append(newLabels, fmt.Sprintf("%s=%s", k, v))
|
|
| 224 |
+ } |
|
| 225 |
+ return newLabels, nil |
|
| 226 |
+} |
|
| 227 |
+ |
|
| 228 |
+// Reload reads the configuration in the host and reloads the daemon and server. |
|
| 229 |
+func Reload(configFile string, flags *pflag.FlagSet, reload func(*Config)) error {
|
|
| 230 |
+ logrus.Infof("Got signal to reload configuration, reloading from: %s", configFile)
|
|
| 231 |
+ newConfig, err := getConflictFreeConfiguration(configFile, flags) |
|
| 232 |
+ if err != nil {
|
|
| 233 |
+ return err |
|
| 234 |
+ } |
|
| 235 |
+ |
|
| 236 |
+ if err := Validate(newConfig); err != nil {
|
|
| 237 |
+ return fmt.Errorf("file configuration validation failed (%v)", err)
|
|
| 238 |
+ } |
|
| 239 |
+ |
|
| 240 |
+ // Labels of the docker engine used to allow multiple values associated with the same key. |
|
| 241 |
+ // This is deprecated in 1.13, and, be removed after 3 release cycles. |
|
| 242 |
+ // The following will check the conflict of labels, and report a warning for deprecation. |
|
| 243 |
+ // |
|
| 244 |
+ // TODO: After 3 release cycles (1.16) an error will be returned, and labels will be |
|
| 245 |
+ // sanitized to consolidate duplicate key-value pairs (config.Labels = newLabels): |
|
| 246 |
+ // |
|
| 247 |
+ // newLabels, err := GetConflictFreeLabels(newConfig.Labels) |
|
| 248 |
+ // if err != nil {
|
|
| 249 |
+ // return err |
|
| 250 |
+ // } |
|
| 251 |
+ // newConfig.Labels = newLabels |
|
| 252 |
+ // |
|
| 253 |
+ if _, err := GetConflictFreeLabels(newConfig.Labels); err != nil {
|
|
| 254 |
+ logrus.Warnf("Engine labels with duplicate keys and conflicting values have been deprecated: %s", err)
|
|
| 255 |
+ } |
|
| 256 |
+ |
|
| 257 |
+ reload(newConfig) |
|
| 258 |
+ return nil |
|
| 259 |
+} |
|
| 260 |
+ |
|
| 261 |
+// boolValue is an interface that boolean value flags implement |
|
| 262 |
+// to tell the command line how to make -name equivalent to -name=true. |
|
| 263 |
+type boolValue interface {
|
|
| 264 |
+ IsBoolFlag() bool |
|
| 265 |
+} |
|
| 266 |
+ |
|
| 267 |
+// MergeDaemonConfigurations reads a configuration file, |
|
| 268 |
+// loads the file configuration in an isolated structure, |
|
| 269 |
+// and merges the configuration provided from flags on top |
|
| 270 |
+// if there are no conflicts. |
|
| 271 |
+func MergeDaemonConfigurations(flagsConfig *Config, flags *pflag.FlagSet, configFile string) (*Config, error) {
|
|
| 272 |
+ fileConfig, err := getConflictFreeConfiguration(configFile, flags) |
|
| 273 |
+ if err != nil {
|
|
| 274 |
+ return nil, err |
|
| 275 |
+ } |
|
| 276 |
+ |
|
| 277 |
+ if err := Validate(fileConfig); err != nil {
|
|
| 278 |
+ return nil, fmt.Errorf("file configuration validation failed (%v)", err)
|
|
| 279 |
+ } |
|
| 280 |
+ |
|
| 281 |
+ // merge flags configuration on top of the file configuration |
|
| 282 |
+ if err := mergo.Merge(fileConfig, flagsConfig); err != nil {
|
|
| 283 |
+ return nil, err |
|
| 284 |
+ } |
|
| 285 |
+ |
|
| 286 |
+ // We need to validate again once both fileConfig and flagsConfig |
|
| 287 |
+ // have been merged |
|
| 288 |
+ if err := Validate(fileConfig); err != nil {
|
|
| 289 |
+ return nil, fmt.Errorf("file configuration validation failed (%v)", err)
|
|
| 290 |
+ } |
|
| 291 |
+ |
|
| 292 |
+ return fileConfig, nil |
|
| 293 |
+} |
|
| 294 |
+ |
|
| 295 |
+// getConflictFreeConfiguration loads the configuration from a JSON file. |
|
| 296 |
+// It compares that configuration with the one provided by the flags, |
|
| 297 |
+// and returns an error if there are conflicts. |
|
| 298 |
+func getConflictFreeConfiguration(configFile string, flags *pflag.FlagSet) (*Config, error) {
|
|
| 299 |
+ b, err := ioutil.ReadFile(configFile) |
|
| 300 |
+ if err != nil {
|
|
| 301 |
+ return nil, err |
|
| 302 |
+ } |
|
| 303 |
+ |
|
| 304 |
+ var config Config |
|
| 305 |
+ var reader io.Reader |
|
| 306 |
+ if flags != nil {
|
|
| 307 |
+ var jsonConfig map[string]interface{}
|
|
| 308 |
+ reader = bytes.NewReader(b) |
|
| 309 |
+ if err := json.NewDecoder(reader).Decode(&jsonConfig); err != nil {
|
|
| 310 |
+ return nil, err |
|
| 311 |
+ } |
|
| 312 |
+ |
|
| 313 |
+ configSet := configValuesSet(jsonConfig) |
|
| 314 |
+ |
|
| 315 |
+ if err := findConfigurationConflicts(configSet, flags); err != nil {
|
|
| 316 |
+ return nil, err |
|
| 317 |
+ } |
|
| 318 |
+ |
|
| 319 |
+ // Override flag values to make sure the values set in the config file with nullable values, like `false`, |
|
| 320 |
+ // are not overridden by default truthy values from the flags that were not explicitly set. |
|
| 321 |
+ // See https://github.com/docker/docker/issues/20289 for an example. |
|
| 322 |
+ // |
|
| 323 |
+ // TODO: Rewrite configuration logic to avoid same issue with other nullable values, like numbers. |
|
| 324 |
+ namedOptions := make(map[string]interface{})
|
|
| 325 |
+ for key, value := range configSet {
|
|
| 326 |
+ f := flags.Lookup(key) |
|
| 327 |
+ if f == nil { // ignore named flags that don't match
|
|
| 328 |
+ namedOptions[key] = value |
|
| 329 |
+ continue |
|
| 330 |
+ } |
|
| 331 |
+ |
|
| 332 |
+ if _, ok := f.Value.(boolValue); ok {
|
|
| 333 |
+ f.Value.Set(fmt.Sprintf("%v", value))
|
|
| 334 |
+ } |
|
| 335 |
+ } |
|
| 336 |
+ if len(namedOptions) > 0 {
|
|
| 337 |
+ // set also default for mergeVal flags that are boolValue at the same time. |
|
| 338 |
+ flags.VisitAll(func(f *pflag.Flag) {
|
|
| 339 |
+ if opt, named := f.Value.(opts.NamedOption); named {
|
|
| 340 |
+ v, set := namedOptions[opt.Name()] |
|
| 341 |
+ _, boolean := f.Value.(boolValue) |
|
| 342 |
+ if set && boolean {
|
|
| 343 |
+ f.Value.Set(fmt.Sprintf("%v", v))
|
|
| 344 |
+ } |
|
| 345 |
+ } |
|
| 346 |
+ }) |
|
| 347 |
+ } |
|
| 348 |
+ |
|
| 349 |
+ config.ValuesSet = configSet |
|
| 350 |
+ } |
|
| 351 |
+ |
|
| 352 |
+ reader = bytes.NewReader(b) |
|
| 353 |
+ err = json.NewDecoder(reader).Decode(&config) |
|
| 354 |
+ return &config, err |
|
| 355 |
+} |
|
| 356 |
+ |
|
| 357 |
+// configValuesSet returns the configuration values explicitly set in the file. |
|
| 358 |
+func configValuesSet(config map[string]interface{}) map[string]interface{} {
|
|
| 359 |
+ flatten := make(map[string]interface{})
|
|
| 360 |
+ for k, v := range config {
|
|
| 361 |
+ if m, isMap := v.(map[string]interface{}); isMap && !flatOptions[k] {
|
|
| 362 |
+ for km, vm := range m {
|
|
| 363 |
+ flatten[km] = vm |
|
| 364 |
+ } |
|
| 365 |
+ continue |
|
| 366 |
+ } |
|
| 367 |
+ |
|
| 368 |
+ flatten[k] = v |
|
| 369 |
+ } |
|
| 370 |
+ return flatten |
|
| 371 |
+} |
|
| 372 |
+ |
|
| 373 |
+// findConfigurationConflicts iterates over the provided flags searching for |
|
| 374 |
+// duplicated configurations and unknown keys. It returns an error with all the conflicts if |
|
| 375 |
+// it finds any. |
|
| 376 |
+func findConfigurationConflicts(config map[string]interface{}, flags *pflag.FlagSet) error {
|
|
| 377 |
+ // 1. Search keys from the file that we don't recognize as flags. |
|
| 378 |
+ unknownKeys := make(map[string]interface{})
|
|
| 379 |
+ for key, value := range config {
|
|
| 380 |
+ if flag := flags.Lookup(key); flag == nil {
|
|
| 381 |
+ unknownKeys[key] = value |
|
| 382 |
+ } |
|
| 383 |
+ } |
|
| 384 |
+ |
|
| 385 |
+ // 2. Discard values that implement NamedOption. |
|
| 386 |
+ // Their configuration name differs from their flag name, like `labels` and `label`. |
|
| 387 |
+ if len(unknownKeys) > 0 {
|
|
| 388 |
+ unknownNamedConflicts := func(f *pflag.Flag) {
|
|
| 389 |
+ if namedOption, ok := f.Value.(opts.NamedOption); ok {
|
|
| 390 |
+ if _, valid := unknownKeys[namedOption.Name()]; valid {
|
|
| 391 |
+ delete(unknownKeys, namedOption.Name()) |
|
| 392 |
+ } |
|
| 393 |
+ } |
|
| 394 |
+ } |
|
| 395 |
+ flags.VisitAll(unknownNamedConflicts) |
|
| 396 |
+ } |
|
| 397 |
+ |
|
| 398 |
+ if len(unknownKeys) > 0 {
|
|
| 399 |
+ var unknown []string |
|
| 400 |
+ for key := range unknownKeys {
|
|
| 401 |
+ unknown = append(unknown, key) |
|
| 402 |
+ } |
|
| 403 |
+ return fmt.Errorf("the following directives don't match any configuration option: %s", strings.Join(unknown, ", "))
|
|
| 404 |
+ } |
|
| 405 |
+ |
|
| 406 |
+ var conflicts []string |
|
| 407 |
+ printConflict := func(name string, flagValue, fileValue interface{}) string {
|
|
| 408 |
+ return fmt.Sprintf("%s: (from flag: %v, from file: %v)", name, flagValue, fileValue)
|
|
| 409 |
+ } |
|
| 410 |
+ |
|
| 411 |
+ // 3. Search keys that are present as a flag and as a file option. |
|
| 412 |
+ duplicatedConflicts := func(f *pflag.Flag) {
|
|
| 413 |
+ // search option name in the json configuration payload if the value is a named option |
|
| 414 |
+ if namedOption, ok := f.Value.(opts.NamedOption); ok {
|
|
| 415 |
+ if optsValue, ok := config[namedOption.Name()]; ok {
|
|
| 416 |
+ conflicts = append(conflicts, printConflict(namedOption.Name(), f.Value.String(), optsValue)) |
|
| 417 |
+ } |
|
| 418 |
+ } else {
|
|
| 419 |
+ // search flag name in the json configuration payload |
|
| 420 |
+ for _, name := range []string{f.Name, f.Shorthand} {
|
|
| 421 |
+ if value, ok := config[name]; ok {
|
|
| 422 |
+ conflicts = append(conflicts, printConflict(name, f.Value.String(), value)) |
|
| 423 |
+ break |
|
| 424 |
+ } |
|
| 425 |
+ } |
|
| 426 |
+ } |
|
| 427 |
+ } |
|
| 428 |
+ |
|
| 429 |
+ flags.Visit(duplicatedConflicts) |
|
| 430 |
+ |
|
| 431 |
+ if len(conflicts) > 0 {
|
|
| 432 |
+ return fmt.Errorf("the following directives are specified both as a flag and in the configuration file: %s", strings.Join(conflicts, ", "))
|
|
| 433 |
+ } |
|
| 434 |
+ return nil |
|
| 435 |
+} |
|
| 436 |
+ |
|
| 437 |
+// Validate validates some specific configs. |
|
| 438 |
+// such as config.DNS, config.Labels, config.DNSSearch, |
|
| 439 |
+// as well as config.MaxConcurrentDownloads, config.MaxConcurrentUploads. |
|
| 440 |
+func Validate(config *Config) error {
|
|
| 441 |
+ // validate DNS |
|
| 442 |
+ for _, dns := range config.DNS {
|
|
| 443 |
+ if _, err := opts.ValidateIPAddress(dns); err != nil {
|
|
| 444 |
+ return err |
|
| 445 |
+ } |
|
| 446 |
+ } |
|
| 447 |
+ |
|
| 448 |
+ // validate DNSSearch |
|
| 449 |
+ for _, dnsSearch := range config.DNSSearch {
|
|
| 450 |
+ if _, err := opts.ValidateDNSSearch(dnsSearch); err != nil {
|
|
| 451 |
+ return err |
|
| 452 |
+ } |
|
| 453 |
+ } |
|
| 454 |
+ |
|
| 455 |
+ // validate Labels |
|
| 456 |
+ for _, label := range config.Labels {
|
|
| 457 |
+ if _, err := opts.ValidateLabel(label); err != nil {
|
|
| 458 |
+ return err |
|
| 459 |
+ } |
|
| 460 |
+ } |
|
| 461 |
+ |
|
| 462 |
+ // validate MaxConcurrentDownloads |
|
| 463 |
+ if config.IsValueSet("max-concurrent-downloads") && config.MaxConcurrentDownloads != nil && *config.MaxConcurrentDownloads < 0 {
|
|
| 464 |
+ return fmt.Errorf("invalid max concurrent downloads: %d", *config.MaxConcurrentDownloads)
|
|
| 465 |
+ } |
|
| 466 |
+ |
|
| 467 |
+ // validate MaxConcurrentUploads |
|
| 468 |
+ if config.IsValueSet("max-concurrent-uploads") && config.MaxConcurrentUploads != nil && *config.MaxConcurrentUploads < 0 {
|
|
| 469 |
+ return fmt.Errorf("invalid max concurrent uploads: %d", *config.MaxConcurrentUploads)
|
|
| 470 |
+ } |
|
| 471 |
+ |
|
| 472 |
+ // validate that "default" runtime is not reset |
|
| 473 |
+ if runtimes := config.GetAllRuntimes(); len(runtimes) > 0 {
|
|
| 474 |
+ if _, ok := runtimes[StockRuntimeName]; ok {
|
|
| 475 |
+ return fmt.Errorf("runtime name '%s' is reserved", StockRuntimeName)
|
|
| 476 |
+ } |
|
| 477 |
+ } |
|
| 478 |
+ |
|
| 479 |
+ if defaultRuntime := config.GetDefaultRuntimeName(); defaultRuntime != "" && defaultRuntime != StockRuntimeName {
|
|
| 480 |
+ runtimes := config.GetAllRuntimes() |
|
| 481 |
+ if _, ok := runtimes[defaultRuntime]; !ok {
|
|
| 482 |
+ return fmt.Errorf("specified default runtime '%s' does not exist", defaultRuntime)
|
|
| 483 |
+ } |
|
| 484 |
+ } |
|
| 485 |
+ |
|
| 486 |
+ return nil |
|
| 487 |
+} |
|
| 488 |
+ |
|
| 489 |
+// GetAuthorizationPlugins returns daemon's sorted authorization plugins |
|
| 490 |
+func (conf *Config) GetAuthorizationPlugins() []string {
|
|
| 491 |
+ conf.Lock() |
|
| 492 |
+ defer conf.Unlock() |
|
| 493 |
+ |
|
| 494 |
+ authPlugins := make([]string, 0, len(conf.AuthorizationPlugins)) |
|
| 495 |
+ for _, p := range conf.AuthorizationPlugins {
|
|
| 496 |
+ authPlugins = append(authPlugins, p) |
|
| 497 |
+ } |
|
| 498 |
+ sort.Strings(authPlugins) |
|
| 499 |
+ return authPlugins |
|
| 500 |
+} |
|
| 501 |
+ |
|
| 502 |
+// ModifiedDiscoverySettings returns whether the discovery configuration has been modified or not. |
|
| 503 |
+func ModifiedDiscoverySettings(config *Config, backendType, advertise string, clusterOpts map[string]string) bool {
|
|
| 504 |
+ if config.ClusterStore != backendType || config.ClusterAdvertise != advertise {
|
|
| 505 |
+ return true |
|
| 506 |
+ } |
|
| 507 |
+ |
|
| 508 |
+ if (config.ClusterOpts == nil && clusterOpts == nil) || |
|
| 509 |
+ (config.ClusterOpts == nil && len(clusterOpts) == 0) || |
|
| 510 |
+ (len(config.ClusterOpts) == 0 && clusterOpts == nil) {
|
|
| 511 |
+ return false |
|
| 512 |
+ } |
|
| 513 |
+ |
|
| 514 |
+ return !reflect.DeepEqual(config.ClusterOpts, clusterOpts) |
|
| 515 |
+} |
| 0 | 516 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,70 @@ |
| 0 |
+// +build solaris linux freebsd |
|
| 1 |
+ |
|
| 2 |
+package config |
|
| 3 |
+ |
|
| 4 |
+import ( |
|
| 5 |
+ "net" |
|
| 6 |
+ |
|
| 7 |
+ "github.com/docker/docker/api/types" |
|
| 8 |
+) |
|
| 9 |
+ |
|
| 10 |
+// CommonUnixConfig defines configuration of a docker daemon that is |
|
| 11 |
+// common across Unix platforms. |
|
| 12 |
+type CommonUnixConfig struct {
|
|
| 13 |
+ ExecRoot string `json:"exec-root,omitempty"` |
|
| 14 |
+ ContainerdAddr string `json:"containerd,omitempty"` |
|
| 15 |
+ Runtimes map[string]types.Runtime `json:"runtimes,omitempty"` |
|
| 16 |
+ DefaultRuntime string `json:"default-runtime,omitempty"` |
|
| 17 |
+ DefaultInitBinary string `json:"default-init,omitempty"` |
|
| 18 |
+} |
|
| 19 |
+ |
|
| 20 |
+type commonUnixBridgeConfig struct {
|
|
| 21 |
+ DefaultIP net.IP `json:"ip,omitempty"` |
|
| 22 |
+ IP string `json:"bip,omitempty"` |
|
| 23 |
+ DefaultGatewayIPv4 net.IP `json:"default-gateway,omitempty"` |
|
| 24 |
+ DefaultGatewayIPv6 net.IP `json:"default-gateway-v6,omitempty"` |
|
| 25 |
+ InterContainerCommunication bool `json:"icc,omitempty"` |
|
| 26 |
+} |
|
| 27 |
+ |
|
| 28 |
+// GetRuntime returns the runtime path and arguments for a given |
|
| 29 |
+// runtime name |
|
| 30 |
+func (conf *Config) GetRuntime(name string) *types.Runtime {
|
|
| 31 |
+ conf.Lock() |
|
| 32 |
+ defer conf.Unlock() |
|
| 33 |
+ if rt, ok := conf.Runtimes[name]; ok {
|
|
| 34 |
+ return &rt |
|
| 35 |
+ } |
|
| 36 |
+ return nil |
|
| 37 |
+} |
|
| 38 |
+ |
|
| 39 |
+// GetDefaultRuntimeName returns the current default runtime |
|
| 40 |
+func (conf *Config) GetDefaultRuntimeName() string {
|
|
| 41 |
+ conf.Lock() |
|
| 42 |
+ rt := conf.DefaultRuntime |
|
| 43 |
+ conf.Unlock() |
|
| 44 |
+ |
|
| 45 |
+ return rt |
|
| 46 |
+} |
|
| 47 |
+ |
|
| 48 |
+// GetAllRuntimes returns a copy of the runtimes map |
|
| 49 |
+func (conf *Config) GetAllRuntimes() map[string]types.Runtime {
|
|
| 50 |
+ conf.Lock() |
|
| 51 |
+ rts := conf.Runtimes |
|
| 52 |
+ conf.Unlock() |
|
| 53 |
+ return rts |
|
| 54 |
+} |
|
| 55 |
+ |
|
| 56 |
+// GetExecRoot returns the user configured Exec-root |
|
| 57 |
+func (conf *Config) GetExecRoot() string {
|
|
| 58 |
+ return conf.ExecRoot |
|
| 59 |
+} |
|
| 60 |
+ |
|
| 61 |
+// GetInitPath returns the configure docker-init path |
|
| 62 |
+func (conf *Config) GetInitPath() string {
|
|
| 63 |
+ conf.Lock() |
|
| 64 |
+ defer conf.Unlock() |
|
| 65 |
+ if conf.InitPath != "" {
|
|
| 66 |
+ return conf.InitPath |
|
| 67 |
+ } |
|
| 68 |
+ return conf.DefaultInitBinary |
|
| 69 |
+} |
| 0 | 70 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,43 @@ |
| 0 |
+// +build !windows |
|
| 1 |
+ |
|
| 2 |
+package config |
|
| 3 |
+ |
|
| 4 |
+import ( |
|
| 5 |
+ "testing" |
|
| 6 |
+ |
|
| 7 |
+ "github.com/docker/docker/api/types" |
|
| 8 |
+) |
|
| 9 |
+ |
|
| 10 |
+func TestCommonUnixValidateConfigurationErrors(t *testing.T) {
|
|
| 11 |
+ testCases := []struct {
|
|
| 12 |
+ config *Config |
|
| 13 |
+ }{
|
|
| 14 |
+ // Can't override the stock runtime |
|
| 15 |
+ {
|
|
| 16 |
+ config: &Config{
|
|
| 17 |
+ CommonUnixConfig: CommonUnixConfig{
|
|
| 18 |
+ Runtimes: map[string]types.Runtime{
|
|
| 19 |
+ StockRuntimeName: {},
|
|
| 20 |
+ }, |
|
| 21 |
+ }, |
|
| 22 |
+ }, |
|
| 23 |
+ }, |
|
| 24 |
+ // Default runtime should be present in runtimes |
|
| 25 |
+ {
|
|
| 26 |
+ config: &Config{
|
|
| 27 |
+ CommonUnixConfig: CommonUnixConfig{
|
|
| 28 |
+ Runtimes: map[string]types.Runtime{
|
|
| 29 |
+ "foo": {},
|
|
| 30 |
+ }, |
|
| 31 |
+ DefaultRuntime: "bar", |
|
| 32 |
+ }, |
|
| 33 |
+ }, |
|
| 34 |
+ }, |
|
| 35 |
+ } |
|
| 36 |
+ for _, tc := range testCases {
|
|
| 37 |
+ err := Validate(tc.config) |
|
| 38 |
+ if err == nil {
|
|
| 39 |
+ t.Fatalf("expected error, got nil for config %v", tc.config)
|
|
| 40 |
+ } |
|
| 41 |
+ } |
|
| 42 |
+} |
| 0 | 43 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,35 @@ |
| 0 |
+package config |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "github.com/spf13/pflag" |
|
| 4 |
+) |
|
| 5 |
+ |
|
| 6 |
+var ( |
|
| 7 |
+ defaultPidFile = "/system/volatile/docker/docker.pid" |
|
| 8 |
+ defaultGraph = "/var/lib/docker" |
|
| 9 |
+ defaultExec = "zones" |
|
| 10 |
+) |
|
| 11 |
+ |
|
| 12 |
+// Config defines the configuration of a docker daemon. |
|
| 13 |
+// These are the configuration settings that you pass |
|
| 14 |
+// to the docker daemon when you launch it with say: `docker -d -e lxc` |
|
| 15 |
+type Config struct {
|
|
| 16 |
+ CommonConfig |
|
| 17 |
+ |
|
| 18 |
+ // These fields are common to all unix platforms. |
|
| 19 |
+ CommonUnixConfig |
|
| 20 |
+} |
|
| 21 |
+ |
|
| 22 |
+// BridgeConfig stores all the bridge driver specific |
|
| 23 |
+// configuration. |
|
| 24 |
+type BridgeConfig struct {
|
|
| 25 |
+ commonBridgeConfig |
|
| 26 |
+ |
|
| 27 |
+ // Fields below here are platform specific. |
|
| 28 |
+ commonUnixBridgeConfig |
|
| 29 |
+} |
|
| 30 |
+ |
|
| 31 |
+// IsSwarmCompatible defines if swarm mode can be enabled in this config |
|
| 32 |
+func (conf *Config) IsSwarmCompatible() error {
|
|
| 33 |
+ return nil |
|
| 34 |
+} |
| 0 | 35 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,335 @@ |
| 0 |
+package config |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "io/ioutil" |
|
| 4 |
+ "os" |
|
| 5 |
+ "runtime" |
|
| 6 |
+ "strings" |
|
| 7 |
+ "testing" |
|
| 8 |
+ |
|
| 9 |
+ "github.com/docker/docker/daemon/discovery" |
|
| 10 |
+ "github.com/docker/docker/opts" |
|
| 11 |
+ "github.com/docker/docker/pkg/testutil/assert" |
|
| 12 |
+ "github.com/spf13/pflag" |
|
| 13 |
+) |
|
| 14 |
+ |
|
| 15 |
+func TestDaemonConfigurationNotFound(t *testing.T) {
|
|
| 16 |
+ _, err := MergeDaemonConfigurations(&Config{}, nil, "/tmp/foo-bar-baz-docker")
|
|
| 17 |
+ if err == nil || !os.IsNotExist(err) {
|
|
| 18 |
+ t.Fatalf("expected does not exist error, got %v", err)
|
|
| 19 |
+ } |
|
| 20 |
+} |
|
| 21 |
+ |
|
| 22 |
+func TestDaemonBrokenConfiguration(t *testing.T) {
|
|
| 23 |
+ f, err := ioutil.TempFile("", "docker-config-")
|
|
| 24 |
+ if err != nil {
|
|
| 25 |
+ t.Fatal(err) |
|
| 26 |
+ } |
|
| 27 |
+ |
|
| 28 |
+ configFile := f.Name() |
|
| 29 |
+ f.Write([]byte(`{"Debug": tru`))
|
|
| 30 |
+ f.Close() |
|
| 31 |
+ |
|
| 32 |
+ _, err = MergeDaemonConfigurations(&Config{}, nil, configFile)
|
|
| 33 |
+ if err == nil {
|
|
| 34 |
+ t.Fatalf("expected error, got %v", err)
|
|
| 35 |
+ } |
|
| 36 |
+} |
|
| 37 |
+ |
|
| 38 |
+func TestParseClusterAdvertiseSettings(t *testing.T) {
|
|
| 39 |
+ if runtime.GOOS == "solaris" {
|
|
| 40 |
+ t.Skip("ClusterSettings not supported on Solaris\n")
|
|
| 41 |
+ } |
|
| 42 |
+ _, err := ParseClusterAdvertiseSettings("something", "")
|
|
| 43 |
+ if err != discovery.ErrDiscoveryDisabled {
|
|
| 44 |
+ t.Fatalf("expected discovery disabled error, got %v\n", err)
|
|
| 45 |
+ } |
|
| 46 |
+ |
|
| 47 |
+ _, err = ParseClusterAdvertiseSettings("", "something")
|
|
| 48 |
+ if err == nil {
|
|
| 49 |
+ t.Fatalf("expected discovery store error, got %v\n", err)
|
|
| 50 |
+ } |
|
| 51 |
+ |
|
| 52 |
+ _, err = ParseClusterAdvertiseSettings("etcd", "127.0.0.1:8080")
|
|
| 53 |
+ if err != nil {
|
|
| 54 |
+ t.Fatal(err) |
|
| 55 |
+ } |
|
| 56 |
+} |
|
| 57 |
+ |
|
| 58 |
+func TestFindConfigurationConflicts(t *testing.T) {
|
|
| 59 |
+ config := map[string]interface{}{"authorization-plugins": "foobar"}
|
|
| 60 |
+ flags := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
|
| 61 |
+ |
|
| 62 |
+ flags.String("authorization-plugins", "", "")
|
|
| 63 |
+ assert.NilError(t, flags.Set("authorization-plugins", "asdf"))
|
|
| 64 |
+ |
|
| 65 |
+ assert.Error(t, |
|
| 66 |
+ findConfigurationConflicts(config, flags), |
|
| 67 |
+ "authorization-plugins: (from flag: asdf, from file: foobar)") |
|
| 68 |
+} |
|
| 69 |
+ |
|
| 70 |
+func TestFindConfigurationConflictsWithNamedOptions(t *testing.T) {
|
|
| 71 |
+ config := map[string]interface{}{"hosts": []string{"qwer"}}
|
|
| 72 |
+ flags := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
|
| 73 |
+ |
|
| 74 |
+ var hosts []string |
|
| 75 |
+ flags.VarP(opts.NewNamedListOptsRef("hosts", &hosts, opts.ValidateHost), "host", "H", "Daemon socket(s) to connect to")
|
|
| 76 |
+ assert.NilError(t, flags.Set("host", "tcp://127.0.0.1:4444"))
|
|
| 77 |
+ assert.NilError(t, flags.Set("host", "unix:///var/run/docker.sock"))
|
|
| 78 |
+ |
|
| 79 |
+ assert.Error(t, findConfigurationConflicts(config, flags), "hosts") |
|
| 80 |
+} |
|
| 81 |
+ |
|
| 82 |
+func TestDaemonConfigurationMergeConflicts(t *testing.T) {
|
|
| 83 |
+ f, err := ioutil.TempFile("", "docker-config-")
|
|
| 84 |
+ if err != nil {
|
|
| 85 |
+ t.Fatal(err) |
|
| 86 |
+ } |
|
| 87 |
+ |
|
| 88 |
+ configFile := f.Name() |
|
| 89 |
+ f.Write([]byte(`{"debug": true}`))
|
|
| 90 |
+ f.Close() |
|
| 91 |
+ |
|
| 92 |
+ flags := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
|
| 93 |
+ flags.Bool("debug", false, "")
|
|
| 94 |
+ flags.Set("debug", "false")
|
|
| 95 |
+ |
|
| 96 |
+ _, err = MergeDaemonConfigurations(&Config{}, flags, configFile)
|
|
| 97 |
+ if err == nil {
|
|
| 98 |
+ t.Fatal("expected error, got nil")
|
|
| 99 |
+ } |
|
| 100 |
+ if !strings.Contains(err.Error(), "debug") {
|
|
| 101 |
+ t.Fatalf("expected debug conflict, got %v", err)
|
|
| 102 |
+ } |
|
| 103 |
+} |
|
| 104 |
+ |
|
| 105 |
+func TestDaemonConfigurationMergeConflictsWithInnerStructs(t *testing.T) {
|
|
| 106 |
+ f, err := ioutil.TempFile("", "docker-config-")
|
|
| 107 |
+ if err != nil {
|
|
| 108 |
+ t.Fatal(err) |
|
| 109 |
+ } |
|
| 110 |
+ |
|
| 111 |
+ configFile := f.Name() |
|
| 112 |
+ f.Write([]byte(`{"tlscacert": "/etc/certificates/ca.pem"}`))
|
|
| 113 |
+ f.Close() |
|
| 114 |
+ |
|
| 115 |
+ flags := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
|
| 116 |
+ flags.String("tlscacert", "", "")
|
|
| 117 |
+ flags.Set("tlscacert", "~/.docker/ca.pem")
|
|
| 118 |
+ |
|
| 119 |
+ _, err = MergeDaemonConfigurations(&Config{}, flags, configFile)
|
|
| 120 |
+ if err == nil {
|
|
| 121 |
+ t.Fatal("expected error, got nil")
|
|
| 122 |
+ } |
|
| 123 |
+ if !strings.Contains(err.Error(), "tlscacert") {
|
|
| 124 |
+ t.Fatalf("expected tlscacert conflict, got %v", err)
|
|
| 125 |
+ } |
|
| 126 |
+} |
|
| 127 |
+ |
|
| 128 |
+func TestFindConfigurationConflictsWithUnknownKeys(t *testing.T) {
|
|
| 129 |
+ config := map[string]interface{}{"tls-verify": "true"}
|
|
| 130 |
+ flags := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
|
| 131 |
+ |
|
| 132 |
+ flags.Bool("tlsverify", false, "")
|
|
| 133 |
+ err := findConfigurationConflicts(config, flags) |
|
| 134 |
+ if err == nil {
|
|
| 135 |
+ t.Fatal("expected error, got nil")
|
|
| 136 |
+ } |
|
| 137 |
+ if !strings.Contains(err.Error(), "the following directives don't match any configuration option: tls-verify") {
|
|
| 138 |
+ t.Fatalf("expected tls-verify conflict, got %v", err)
|
|
| 139 |
+ } |
|
| 140 |
+} |
|
| 141 |
+ |
|
| 142 |
+func TestFindConfigurationConflictsWithMergedValues(t *testing.T) {
|
|
| 143 |
+ var hosts []string |
|
| 144 |
+ config := map[string]interface{}{"hosts": "tcp://127.0.0.1:2345"}
|
|
| 145 |
+ flags := pflag.NewFlagSet("base", pflag.ContinueOnError)
|
|
| 146 |
+ flags.VarP(opts.NewNamedListOptsRef("hosts", &hosts, nil), "host", "H", "")
|
|
| 147 |
+ |
|
| 148 |
+ err := findConfigurationConflicts(config, flags) |
|
| 149 |
+ if err != nil {
|
|
| 150 |
+ t.Fatal(err) |
|
| 151 |
+ } |
|
| 152 |
+ |
|
| 153 |
+ flags.Set("host", "unix:///var/run/docker.sock")
|
|
| 154 |
+ err = findConfigurationConflicts(config, flags) |
|
| 155 |
+ if err == nil {
|
|
| 156 |
+ t.Fatal("expected error, got nil")
|
|
| 157 |
+ } |
|
| 158 |
+ if !strings.Contains(err.Error(), "hosts: (from flag: [unix:///var/run/docker.sock], from file: tcp://127.0.0.1:2345)") {
|
|
| 159 |
+ t.Fatalf("expected hosts conflict, got %v", err)
|
|
| 160 |
+ } |
|
| 161 |
+} |
|
| 162 |
+ |
|
| 163 |
+func TestValidateConfigurationErrors(t *testing.T) {
|
|
| 164 |
+ minusNumber := -10 |
|
| 165 |
+ testCases := []struct {
|
|
| 166 |
+ config *Config |
|
| 167 |
+ }{
|
|
| 168 |
+ {
|
|
| 169 |
+ config: &Config{
|
|
| 170 |
+ CommonConfig: CommonConfig{
|
|
| 171 |
+ Labels: []string{"one"},
|
|
| 172 |
+ }, |
|
| 173 |
+ }, |
|
| 174 |
+ }, |
|
| 175 |
+ {
|
|
| 176 |
+ config: &Config{
|
|
| 177 |
+ CommonConfig: CommonConfig{
|
|
| 178 |
+ Labels: []string{"foo=bar", "one"},
|
|
| 179 |
+ }, |
|
| 180 |
+ }, |
|
| 181 |
+ }, |
|
| 182 |
+ {
|
|
| 183 |
+ config: &Config{
|
|
| 184 |
+ CommonConfig: CommonConfig{
|
|
| 185 |
+ DNS: []string{"1.1.1.1o"},
|
|
| 186 |
+ }, |
|
| 187 |
+ }, |
|
| 188 |
+ }, |
|
| 189 |
+ {
|
|
| 190 |
+ config: &Config{
|
|
| 191 |
+ CommonConfig: CommonConfig{
|
|
| 192 |
+ DNS: []string{"2.2.2.2", "1.1.1.1o"},
|
|
| 193 |
+ }, |
|
| 194 |
+ }, |
|
| 195 |
+ }, |
|
| 196 |
+ {
|
|
| 197 |
+ config: &Config{
|
|
| 198 |
+ CommonConfig: CommonConfig{
|
|
| 199 |
+ DNSSearch: []string{"123456"},
|
|
| 200 |
+ }, |
|
| 201 |
+ }, |
|
| 202 |
+ }, |
|
| 203 |
+ {
|
|
| 204 |
+ config: &Config{
|
|
| 205 |
+ CommonConfig: CommonConfig{
|
|
| 206 |
+ DNSSearch: []string{"a.b.c", "123456"},
|
|
| 207 |
+ }, |
|
| 208 |
+ }, |
|
| 209 |
+ }, |
|
| 210 |
+ {
|
|
| 211 |
+ config: &Config{
|
|
| 212 |
+ CommonConfig: CommonConfig{
|
|
| 213 |
+ MaxConcurrentDownloads: &minusNumber, |
|
| 214 |
+ // This is weird... |
|
| 215 |
+ ValuesSet: map[string]interface{}{
|
|
| 216 |
+ "max-concurrent-downloads": -1, |
|
| 217 |
+ }, |
|
| 218 |
+ }, |
|
| 219 |
+ }, |
|
| 220 |
+ }, |
|
| 221 |
+ {
|
|
| 222 |
+ config: &Config{
|
|
| 223 |
+ CommonConfig: CommonConfig{
|
|
| 224 |
+ MaxConcurrentUploads: &minusNumber, |
|
| 225 |
+ // This is weird... |
|
| 226 |
+ ValuesSet: map[string]interface{}{
|
|
| 227 |
+ "max-concurrent-uploads": -1, |
|
| 228 |
+ }, |
|
| 229 |
+ }, |
|
| 230 |
+ }, |
|
| 231 |
+ }, |
|
| 232 |
+ } |
|
| 233 |
+ for _, tc := range testCases {
|
|
| 234 |
+ err := Validate(tc.config) |
|
| 235 |
+ if err == nil {
|
|
| 236 |
+ t.Fatalf("expected error, got nil for config %v", tc.config)
|
|
| 237 |
+ } |
|
| 238 |
+ } |
|
| 239 |
+} |
|
| 240 |
+ |
|
| 241 |
+func TestValidateConfiguration(t *testing.T) {
|
|
| 242 |
+ testCases := []struct {
|
|
| 243 |
+ config *Config |
|
| 244 |
+ }{
|
|
| 245 |
+ {
|
|
| 246 |
+ config: &Config{
|
|
| 247 |
+ CommonConfig: CommonConfig{
|
|
| 248 |
+ Labels: []string{"one=two"},
|
|
| 249 |
+ }, |
|
| 250 |
+ }, |
|
| 251 |
+ }, |
|
| 252 |
+ {
|
|
| 253 |
+ config: &Config{
|
|
| 254 |
+ CommonConfig: CommonConfig{
|
|
| 255 |
+ DNS: []string{"1.1.1.1"},
|
|
| 256 |
+ }, |
|
| 257 |
+ }, |
|
| 258 |
+ }, |
|
| 259 |
+ {
|
|
| 260 |
+ config: &Config{
|
|
| 261 |
+ CommonConfig: CommonConfig{
|
|
| 262 |
+ DNSSearch: []string{"a.b.c"},
|
|
| 263 |
+ }, |
|
| 264 |
+ }, |
|
| 265 |
+ }, |
|
| 266 |
+ } |
|
| 267 |
+ for _, tc := range testCases {
|
|
| 268 |
+ err := Validate(tc.config) |
|
| 269 |
+ if err != nil {
|
|
| 270 |
+ t.Fatalf("expected no error, got error %v", err)
|
|
| 271 |
+ } |
|
| 272 |
+ } |
|
| 273 |
+} |
|
| 274 |
+ |
|
| 275 |
+func TestModifiedDiscoverySettings(t *testing.T) {
|
|
| 276 |
+ cases := []struct {
|
|
| 277 |
+ current *Config |
|
| 278 |
+ modified *Config |
|
| 279 |
+ expected bool |
|
| 280 |
+ }{
|
|
| 281 |
+ {
|
|
| 282 |
+ current: discoveryConfig("foo", "bar", map[string]string{}),
|
|
| 283 |
+ modified: discoveryConfig("foo", "bar", map[string]string{}),
|
|
| 284 |
+ expected: false, |
|
| 285 |
+ }, |
|
| 286 |
+ {
|
|
| 287 |
+ current: discoveryConfig("foo", "bar", map[string]string{"foo": "bar"}),
|
|
| 288 |
+ modified: discoveryConfig("foo", "bar", map[string]string{"foo": "bar"}),
|
|
| 289 |
+ expected: false, |
|
| 290 |
+ }, |
|
| 291 |
+ {
|
|
| 292 |
+ current: discoveryConfig("foo", "bar", map[string]string{}),
|
|
| 293 |
+ modified: discoveryConfig("foo", "bar", nil),
|
|
| 294 |
+ expected: false, |
|
| 295 |
+ }, |
|
| 296 |
+ {
|
|
| 297 |
+ current: discoveryConfig("foo", "bar", nil),
|
|
| 298 |
+ modified: discoveryConfig("foo", "bar", map[string]string{}),
|
|
| 299 |
+ expected: false, |
|
| 300 |
+ }, |
|
| 301 |
+ {
|
|
| 302 |
+ current: discoveryConfig("foo", "bar", nil),
|
|
| 303 |
+ modified: discoveryConfig("baz", "bar", nil),
|
|
| 304 |
+ expected: true, |
|
| 305 |
+ }, |
|
| 306 |
+ {
|
|
| 307 |
+ current: discoveryConfig("foo", "bar", nil),
|
|
| 308 |
+ modified: discoveryConfig("foo", "baz", nil),
|
|
| 309 |
+ expected: true, |
|
| 310 |
+ }, |
|
| 311 |
+ {
|
|
| 312 |
+ current: discoveryConfig("foo", "bar", nil),
|
|
| 313 |
+ modified: discoveryConfig("foo", "bar", map[string]string{"foo": "bar"}),
|
|
| 314 |
+ expected: true, |
|
| 315 |
+ }, |
|
| 316 |
+ } |
|
| 317 |
+ |
|
| 318 |
+ for _, c := range cases {
|
|
| 319 |
+ got := ModifiedDiscoverySettings(c.current, c.modified.ClusterStore, c.modified.ClusterAdvertise, c.modified.ClusterOpts) |
|
| 320 |
+ if c.expected != got {
|
|
| 321 |
+ t.Fatalf("expected %v, got %v: current config %v, new config %v", c.expected, got, c.current, c.modified)
|
|
| 322 |
+ } |
|
| 323 |
+ } |
|
| 324 |
+} |
|
| 325 |
+ |
|
| 326 |
+func discoveryConfig(backendAddr, advertiseAddr string, opts map[string]string) *Config {
|
|
| 327 |
+ return &Config{
|
|
| 328 |
+ CommonConfig: CommonConfig{
|
|
| 329 |
+ ClusterStore: backendAddr, |
|
| 330 |
+ ClusterAdvertise: advertiseAddr, |
|
| 331 |
+ ClusterOpts: opts, |
|
| 332 |
+ }, |
|
| 333 |
+ } |
|
| 334 |
+} |
| 0 | 335 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,62 @@ |
| 0 |
+// +build linux freebsd |
|
| 1 |
+ |
|
| 2 |
+package config |
|
| 3 |
+ |
|
| 4 |
+import ( |
|
| 5 |
+ "fmt" |
|
| 6 |
+ |
|
| 7 |
+ "github.com/docker/docker/opts" |
|
| 8 |
+ units "github.com/docker/go-units" |
|
| 9 |
+) |
|
| 10 |
+ |
|
| 11 |
+// Config defines the configuration of a docker daemon. |
|
| 12 |
+// It includes json tags to deserialize configuration from a file |
|
| 13 |
+// using the same names that the flags in the command line uses. |
|
| 14 |
+type Config struct {
|
|
| 15 |
+ CommonConfig |
|
| 16 |
+ |
|
| 17 |
+ // These fields are common to all unix platforms. |
|
| 18 |
+ CommonUnixConfig |
|
| 19 |
+ |
|
| 20 |
+ // Fields below here are platform specific. |
|
| 21 |
+ CgroupParent string `json:"cgroup-parent,omitempty"` |
|
| 22 |
+ EnableSelinuxSupport bool `json:"selinux-enabled,omitempty"` |
|
| 23 |
+ RemappedRoot string `json:"userns-remap,omitempty"` |
|
| 24 |
+ Ulimits map[string]*units.Ulimit `json:"default-ulimits,omitempty"` |
|
| 25 |
+ CPURealtimePeriod int64 `json:"cpu-rt-period,omitempty"` |
|
| 26 |
+ CPURealtimeRuntime int64 `json:"cpu-rt-runtime,omitempty"` |
|
| 27 |
+ OOMScoreAdjust int `json:"oom-score-adjust,omitempty"` |
|
| 28 |
+ Init bool `json:"init,omitempty"` |
|
| 29 |
+ InitPath string `json:"init-path,omitempty"` |
|
| 30 |
+ SeccompProfile string `json:"seccomp-profile,omitempty"` |
|
| 31 |
+ ShmSize opts.MemBytes `json:"default-shm-size,omitempty"` |
|
| 32 |
+} |
|
| 33 |
+ |
|
| 34 |
+// BridgeConfig stores all the bridge driver specific |
|
| 35 |
+// configuration. |
|
| 36 |
+type BridgeConfig struct {
|
|
| 37 |
+ commonBridgeConfig |
|
| 38 |
+ |
|
| 39 |
+ // These fields are common to all unix platforms. |
|
| 40 |
+ commonUnixBridgeConfig |
|
| 41 |
+ |
|
| 42 |
+ // Fields below here are platform specific. |
|
| 43 |
+ EnableIPv6 bool `json:"ipv6,omitempty"` |
|
| 44 |
+ EnableIPTables bool `json:"iptables,omitempty"` |
|
| 45 |
+ EnableIPForward bool `json:"ip-forward,omitempty"` |
|
| 46 |
+ EnableIPMasq bool `json:"ip-masq,omitempty"` |
|
| 47 |
+ EnableUserlandProxy bool `json:"userland-proxy,omitempty"` |
|
| 48 |
+ UserlandProxyPath string `json:"userland-proxy-path,omitempty"` |
|
| 49 |
+ FixedCIDRv6 string `json:"fixed-cidr-v6,omitempty"` |
|
| 50 |
+} |
|
| 51 |
+ |
|
| 52 |
+// IsSwarmCompatible defines if swarm mode can be enabled in this config |
|
| 53 |
+func (conf *Config) IsSwarmCompatible() error {
|
|
| 54 |
+ if conf.ClusterStore != "" || conf.ClusterAdvertise != "" {
|
|
| 55 |
+ return fmt.Errorf("--cluster-store and --cluster-advertise daemon configurations are incompatible with swarm mode")
|
|
| 56 |
+ } |
|
| 57 |
+ if conf.LiveRestoreEnabled {
|
|
| 58 |
+ return fmt.Errorf("--live-restore daemon configuration is incompatible with swarm mode")
|
|
| 59 |
+ } |
|
| 60 |
+ return nil |
|
| 61 |
+} |
| 0 | 62 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,111 @@ |
| 0 |
+// +build !windows |
|
| 1 |
+ |
|
| 2 |
+package config |
|
| 3 |
+ |
|
| 4 |
+import ( |
|
| 5 |
+ "io/ioutil" |
|
| 6 |
+ "runtime" |
|
| 7 |
+ |
|
| 8 |
+ "testing" |
|
| 9 |
+) |
|
| 10 |
+ |
|
| 11 |
+func TestDaemonConfigurationMerge(t *testing.T) {
|
|
| 12 |
+ f, err := ioutil.TempFile("", "docker-config-")
|
|
| 13 |
+ if err != nil {
|
|
| 14 |
+ t.Fatal(err) |
|
| 15 |
+ } |
|
| 16 |
+ |
|
| 17 |
+ configFile := f.Name() |
|
| 18 |
+ |
|
| 19 |
+ f.Write([]byte(` |
|
| 20 |
+ {
|
|
| 21 |
+ "debug": true, |
|
| 22 |
+ "default-ulimits": {
|
|
| 23 |
+ "nofile": {
|
|
| 24 |
+ "Name": "nofile", |
|
| 25 |
+ "Hard": 2048, |
|
| 26 |
+ "Soft": 1024 |
|
| 27 |
+ } |
|
| 28 |
+ }, |
|
| 29 |
+ "log-opts": {
|
|
| 30 |
+ "tag": "test_tag" |
|
| 31 |
+ } |
|
| 32 |
+ }`)) |
|
| 33 |
+ |
|
| 34 |
+ f.Close() |
|
| 35 |
+ |
|
| 36 |
+ c := &Config{
|
|
| 37 |
+ CommonConfig: CommonConfig{
|
|
| 38 |
+ AutoRestart: true, |
|
| 39 |
+ LogConfig: LogConfig{
|
|
| 40 |
+ Type: "syslog", |
|
| 41 |
+ Config: map[string]string{"tag": "test"},
|
|
| 42 |
+ }, |
|
| 43 |
+ }, |
|
| 44 |
+ } |
|
| 45 |
+ |
|
| 46 |
+ cc, err := MergeDaemonConfigurations(c, nil, configFile) |
|
| 47 |
+ if err != nil {
|
|
| 48 |
+ t.Fatal(err) |
|
| 49 |
+ } |
|
| 50 |
+ if !cc.Debug {
|
|
| 51 |
+ t.Fatalf("expected %v, got %v\n", true, cc.Debug)
|
|
| 52 |
+ } |
|
| 53 |
+ if !cc.AutoRestart {
|
|
| 54 |
+ t.Fatalf("expected %v, got %v\n", true, cc.AutoRestart)
|
|
| 55 |
+ } |
|
| 56 |
+ if cc.LogConfig.Type != "syslog" {
|
|
| 57 |
+ t.Fatalf("expected syslog config, got %q\n", cc.LogConfig)
|
|
| 58 |
+ } |
|
| 59 |
+ |
|
| 60 |
+ if configValue, OK := cc.LogConfig.Config["tag"]; !OK {
|
|
| 61 |
+ t.Fatal("expected syslog config attributes, got nil\n")
|
|
| 62 |
+ } else {
|
|
| 63 |
+ if configValue != "test_tag" {
|
|
| 64 |
+ t.Fatalf("expected syslog config attributes 'tag=test_tag', got 'tag=%s'\n", configValue)
|
|
| 65 |
+ } |
|
| 66 |
+ } |
|
| 67 |
+ |
|
| 68 |
+ if cc.Ulimits == nil {
|
|
| 69 |
+ t.Fatal("expected default ulimit config, got nil\n")
|
|
| 70 |
+ } else {
|
|
| 71 |
+ if _, OK := cc.Ulimits["nofile"]; OK {
|
|
| 72 |
+ if cc.Ulimits["nofile"].Name != "nofile" || |
|
| 73 |
+ cc.Ulimits["nofile"].Hard != 2048 || |
|
| 74 |
+ cc.Ulimits["nofile"].Soft != 1024 {
|
|
| 75 |
+ t.Fatalf("expected default ulimit name, hard and soft are nofile, 2048, 1024, got %s, %d, %d\n", cc.Ulimits["nofile"].Name, cc.Ulimits["nofile"].Hard, cc.Ulimits["nofile"].Soft)
|
|
| 76 |
+ } |
|
| 77 |
+ } else {
|
|
| 78 |
+ t.Fatal("expected default ulimit name nofile, got nil\n")
|
|
| 79 |
+ } |
|
| 80 |
+ } |
|
| 81 |
+} |
|
| 82 |
+ |
|
| 83 |
+func TestDaemonConfigurationMergeShmSize(t *testing.T) {
|
|
| 84 |
+ if runtime.GOOS == "solaris" {
|
|
| 85 |
+ t.Skip("ShmSize not supported on Solaris\n")
|
|
| 86 |
+ } |
|
| 87 |
+ f, err := ioutil.TempFile("", "docker-config-")
|
|
| 88 |
+ if err != nil {
|
|
| 89 |
+ t.Fatal(err) |
|
| 90 |
+ } |
|
| 91 |
+ |
|
| 92 |
+ configFile := f.Name() |
|
| 93 |
+ |
|
| 94 |
+ f.Write([]byte(` |
|
| 95 |
+ {
|
|
| 96 |
+ "default-shm-size": "1g" |
|
| 97 |
+ }`)) |
|
| 98 |
+ |
|
| 99 |
+ f.Close() |
|
| 100 |
+ |
|
| 101 |
+ c := &Config{}
|
|
| 102 |
+ cc, err := MergeDaemonConfigurations(c, nil, configFile) |
|
| 103 |
+ if err != nil {
|
|
| 104 |
+ t.Fatal(err) |
|
| 105 |
+ } |
|
| 106 |
+ expectedValue := 1 * 1024 * 1024 * 1024 |
|
| 107 |
+ if cc.ShmSize.Value() != int64(expectedValue) {
|
|
| 108 |
+ t.Fatalf("expected default shm size %d, got %d", expectedValue, cc.ShmSize.Value())
|
|
| 109 |
+ } |
|
| 110 |
+} |
| 0 | 111 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,52 @@ |
| 0 |
+package config |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "github.com/docker/docker/api/types" |
|
| 4 |
+) |
|
| 5 |
+ |
|
| 6 |
+// BridgeConfig stores all the bridge driver specific |
|
| 7 |
+// configuration. |
|
| 8 |
+type BridgeConfig struct {
|
|
| 9 |
+ commonBridgeConfig |
|
| 10 |
+} |
|
| 11 |
+ |
|
| 12 |
+// Config defines the configuration of a docker daemon. |
|
| 13 |
+// These are the configuration settings that you pass |
|
| 14 |
+// to the docker daemon when you launch it with say: `dockerd -e windows` |
|
| 15 |
+type Config struct {
|
|
| 16 |
+ CommonConfig |
|
| 17 |
+ |
|
| 18 |
+ // Fields below here are platform specific. (There are none presently |
|
| 19 |
+ // for the Windows daemon.) |
|
| 20 |
+} |
|
| 21 |
+ |
|
| 22 |
+// GetRuntime returns the runtime path and arguments for a given |
|
| 23 |
+// runtime name |
|
| 24 |
+func (conf *Config) GetRuntime(name string) *types.Runtime {
|
|
| 25 |
+ return nil |
|
| 26 |
+} |
|
| 27 |
+ |
|
| 28 |
+// GetInitPath returns the configure docker-init path |
|
| 29 |
+func (conf *Config) GetInitPath() string {
|
|
| 30 |
+ return "" |
|
| 31 |
+} |
|
| 32 |
+ |
|
| 33 |
+// GetDefaultRuntimeName returns the current default runtime |
|
| 34 |
+func (conf *Config) GetDefaultRuntimeName() string {
|
|
| 35 |
+ return StockRuntimeName |
|
| 36 |
+} |
|
| 37 |
+ |
|
| 38 |
+// GetAllRuntimes returns a copy of the runtimes map |
|
| 39 |
+func (conf *Config) GetAllRuntimes() map[string]types.Runtime {
|
|
| 40 |
+ return map[string]types.Runtime{}
|
|
| 41 |
+} |
|
| 42 |
+ |
|
| 43 |
+// GetExecRoot returns the user configured Exec-root |
|
| 44 |
+func (conf *Config) GetExecRoot() string {
|
|
| 45 |
+ return "" |
|
| 46 |
+} |
|
| 47 |
+ |
|
| 48 |
+// IsSwarmCompatible defines if swarm mode can be enabled in this config |
|
| 49 |
+func (conf *Config) IsSwarmCompatible() error {
|
|
| 50 |
+ return nil |
|
| 51 |
+} |
| 0 | 52 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,59 @@ |
| 0 |
+// +build windows |
|
| 1 |
+ |
|
| 2 |
+package config |
|
| 3 |
+ |
|
| 4 |
+import ( |
|
| 5 |
+ "io/ioutil" |
|
| 6 |
+ "testing" |
|
| 7 |
+) |
|
| 8 |
+ |
|
| 9 |
+func TestDaemonConfigurationMerge(t *testing.T) {
|
|
| 10 |
+ f, err := ioutil.TempFile("", "docker-config-")
|
|
| 11 |
+ if err != nil {
|
|
| 12 |
+ t.Fatal(err) |
|
| 13 |
+ } |
|
| 14 |
+ |
|
| 15 |
+ configFile := f.Name() |
|
| 16 |
+ |
|
| 17 |
+ f.Write([]byte(` |
|
| 18 |
+ {
|
|
| 19 |
+ "debug": true, |
|
| 20 |
+ "log-opts": {
|
|
| 21 |
+ "tag": "test_tag" |
|
| 22 |
+ } |
|
| 23 |
+ }`)) |
|
| 24 |
+ |
|
| 25 |
+ f.Close() |
|
| 26 |
+ |
|
| 27 |
+ c := &Config{
|
|
| 28 |
+ CommonConfig: CommonConfig{
|
|
| 29 |
+ AutoRestart: true, |
|
| 30 |
+ LogConfig: LogConfig{
|
|
| 31 |
+ Type: "syslog", |
|
| 32 |
+ Config: map[string]string{"tag": "test"},
|
|
| 33 |
+ }, |
|
| 34 |
+ }, |
|
| 35 |
+ } |
|
| 36 |
+ |
|
| 37 |
+ cc, err := MergeDaemonConfigurations(c, nil, configFile) |
|
| 38 |
+ if err != nil {
|
|
| 39 |
+ t.Fatal(err) |
|
| 40 |
+ } |
|
| 41 |
+ if !cc.Debug {
|
|
| 42 |
+ t.Fatalf("expected %v, got %v\n", true, cc.Debug)
|
|
| 43 |
+ } |
|
| 44 |
+ if !cc.AutoRestart {
|
|
| 45 |
+ t.Fatalf("expected %v, got %v\n", true, cc.AutoRestart)
|
|
| 46 |
+ } |
|
| 47 |
+ if cc.LogConfig.Type != "syslog" {
|
|
| 48 |
+ t.Fatalf("expected syslog config, got %q\n", cc.LogConfig)
|
|
| 49 |
+ } |
|
| 50 |
+ |
|
| 51 |
+ if configValue, OK := cc.LogConfig.Config["tag"]; !OK {
|
|
| 52 |
+ t.Fatal("expected syslog config attributes, got nil\n")
|
|
| 53 |
+ } else {
|
|
| 54 |
+ if configValue != "test_tag" {
|
|
| 55 |
+ t.Fatalf("expected syslog config attributes 'tag=test_tag', got 'tag=%s'\n", configValue)
|
|
| 56 |
+ } |
|
| 57 |
+ } |
|
| 58 |
+} |
| 0 | 59 |
deleted file mode 100644 |
| ... | ... |
@@ -1,89 +0,0 @@ |
| 1 |
-// +build solaris linux freebsd |
|
| 2 |
- |
|
| 3 |
-package daemon |
|
| 4 |
- |
|
| 5 |
-import ( |
|
| 6 |
- "net" |
|
| 7 |
- |
|
| 8 |
- "github.com/docker/docker/api/types" |
|
| 9 |
- "github.com/docker/docker/opts" |
|
| 10 |
- "github.com/spf13/pflag" |
|
| 11 |
-) |
|
| 12 |
- |
|
| 13 |
-// CommonUnixConfig defines configuration of a docker daemon that is |
|
| 14 |
-// common across Unix platforms. |
|
| 15 |
-type CommonUnixConfig struct {
|
|
| 16 |
- ExecRoot string `json:"exec-root,omitempty"` |
|
| 17 |
- ContainerdAddr string `json:"containerd,omitempty"` |
|
| 18 |
- Runtimes map[string]types.Runtime `json:"runtimes,omitempty"` |
|
| 19 |
- DefaultRuntime string `json:"default-runtime,omitempty"` |
|
| 20 |
-} |
|
| 21 |
- |
|
| 22 |
-type commonUnixBridgeConfig struct {
|
|
| 23 |
- DefaultIP net.IP `json:"ip,omitempty"` |
|
| 24 |
- IP string `json:"bip,omitempty"` |
|
| 25 |
- DefaultGatewayIPv4 net.IP `json:"default-gateway,omitempty"` |
|
| 26 |
- DefaultGatewayIPv6 net.IP `json:"default-gateway-v6,omitempty"` |
|
| 27 |
- InterContainerCommunication bool `json:"icc,omitempty"` |
|
| 28 |
-} |
|
| 29 |
- |
|
| 30 |
-// InstallCommonUnixFlags adds command-line options to the top-level flag parser for |
|
| 31 |
-// the current process that are common across Unix platforms. |
|
| 32 |
-func (config *Config) InstallCommonUnixFlags(flags *pflag.FlagSet) {
|
|
| 33 |
- config.Runtimes = make(map[string]types.Runtime) |
|
| 34 |
- |
|
| 35 |
- flags.StringVarP(&config.SocketGroup, "group", "G", "docker", "Group for the unix socket") |
|
| 36 |
- flags.StringVar(&config.bridgeConfig.IP, "bip", "", "Specify network bridge IP") |
|
| 37 |
- flags.StringVarP(&config.bridgeConfig.Iface, "bridge", "b", "", "Attach containers to a network bridge") |
|
| 38 |
- flags.StringVar(&config.bridgeConfig.FixedCIDR, "fixed-cidr", "", "IPv4 subnet for fixed IPs") |
|
| 39 |
- flags.Var(opts.NewIPOpt(&config.bridgeConfig.DefaultGatewayIPv4, ""), "default-gateway", "Container default gateway IPv4 address") |
|
| 40 |
- flags.Var(opts.NewIPOpt(&config.bridgeConfig.DefaultGatewayIPv6, ""), "default-gateway-v6", "Container default gateway IPv6 address") |
|
| 41 |
- flags.BoolVar(&config.bridgeConfig.InterContainerCommunication, "icc", true, "Enable inter-container communication") |
|
| 42 |
- flags.Var(opts.NewIPOpt(&config.bridgeConfig.DefaultIP, "0.0.0.0"), "ip", "Default IP when binding container ports") |
|
| 43 |
- flags.Var(opts.NewNamedRuntimeOpt("runtimes", &config.Runtimes, stockRuntimeName), "add-runtime", "Register an additional OCI compatible runtime")
|
|
| 44 |
- flags.StringVar(&config.DefaultRuntime, "default-runtime", stockRuntimeName, "Default OCI runtime for containers") |
|
| 45 |
- |
|
| 46 |
-} |
|
| 47 |
- |
|
| 48 |
-// GetRuntime returns the runtime path and arguments for a given |
|
| 49 |
-// runtime name |
|
| 50 |
-func (config *Config) GetRuntime(name string) *types.Runtime {
|
|
| 51 |
- config.reloadLock.Lock() |
|
| 52 |
- defer config.reloadLock.Unlock() |
|
| 53 |
- if rt, ok := config.Runtimes[name]; ok {
|
|
| 54 |
- return &rt |
|
| 55 |
- } |
|
| 56 |
- return nil |
|
| 57 |
-} |
|
| 58 |
- |
|
| 59 |
-// GetDefaultRuntimeName returns the current default runtime |
|
| 60 |
-func (config *Config) GetDefaultRuntimeName() string {
|
|
| 61 |
- config.reloadLock.Lock() |
|
| 62 |
- rt := config.DefaultRuntime |
|
| 63 |
- config.reloadLock.Unlock() |
|
| 64 |
- |
|
| 65 |
- return rt |
|
| 66 |
-} |
|
| 67 |
- |
|
| 68 |
-// GetAllRuntimes returns a copy of the runtimes map |
|
| 69 |
-func (config *Config) GetAllRuntimes() map[string]types.Runtime {
|
|
| 70 |
- config.reloadLock.Lock() |
|
| 71 |
- rts := config.Runtimes |
|
| 72 |
- config.reloadLock.Unlock() |
|
| 73 |
- return rts |
|
| 74 |
-} |
|
| 75 |
- |
|
| 76 |
-// GetExecRoot returns the user configured Exec-root |
|
| 77 |
-func (config *Config) GetExecRoot() string {
|
|
| 78 |
- return config.ExecRoot |
|
| 79 |
-} |
|
| 80 |
- |
|
| 81 |
-// GetInitPath returns the configure docker-init path |
|
| 82 |
-func (config *Config) GetInitPath() string {
|
|
| 83 |
- config.reloadLock.Lock() |
|
| 84 |
- defer config.reloadLock.Unlock() |
|
| 85 |
- if config.InitPath != "" {
|
|
| 86 |
- return config.InitPath |
|
| 87 |
- } |
|
| 88 |
- return DefaultInitBinary |
|
| 89 |
-} |
| 9 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,47 +0,0 @@ |
| 1 |
-package daemon |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "github.com/spf13/pflag" |
|
| 5 |
-) |
|
| 6 |
- |
|
| 7 |
-var ( |
|
| 8 |
- defaultPidFile = "/system/volatile/docker/docker.pid" |
|
| 9 |
- defaultGraph = "/var/lib/docker" |
|
| 10 |
- defaultExec = "zones" |
|
| 11 |
-) |
|
| 12 |
- |
|
| 13 |
-// Config defines the configuration of a docker daemon. |
|
| 14 |
-// These are the configuration settings that you pass |
|
| 15 |
-// to the docker daemon when you launch it with say: `docker -d -e lxc` |
|
| 16 |
-type Config struct {
|
|
| 17 |
- CommonConfig |
|
| 18 |
- |
|
| 19 |
- // These fields are common to all unix platforms. |
|
| 20 |
- CommonUnixConfig |
|
| 21 |
-} |
|
| 22 |
- |
|
| 23 |
-// bridgeConfig stores all the bridge driver specific |
|
| 24 |
-// configuration. |
|
| 25 |
-type bridgeConfig struct {
|
|
| 26 |
- commonBridgeConfig |
|
| 27 |
- |
|
| 28 |
- // Fields below here are platform specific. |
|
| 29 |
- commonUnixBridgeConfig |
|
| 30 |
-} |
|
| 31 |
- |
|
| 32 |
-// InstallFlags adds command-line options to the top-level flag parser for |
|
| 33 |
-// the current process. |
|
| 34 |
-func (config *Config) InstallFlags(flags *pflag.FlagSet) {
|
|
| 35 |
- // First handle install flags which are consistent cross-platform |
|
| 36 |
- config.InstallCommonFlags(flags) |
|
| 37 |
- |
|
| 38 |
- // Then install flags common to unix platforms |
|
| 39 |
- config.InstallCommonUnixFlags(flags) |
|
| 40 |
- |
|
| 41 |
- // Then platform-specific install flags |
|
| 42 |
- config.attachExperimentalFlags(flags) |
|
| 43 |
-} |
|
| 44 |
- |
|
| 45 |
-func (config *Config) isSwarmCompatible() error {
|
|
| 46 |
- return nil |
|
| 47 |
-} |
| 48 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,229 +0,0 @@ |
| 1 |
-package daemon |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "io/ioutil" |
|
| 5 |
- "os" |
|
| 6 |
- "runtime" |
|
| 7 |
- "strings" |
|
| 8 |
- "testing" |
|
| 9 |
- |
|
| 10 |
- "github.com/docker/docker/opts" |
|
| 11 |
- "github.com/docker/docker/pkg/testutil/assert" |
|
| 12 |
- "github.com/spf13/pflag" |
|
| 13 |
-) |
|
| 14 |
- |
|
| 15 |
-func TestDaemonConfigurationNotFound(t *testing.T) {
|
|
| 16 |
- _, err := MergeDaemonConfigurations(&Config{}, nil, "/tmp/foo-bar-baz-docker")
|
|
| 17 |
- if err == nil || !os.IsNotExist(err) {
|
|
| 18 |
- t.Fatalf("expected does not exist error, got %v", err)
|
|
| 19 |
- } |
|
| 20 |
-} |
|
| 21 |
- |
|
| 22 |
-func TestDaemonBrokenConfiguration(t *testing.T) {
|
|
| 23 |
- f, err := ioutil.TempFile("", "docker-config-")
|
|
| 24 |
- if err != nil {
|
|
| 25 |
- t.Fatal(err) |
|
| 26 |
- } |
|
| 27 |
- |
|
| 28 |
- configFile := f.Name() |
|
| 29 |
- f.Write([]byte(`{"Debug": tru`))
|
|
| 30 |
- f.Close() |
|
| 31 |
- |
|
| 32 |
- _, err = MergeDaemonConfigurations(&Config{}, nil, configFile)
|
|
| 33 |
- if err == nil {
|
|
| 34 |
- t.Fatalf("expected error, got %v", err)
|
|
| 35 |
- } |
|
| 36 |
-} |
|
| 37 |
- |
|
| 38 |
-func TestParseClusterAdvertiseSettings(t *testing.T) {
|
|
| 39 |
- if runtime.GOOS == "solaris" {
|
|
| 40 |
- t.Skip("ClusterSettings not supported on Solaris\n")
|
|
| 41 |
- } |
|
| 42 |
- _, err := parseClusterAdvertiseSettings("something", "")
|
|
| 43 |
- if err != errDiscoveryDisabled {
|
|
| 44 |
- t.Fatalf("expected discovery disabled error, got %v\n", err)
|
|
| 45 |
- } |
|
| 46 |
- |
|
| 47 |
- _, err = parseClusterAdvertiseSettings("", "something")
|
|
| 48 |
- if err == nil {
|
|
| 49 |
- t.Fatalf("expected discovery store error, got %v\n", err)
|
|
| 50 |
- } |
|
| 51 |
- |
|
| 52 |
- _, err = parseClusterAdvertiseSettings("etcd", "127.0.0.1:8080")
|
|
| 53 |
- if err != nil {
|
|
| 54 |
- t.Fatal(err) |
|
| 55 |
- } |
|
| 56 |
-} |
|
| 57 |
- |
|
| 58 |
-func TestFindConfigurationConflicts(t *testing.T) {
|
|
| 59 |
- config := map[string]interface{}{"authorization-plugins": "foobar"}
|
|
| 60 |
- flags := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
|
| 61 |
- |
|
| 62 |
- flags.String("authorization-plugins", "", "")
|
|
| 63 |
- assert.NilError(t, flags.Set("authorization-plugins", "asdf"))
|
|
| 64 |
- |
|
| 65 |
- assert.Error(t, |
|
| 66 |
- findConfigurationConflicts(config, flags), |
|
| 67 |
- "authorization-plugins: (from flag: asdf, from file: foobar)") |
|
| 68 |
-} |
|
| 69 |
- |
|
| 70 |
-func TestFindConfigurationConflictsWithNamedOptions(t *testing.T) {
|
|
| 71 |
- config := map[string]interface{}{"hosts": []string{"qwer"}}
|
|
| 72 |
- flags := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
|
| 73 |
- |
|
| 74 |
- var hosts []string |
|
| 75 |
- flags.VarP(opts.NewNamedListOptsRef("hosts", &hosts, opts.ValidateHost), "host", "H", "Daemon socket(s) to connect to")
|
|
| 76 |
- assert.NilError(t, flags.Set("host", "tcp://127.0.0.1:4444"))
|
|
| 77 |
- assert.NilError(t, flags.Set("host", "unix:///var/run/docker.sock"))
|
|
| 78 |
- |
|
| 79 |
- assert.Error(t, findConfigurationConflicts(config, flags), "hosts") |
|
| 80 |
-} |
|
| 81 |
- |
|
| 82 |
-func TestDaemonConfigurationMergeConflicts(t *testing.T) {
|
|
| 83 |
- f, err := ioutil.TempFile("", "docker-config-")
|
|
| 84 |
- if err != nil {
|
|
| 85 |
- t.Fatal(err) |
|
| 86 |
- } |
|
| 87 |
- |
|
| 88 |
- configFile := f.Name() |
|
| 89 |
- f.Write([]byte(`{"debug": true}`))
|
|
| 90 |
- f.Close() |
|
| 91 |
- |
|
| 92 |
- flags := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
|
| 93 |
- flags.Bool("debug", false, "")
|
|
| 94 |
- flags.Set("debug", "false")
|
|
| 95 |
- |
|
| 96 |
- _, err = MergeDaemonConfigurations(&Config{}, flags, configFile)
|
|
| 97 |
- if err == nil {
|
|
| 98 |
- t.Fatal("expected error, got nil")
|
|
| 99 |
- } |
|
| 100 |
- if !strings.Contains(err.Error(), "debug") {
|
|
| 101 |
- t.Fatalf("expected debug conflict, got %v", err)
|
|
| 102 |
- } |
|
| 103 |
-} |
|
| 104 |
- |
|
| 105 |
-func TestDaemonConfigurationMergeConflictsWithInnerStructs(t *testing.T) {
|
|
| 106 |
- f, err := ioutil.TempFile("", "docker-config-")
|
|
| 107 |
- if err != nil {
|
|
| 108 |
- t.Fatal(err) |
|
| 109 |
- } |
|
| 110 |
- |
|
| 111 |
- configFile := f.Name() |
|
| 112 |
- f.Write([]byte(`{"tlscacert": "/etc/certificates/ca.pem"}`))
|
|
| 113 |
- f.Close() |
|
| 114 |
- |
|
| 115 |
- flags := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
|
| 116 |
- flags.String("tlscacert", "", "")
|
|
| 117 |
- flags.Set("tlscacert", "~/.docker/ca.pem")
|
|
| 118 |
- |
|
| 119 |
- _, err = MergeDaemonConfigurations(&Config{}, flags, configFile)
|
|
| 120 |
- if err == nil {
|
|
| 121 |
- t.Fatal("expected error, got nil")
|
|
| 122 |
- } |
|
| 123 |
- if !strings.Contains(err.Error(), "tlscacert") {
|
|
| 124 |
- t.Fatalf("expected tlscacert conflict, got %v", err)
|
|
| 125 |
- } |
|
| 126 |
-} |
|
| 127 |
- |
|
| 128 |
-func TestFindConfigurationConflictsWithUnknownKeys(t *testing.T) {
|
|
| 129 |
- config := map[string]interface{}{"tls-verify": "true"}
|
|
| 130 |
- flags := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
|
| 131 |
- |
|
| 132 |
- flags.Bool("tlsverify", false, "")
|
|
| 133 |
- err := findConfigurationConflicts(config, flags) |
|
| 134 |
- if err == nil {
|
|
| 135 |
- t.Fatal("expected error, got nil")
|
|
| 136 |
- } |
|
| 137 |
- if !strings.Contains(err.Error(), "the following directives don't match any configuration option: tls-verify") {
|
|
| 138 |
- t.Fatalf("expected tls-verify conflict, got %v", err)
|
|
| 139 |
- } |
|
| 140 |
-} |
|
| 141 |
- |
|
| 142 |
-func TestFindConfigurationConflictsWithMergedValues(t *testing.T) {
|
|
| 143 |
- var hosts []string |
|
| 144 |
- config := map[string]interface{}{"hosts": "tcp://127.0.0.1:2345"}
|
|
| 145 |
- flags := pflag.NewFlagSet("base", pflag.ContinueOnError)
|
|
| 146 |
- flags.VarP(opts.NewNamedListOptsRef("hosts", &hosts, nil), "host", "H", "")
|
|
| 147 |
- |
|
| 148 |
- err := findConfigurationConflicts(config, flags) |
|
| 149 |
- if err != nil {
|
|
| 150 |
- t.Fatal(err) |
|
| 151 |
- } |
|
| 152 |
- |
|
| 153 |
- flags.Set("host", "unix:///var/run/docker.sock")
|
|
| 154 |
- err = findConfigurationConflicts(config, flags) |
|
| 155 |
- if err == nil {
|
|
| 156 |
- t.Fatal("expected error, got nil")
|
|
| 157 |
- } |
|
| 158 |
- if !strings.Contains(err.Error(), "hosts: (from flag: [unix:///var/run/docker.sock], from file: tcp://127.0.0.1:2345)") {
|
|
| 159 |
- t.Fatalf("expected hosts conflict, got %v", err)
|
|
| 160 |
- } |
|
| 161 |
-} |
|
| 162 |
- |
|
| 163 |
-func TestValidateConfiguration(t *testing.T) {
|
|
| 164 |
- c1 := &Config{
|
|
| 165 |
- CommonConfig: CommonConfig{
|
|
| 166 |
- Labels: []string{"one"},
|
|
| 167 |
- }, |
|
| 168 |
- } |
|
| 169 |
- |
|
| 170 |
- err := ValidateConfiguration(c1) |
|
| 171 |
- if err == nil {
|
|
| 172 |
- t.Fatal("expected error, got nil")
|
|
| 173 |
- } |
|
| 174 |
- |
|
| 175 |
- c2 := &Config{
|
|
| 176 |
- CommonConfig: CommonConfig{
|
|
| 177 |
- Labels: []string{"one=two"},
|
|
| 178 |
- }, |
|
| 179 |
- } |
|
| 180 |
- |
|
| 181 |
- err = ValidateConfiguration(c2) |
|
| 182 |
- if err != nil {
|
|
| 183 |
- t.Fatalf("expected no error, got error %v", err)
|
|
| 184 |
- } |
|
| 185 |
- |
|
| 186 |
- c3 := &Config{
|
|
| 187 |
- CommonConfig: CommonConfig{
|
|
| 188 |
- DNS: []string{"1.1.1.1"},
|
|
| 189 |
- }, |
|
| 190 |
- } |
|
| 191 |
- |
|
| 192 |
- err = ValidateConfiguration(c3) |
|
| 193 |
- if err != nil {
|
|
| 194 |
- t.Fatalf("expected no error, got error %v", err)
|
|
| 195 |
- } |
|
| 196 |
- |
|
| 197 |
- c4 := &Config{
|
|
| 198 |
- CommonConfig: CommonConfig{
|
|
| 199 |
- DNS: []string{"1.1.1.1o"},
|
|
| 200 |
- }, |
|
| 201 |
- } |
|
| 202 |
- |
|
| 203 |
- err = ValidateConfiguration(c4) |
|
| 204 |
- if err == nil {
|
|
| 205 |
- t.Fatal("expected error, got nil")
|
|
| 206 |
- } |
|
| 207 |
- |
|
| 208 |
- c5 := &Config{
|
|
| 209 |
- CommonConfig: CommonConfig{
|
|
| 210 |
- DNSSearch: []string{"a.b.c"},
|
|
| 211 |
- }, |
|
| 212 |
- } |
|
| 213 |
- |
|
| 214 |
- err = ValidateConfiguration(c5) |
|
| 215 |
- if err != nil {
|
|
| 216 |
- t.Fatalf("expected no error, got error %v", err)
|
|
| 217 |
- } |
|
| 218 |
- |
|
| 219 |
- c6 := &Config{
|
|
| 220 |
- CommonConfig: CommonConfig{
|
|
| 221 |
- DNSSearch: []string{"123456"},
|
|
| 222 |
- }, |
|
| 223 |
- } |
|
| 224 |
- |
|
| 225 |
- err = ValidateConfiguration(c6) |
|
| 226 |
- if err == nil {
|
|
| 227 |
- t.Fatal("expected error, got nil")
|
|
| 228 |
- } |
|
| 229 |
-} |
| 230 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,110 +0,0 @@ |
| 1 |
-// +build linux freebsd |
|
| 2 |
- |
|
| 3 |
-package daemon |
|
| 4 |
- |
|
| 5 |
-import ( |
|
| 6 |
- "fmt" |
|
| 7 |
- |
|
| 8 |
- "github.com/docker/docker/opts" |
|
| 9 |
- units "github.com/docker/go-units" |
|
| 10 |
- "github.com/spf13/pflag" |
|
| 11 |
-) |
|
| 12 |
- |
|
| 13 |
-var ( |
|
| 14 |
- defaultPidFile = "/var/run/docker.pid" |
|
| 15 |
- defaultGraph = "/var/lib/docker" |
|
| 16 |
- defaultExecRoot = "/var/run/docker" |
|
| 17 |
- defaultShmSize = int64(67108864) |
|
| 18 |
-) |
|
| 19 |
- |
|
| 20 |
-// Config defines the configuration of a docker daemon. |
|
| 21 |
-// It includes json tags to deserialize configuration from a file |
|
| 22 |
-// using the same names that the flags in the command line uses. |
|
| 23 |
-type Config struct {
|
|
| 24 |
- CommonConfig |
|
| 25 |
- |
|
| 26 |
- // These fields are common to all unix platforms. |
|
| 27 |
- CommonUnixConfig |
|
| 28 |
- |
|
| 29 |
- // Fields below here are platform specific. |
|
| 30 |
- CgroupParent string `json:"cgroup-parent,omitempty"` |
|
| 31 |
- EnableSelinuxSupport bool `json:"selinux-enabled,omitempty"` |
|
| 32 |
- RemappedRoot string `json:"userns-remap,omitempty"` |
|
| 33 |
- Ulimits map[string]*units.Ulimit `json:"default-ulimits,omitempty"` |
|
| 34 |
- CPURealtimePeriod int64 `json:"cpu-rt-period,omitempty"` |
|
| 35 |
- CPURealtimeRuntime int64 `json:"cpu-rt-runtime,omitempty"` |
|
| 36 |
- OOMScoreAdjust int `json:"oom-score-adjust,omitempty"` |
|
| 37 |
- Init bool `json:"init,omitempty"` |
|
| 38 |
- InitPath string `json:"init-path,omitempty"` |
|
| 39 |
- SeccompProfile string `json:"seccomp-profile,omitempty"` |
|
| 40 |
- ShmSize opts.MemBytes `json:"default-shm-size,omitempty"` |
|
| 41 |
-} |
|
| 42 |
- |
|
| 43 |
-// bridgeConfig stores all the bridge driver specific |
|
| 44 |
-// configuration. |
|
| 45 |
-type bridgeConfig struct {
|
|
| 46 |
- commonBridgeConfig |
|
| 47 |
- |
|
| 48 |
- // These fields are common to all unix platforms. |
|
| 49 |
- commonUnixBridgeConfig |
|
| 50 |
- |
|
| 51 |
- // Fields below here are platform specific. |
|
| 52 |
- EnableIPv6 bool `json:"ipv6,omitempty"` |
|
| 53 |
- EnableIPTables bool `json:"iptables,omitempty"` |
|
| 54 |
- EnableIPForward bool `json:"ip-forward,omitempty"` |
|
| 55 |
- EnableIPMasq bool `json:"ip-masq,omitempty"` |
|
| 56 |
- EnableUserlandProxy bool `json:"userland-proxy,omitempty"` |
|
| 57 |
- UserlandProxyPath string `json:"userland-proxy-path,omitempty"` |
|
| 58 |
- FixedCIDRv6 string `json:"fixed-cidr-v6,omitempty"` |
|
| 59 |
-} |
|
| 60 |
- |
|
| 61 |
-// InstallFlags adds flags to the pflag.FlagSet to configure the daemon |
|
| 62 |
-func (config *Config) InstallFlags(flags *pflag.FlagSet) {
|
|
| 63 |
- // First handle install flags which are consistent cross-platform |
|
| 64 |
- config.InstallCommonFlags(flags) |
|
| 65 |
- |
|
| 66 |
- // Then install flags common to unix platforms |
|
| 67 |
- config.InstallCommonUnixFlags(flags) |
|
| 68 |
- |
|
| 69 |
- config.Ulimits = make(map[string]*units.Ulimit) |
|
| 70 |
- |
|
| 71 |
- // Set default value for `--default-shm-size` |
|
| 72 |
- config.ShmSize = opts.MemBytes(defaultShmSize) |
|
| 73 |
- |
|
| 74 |
- // Then platform-specific install flags |
|
| 75 |
- flags.BoolVar(&config.EnableSelinuxSupport, "selinux-enabled", false, "Enable selinux support") |
|
| 76 |
- flags.Var(opts.NewUlimitOpt(&config.Ulimits), "default-ulimit", "Default ulimits for containers") |
|
| 77 |
- flags.BoolVar(&config.bridgeConfig.EnableIPTables, "iptables", true, "Enable addition of iptables rules") |
|
| 78 |
- flags.BoolVar(&config.bridgeConfig.EnableIPForward, "ip-forward", true, "Enable net.ipv4.ip_forward") |
|
| 79 |
- flags.BoolVar(&config.bridgeConfig.EnableIPMasq, "ip-masq", true, "Enable IP masquerading") |
|
| 80 |
- flags.BoolVar(&config.bridgeConfig.EnableIPv6, "ipv6", false, "Enable IPv6 networking") |
|
| 81 |
- flags.StringVar(&config.ExecRoot, "exec-root", defaultExecRoot, "Root directory for execution state files") |
|
| 82 |
- flags.StringVar(&config.bridgeConfig.FixedCIDRv6, "fixed-cidr-v6", "", "IPv6 subnet for fixed IPs") |
|
| 83 |
- flags.BoolVar(&config.bridgeConfig.EnableUserlandProxy, "userland-proxy", true, "Use userland proxy for loopback traffic") |
|
| 84 |
- flags.StringVar(&config.bridgeConfig.UserlandProxyPath, "userland-proxy-path", "", "Path to the userland proxy binary") |
|
| 85 |
- flags.BoolVar(&config.EnableCors, "api-enable-cors", false, "Enable CORS headers in the Engine API, this is deprecated by --api-cors-header") |
|
| 86 |
- flags.MarkDeprecated("api-enable-cors", "Please use --api-cors-header")
|
|
| 87 |
- flags.StringVar(&config.CgroupParent, "cgroup-parent", "", "Set parent cgroup for all containers") |
|
| 88 |
- flags.StringVar(&config.RemappedRoot, "userns-remap", "", "User/Group setting for user namespaces") |
|
| 89 |
- flags.StringVar(&config.ContainerdAddr, "containerd", "", "Path to containerd socket") |
|
| 90 |
- flags.BoolVar(&config.LiveRestoreEnabled, "live-restore", false, "Enable live restore of docker when containers are still running") |
|
| 91 |
- flags.IntVar(&config.OOMScoreAdjust, "oom-score-adjust", -500, "Set the oom_score_adj for the daemon") |
|
| 92 |
- flags.BoolVar(&config.Init, "init", false, "Run an init in the container to forward signals and reap processes") |
|
| 93 |
- flags.StringVar(&config.InitPath, "init-path", "", "Path to the docker-init binary") |
|
| 94 |
- flags.Int64Var(&config.CPURealtimePeriod, "cpu-rt-period", 0, "Limit the CPU real-time period in microseconds") |
|
| 95 |
- flags.Int64Var(&config.CPURealtimeRuntime, "cpu-rt-runtime", 0, "Limit the CPU real-time runtime in microseconds") |
|
| 96 |
- flags.StringVar(&config.SeccompProfile, "seccomp-profile", "", "Path to seccomp profile") |
|
| 97 |
- flags.Var(&config.ShmSize, "default-shm-size", "Default shm size for containers") |
|
| 98 |
- |
|
| 99 |
- config.attachExperimentalFlags(flags) |
|
| 100 |
-} |
|
| 101 |
- |
|
| 102 |
-func (config *Config) isSwarmCompatible() error {
|
|
| 103 |
- if config.ClusterStore != "" || config.ClusterAdvertise != "" {
|
|
| 104 |
- return fmt.Errorf("--cluster-store and --cluster-advertise daemon configurations are incompatible with swarm mode")
|
|
| 105 |
- } |
|
| 106 |
- if config.LiveRestoreEnabled {
|
|
| 107 |
- return fmt.Errorf("--live-restore daemon configuration is incompatible with swarm mode")
|
|
| 108 |
- } |
|
| 109 |
- return nil |
|
| 110 |
-} |
| 111 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,134 +0,0 @@ |
| 1 |
-// +build !windows |
|
| 2 |
- |
|
| 3 |
-package daemon |
|
| 4 |
- |
|
| 5 |
-import ( |
|
| 6 |
- "io/ioutil" |
|
| 7 |
- "runtime" |
|
| 8 |
- |
|
| 9 |
- "testing" |
|
| 10 |
- |
|
| 11 |
- "github.com/docker/docker/pkg/testutil/assert" |
|
| 12 |
- "github.com/spf13/pflag" |
|
| 13 |
-) |
|
| 14 |
- |
|
| 15 |
-func TestDaemonConfigurationMerge(t *testing.T) {
|
|
| 16 |
- f, err := ioutil.TempFile("", "docker-config-")
|
|
| 17 |
- if err != nil {
|
|
| 18 |
- t.Fatal(err) |
|
| 19 |
- } |
|
| 20 |
- |
|
| 21 |
- configFile := f.Name() |
|
| 22 |
- |
|
| 23 |
- f.Write([]byte(` |
|
| 24 |
- {
|
|
| 25 |
- "debug": true, |
|
| 26 |
- "default-ulimits": {
|
|
| 27 |
- "nofile": {
|
|
| 28 |
- "Name": "nofile", |
|
| 29 |
- "Hard": 2048, |
|
| 30 |
- "Soft": 1024 |
|
| 31 |
- } |
|
| 32 |
- }, |
|
| 33 |
- "log-opts": {
|
|
| 34 |
- "tag": "test_tag" |
|
| 35 |
- } |
|
| 36 |
- }`)) |
|
| 37 |
- |
|
| 38 |
- f.Close() |
|
| 39 |
- |
|
| 40 |
- c := &Config{
|
|
| 41 |
- CommonConfig: CommonConfig{
|
|
| 42 |
- AutoRestart: true, |
|
| 43 |
- LogConfig: LogConfig{
|
|
| 44 |
- Type: "syslog", |
|
| 45 |
- Config: map[string]string{"tag": "test"},
|
|
| 46 |
- }, |
|
| 47 |
- }, |
|
| 48 |
- } |
|
| 49 |
- |
|
| 50 |
- cc, err := MergeDaemonConfigurations(c, nil, configFile) |
|
| 51 |
- if err != nil {
|
|
| 52 |
- t.Fatal(err) |
|
| 53 |
- } |
|
| 54 |
- if !cc.Debug {
|
|
| 55 |
- t.Fatalf("expected %v, got %v\n", true, cc.Debug)
|
|
| 56 |
- } |
|
| 57 |
- if !cc.AutoRestart {
|
|
| 58 |
- t.Fatalf("expected %v, got %v\n", true, cc.AutoRestart)
|
|
| 59 |
- } |
|
| 60 |
- if cc.LogConfig.Type != "syslog" {
|
|
| 61 |
- t.Fatalf("expected syslog config, got %q\n", cc.LogConfig)
|
|
| 62 |
- } |
|
| 63 |
- |
|
| 64 |
- if configValue, OK := cc.LogConfig.Config["tag"]; !OK {
|
|
| 65 |
- t.Fatal("expected syslog config attributes, got nil\n")
|
|
| 66 |
- } else {
|
|
| 67 |
- if configValue != "test_tag" {
|
|
| 68 |
- t.Fatalf("expected syslog config attributes 'tag=test_tag', got 'tag=%s'\n", configValue)
|
|
| 69 |
- } |
|
| 70 |
- } |
|
| 71 |
- |
|
| 72 |
- if cc.Ulimits == nil {
|
|
| 73 |
- t.Fatal("expected default ulimit config, got nil\n")
|
|
| 74 |
- } else {
|
|
| 75 |
- if _, OK := cc.Ulimits["nofile"]; OK {
|
|
| 76 |
- if cc.Ulimits["nofile"].Name != "nofile" || |
|
| 77 |
- cc.Ulimits["nofile"].Hard != 2048 || |
|
| 78 |
- cc.Ulimits["nofile"].Soft != 1024 {
|
|
| 79 |
- t.Fatalf("expected default ulimit name, hard and soft are nofile, 2048, 1024, got %s, %d, %d\n", cc.Ulimits["nofile"].Name, cc.Ulimits["nofile"].Hard, cc.Ulimits["nofile"].Soft)
|
|
| 80 |
- } |
|
| 81 |
- } else {
|
|
| 82 |
- t.Fatal("expected default ulimit name nofile, got nil\n")
|
|
| 83 |
- } |
|
| 84 |
- } |
|
| 85 |
-} |
|
| 86 |
- |
|
| 87 |
-func TestDaemonParseShmSize(t *testing.T) {
|
|
| 88 |
- if runtime.GOOS == "solaris" {
|
|
| 89 |
- t.Skip("ShmSize not supported on Solaris\n")
|
|
| 90 |
- } |
|
| 91 |
- flags := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
|
| 92 |
- |
|
| 93 |
- config := &Config{}
|
|
| 94 |
- config.InstallFlags(flags) |
|
| 95 |
- // By default `--default-shm-size=64M` |
|
| 96 |
- expectedValue := 64 * 1024 * 1024 |
|
| 97 |
- if config.ShmSize.Value() != int64(expectedValue) {
|
|
| 98 |
- t.Fatalf("expected default shm size %d, got %d", expectedValue, config.ShmSize.Value())
|
|
| 99 |
- } |
|
| 100 |
- assert.NilError(t, flags.Set("default-shm-size", "128M"))
|
|
| 101 |
- expectedValue = 128 * 1024 * 1024 |
|
| 102 |
- if config.ShmSize.Value() != int64(expectedValue) {
|
|
| 103 |
- t.Fatalf("expected default shm size %d, got %d", expectedValue, config.ShmSize.Value())
|
|
| 104 |
- } |
|
| 105 |
-} |
|
| 106 |
- |
|
| 107 |
-func TestDaemonConfigurationMergeShmSize(t *testing.T) {
|
|
| 108 |
- if runtime.GOOS == "solaris" {
|
|
| 109 |
- t.Skip("ShmSize not supported on Solaris\n")
|
|
| 110 |
- } |
|
| 111 |
- f, err := ioutil.TempFile("", "docker-config-")
|
|
| 112 |
- if err != nil {
|
|
| 113 |
- t.Fatal(err) |
|
| 114 |
- } |
|
| 115 |
- |
|
| 116 |
- configFile := f.Name() |
|
| 117 |
- |
|
| 118 |
- f.Write([]byte(` |
|
| 119 |
- {
|
|
| 120 |
- "default-shm-size": "1g" |
|
| 121 |
- }`)) |
|
| 122 |
- |
|
| 123 |
- f.Close() |
|
| 124 |
- |
|
| 125 |
- c := &Config{}
|
|
| 126 |
- cc, err := MergeDaemonConfigurations(c, nil, configFile) |
|
| 127 |
- if err != nil {
|
|
| 128 |
- t.Fatal(err) |
|
| 129 |
- } |
|
| 130 |
- expectedValue := 1 * 1024 * 1024 * 1024 |
|
| 131 |
- if cc.ShmSize.Value() != int64(expectedValue) {
|
|
| 132 |
- t.Fatalf("expected default shm size %d, got %d", expectedValue, cc.ShmSize.Value())
|
|
| 133 |
- } |
|
| 134 |
-} |
| 135 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,71 +0,0 @@ |
| 1 |
-package daemon |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "os" |
|
| 5 |
- "path/filepath" |
|
| 6 |
- |
|
| 7 |
- "github.com/docker/docker/api/types" |
|
| 8 |
- "github.com/spf13/pflag" |
|
| 9 |
-) |
|
| 10 |
- |
|
| 11 |
-var ( |
|
| 12 |
- defaultPidFile string |
|
| 13 |
- defaultGraph = filepath.Join(os.Getenv("programdata"), "docker")
|
|
| 14 |
-) |
|
| 15 |
- |
|
| 16 |
-// bridgeConfig stores all the bridge driver specific |
|
| 17 |
-// configuration. |
|
| 18 |
-type bridgeConfig struct {
|
|
| 19 |
- commonBridgeConfig |
|
| 20 |
-} |
|
| 21 |
- |
|
| 22 |
-// Config defines the configuration of a docker daemon. |
|
| 23 |
-// These are the configuration settings that you pass |
|
| 24 |
-// to the docker daemon when you launch it with say: `dockerd -e windows` |
|
| 25 |
-type Config struct {
|
|
| 26 |
- CommonConfig |
|
| 27 |
- |
|
| 28 |
- // Fields below here are platform specific. (There are none presently |
|
| 29 |
- // for the Windows daemon.) |
|
| 30 |
-} |
|
| 31 |
- |
|
| 32 |
-// InstallFlags adds flags to the pflag.FlagSet to configure the daemon |
|
| 33 |
-func (config *Config) InstallFlags(flags *pflag.FlagSet) {
|
|
| 34 |
- // First handle install flags which are consistent cross-platform |
|
| 35 |
- config.InstallCommonFlags(flags) |
|
| 36 |
- |
|
| 37 |
- // Then platform-specific install flags. |
|
| 38 |
- flags.StringVar(&config.bridgeConfig.FixedCIDR, "fixed-cidr", "", "IPv4 subnet for fixed IPs") |
|
| 39 |
- flags.StringVarP(&config.bridgeConfig.Iface, "bridge", "b", "", "Attach containers to a virtual switch") |
|
| 40 |
- flags.StringVarP(&config.SocketGroup, "group", "G", "", "Users or groups that can access the named pipe") |
|
| 41 |
-} |
|
| 42 |
- |
|
| 43 |
-// GetRuntime returns the runtime path and arguments for a given |
|
| 44 |
-// runtime name |
|
| 45 |
-func (config *Config) GetRuntime(name string) *types.Runtime {
|
|
| 46 |
- return nil |
|
| 47 |
-} |
|
| 48 |
- |
|
| 49 |
-// GetInitPath returns the configure docker-init path |
|
| 50 |
-func (config *Config) GetInitPath() string {
|
|
| 51 |
- return "" |
|
| 52 |
-} |
|
| 53 |
- |
|
| 54 |
-// GetDefaultRuntimeName returns the current default runtime |
|
| 55 |
-func (config *Config) GetDefaultRuntimeName() string {
|
|
| 56 |
- return stockRuntimeName |
|
| 57 |
-} |
|
| 58 |
- |
|
| 59 |
-// GetAllRuntimes returns a copy of the runtimes map |
|
| 60 |
-func (config *Config) GetAllRuntimes() map[string]types.Runtime {
|
|
| 61 |
- return map[string]types.Runtime{}
|
|
| 62 |
-} |
|
| 63 |
- |
|
| 64 |
-// GetExecRoot returns the user configured Exec-root |
|
| 65 |
-func (config *Config) GetExecRoot() string {
|
|
| 66 |
- return "" |
|
| 67 |
-} |
|
| 68 |
- |
|
| 69 |
-func (config *Config) isSwarmCompatible() error {
|
|
| 70 |
- return nil |
|
| 71 |
-} |
| 72 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,59 +0,0 @@ |
| 1 |
-// +build windows |
|
| 2 |
- |
|
| 3 |
-package daemon |
|
| 4 |
- |
|
| 5 |
-import ( |
|
| 6 |
- "io/ioutil" |
|
| 7 |
- "testing" |
|
| 8 |
-) |
|
| 9 |
- |
|
| 10 |
-func TestDaemonConfigurationMerge(t *testing.T) {
|
|
| 11 |
- f, err := ioutil.TempFile("", "docker-config-")
|
|
| 12 |
- if err != nil {
|
|
| 13 |
- t.Fatal(err) |
|
| 14 |
- } |
|
| 15 |
- |
|
| 16 |
- configFile := f.Name() |
|
| 17 |
- |
|
| 18 |
- f.Write([]byte(` |
|
| 19 |
- {
|
|
| 20 |
- "debug": true, |
|
| 21 |
- "log-opts": {
|
|
| 22 |
- "tag": "test_tag" |
|
| 23 |
- } |
|
| 24 |
- }`)) |
|
| 25 |
- |
|
| 26 |
- f.Close() |
|
| 27 |
- |
|
| 28 |
- c := &Config{
|
|
| 29 |
- CommonConfig: CommonConfig{
|
|
| 30 |
- AutoRestart: true, |
|
| 31 |
- LogConfig: LogConfig{
|
|
| 32 |
- Type: "syslog", |
|
| 33 |
- Config: map[string]string{"tag": "test"},
|
|
| 34 |
- }, |
|
| 35 |
- }, |
|
| 36 |
- } |
|
| 37 |
- |
|
| 38 |
- cc, err := MergeDaemonConfigurations(c, nil, configFile) |
|
| 39 |
- if err != nil {
|
|
| 40 |
- t.Fatal(err) |
|
| 41 |
- } |
|
| 42 |
- if !cc.Debug {
|
|
| 43 |
- t.Fatalf("expected %v, got %v\n", true, cc.Debug)
|
|
| 44 |
- } |
|
| 45 |
- if !cc.AutoRestart {
|
|
| 46 |
- t.Fatalf("expected %v, got %v\n", true, cc.AutoRestart)
|
|
| 47 |
- } |
|
| 48 |
- if cc.LogConfig.Type != "syslog" {
|
|
| 49 |
- t.Fatalf("expected syslog config, got %q\n", cc.LogConfig)
|
|
| 50 |
- } |
|
| 51 |
- |
|
| 52 |
- if configValue, OK := cc.LogConfig.Config["tag"]; !OK {
|
|
| 53 |
- t.Fatal("expected syslog config attributes, got nil\n")
|
|
| 54 |
- } else {
|
|
| 55 |
- if configValue != "test_tag" {
|
|
| 56 |
- t.Fatalf("expected syslog config attributes 'tag=test_tag', got 'tag=%s'\n", configValue)
|
|
| 57 |
- } |
|
| 58 |
- } |
|
| 59 |
-} |
| ... | ... |
@@ -282,7 +282,7 @@ func (daemon *Daemon) updateEndpointNetworkSettings(container *container.Contain |
| 282 | 282 |
} |
| 283 | 283 |
|
| 284 | 284 |
if container.HostConfig.NetworkMode == runconfig.DefaultDaemonNetworkMode() {
|
| 285 |
- container.NetworkSettings.Bridge = daemon.configStore.bridgeConfig.Iface |
|
| 285 |
+ container.NetworkSettings.Bridge = daemon.configStore.BridgeConfig.Iface |
|
| 286 | 286 |
} |
| 287 | 287 |
|
| 288 | 288 |
return nil |
| ... | ... |
@@ -24,6 +24,8 @@ import ( |
| 24 | 24 |
"github.com/docker/docker/api/types" |
| 25 | 25 |
containertypes "github.com/docker/docker/api/types/container" |
| 26 | 26 |
"github.com/docker/docker/container" |
| 27 |
+ "github.com/docker/docker/daemon/config" |
|
| 28 |
+ "github.com/docker/docker/daemon/discovery" |
|
| 27 | 29 |
"github.com/docker/docker/daemon/events" |
| 28 | 30 |
"github.com/docker/docker/daemon/exec" |
| 29 | 31 |
// register graph drivers |
| ... | ... |
@@ -82,14 +84,14 @@ type Daemon struct {
|
| 82 | 82 |
distributionMetadataStore dmetadata.Store |
| 83 | 83 |
trustKey libtrust.PrivateKey |
| 84 | 84 |
idIndex *truncindex.TruncIndex |
| 85 |
- configStore *Config |
|
| 85 |
+ configStore *config.Config |
|
| 86 | 86 |
statsCollector *stats.Collector |
| 87 | 87 |
defaultLogConfig containertypes.LogConfig |
| 88 | 88 |
RegistryService registry.Service |
| 89 | 89 |
EventsService *events.Events |
| 90 | 90 |
netController libnetwork.NetworkController |
| 91 | 91 |
volumes *store.VolumeStore |
| 92 |
- discoveryWatcher discoveryReloader |
|
| 92 |
+ discoveryWatcher discovery.Reloader |
|
| 93 | 93 |
root string |
| 94 | 94 |
seccompEnabled bool |
| 95 | 95 |
apparmorEnabled bool |
| ... | ... |
@@ -459,12 +461,12 @@ func (daemon *Daemon) IsSwarmCompatible() error {
|
| 459 | 459 |
if daemon.configStore == nil {
|
| 460 | 460 |
return nil |
| 461 | 461 |
} |
| 462 |
- return daemon.configStore.isSwarmCompatible() |
|
| 462 |
+ return daemon.configStore.IsSwarmCompatible() |
|
| 463 | 463 |
} |
| 464 | 464 |
|
| 465 | 465 |
// NewDaemon sets up everything for the daemon to be able to service |
| 466 | 466 |
// requests from the webserver. |
| 467 |
-func NewDaemon(config *Config, registryService registry.Service, containerdRemote libcontainerd.Remote) (daemon *Daemon, err error) {
|
|
| 467 |
+func NewDaemon(config *config.Config, registryService registry.Service, containerdRemote libcontainerd.Remote) (daemon *Daemon, err error) {
|
|
| 468 | 468 |
setDefaultMtu(config) |
| 469 | 469 |
|
| 470 | 470 |
// Ensure that we have a correct root key limit for launching containers. |
| ... | ... |
@@ -947,12 +949,12 @@ func (daemon *Daemon) setupInitLayer(initPath string) error {
|
| 947 | 947 |
return initlayer.Setup(initPath, rootUID, rootGID) |
| 948 | 948 |
} |
| 949 | 949 |
|
| 950 |
-func setDefaultMtu(config *Config) {
|
|
| 950 |
+func setDefaultMtu(conf *config.Config) {
|
|
| 951 | 951 |
// do nothing if the config does not have the default 0 value. |
| 952 |
- if config.Mtu != 0 {
|
|
| 952 |
+ if conf.Mtu != 0 {
|
|
| 953 | 953 |
return |
| 954 | 954 |
} |
| 955 |
- config.Mtu = defaultNetworkMtu |
|
| 955 |
+ conf.Mtu = config.DefaultNetworkMtu |
|
| 956 | 956 |
} |
| 957 | 957 |
|
| 958 | 958 |
func (daemon *Daemon) configureVolumes(rootUID, rootGID int) (*store.VolumeStore, error) {
|
| ... | ... |
@@ -975,17 +977,17 @@ func (daemon *Daemon) IsShuttingDown() bool {
|
| 975 | 975 |
} |
| 976 | 976 |
|
| 977 | 977 |
// initDiscovery initializes the discovery watcher for this daemon. |
| 978 |
-func (daemon *Daemon) initDiscovery(config *Config) error {
|
|
| 979 |
- advertise, err := parseClusterAdvertiseSettings(config.ClusterStore, config.ClusterAdvertise) |
|
| 978 |
+func (daemon *Daemon) initDiscovery(conf *config.Config) error {
|
|
| 979 |
+ advertise, err := config.ParseClusterAdvertiseSettings(conf.ClusterStore, conf.ClusterAdvertise) |
|
| 980 | 980 |
if err != nil {
|
| 981 |
- if err == errDiscoveryDisabled {
|
|
| 981 |
+ if err == discovery.ErrDiscoveryDisabled {
|
|
| 982 | 982 |
return nil |
| 983 | 983 |
} |
| 984 | 984 |
return err |
| 985 | 985 |
} |
| 986 | 986 |
|
| 987 |
- config.ClusterAdvertise = advertise |
|
| 988 |
- discoveryWatcher, err := initDiscovery(config.ClusterStore, config.ClusterAdvertise, config.ClusterOpts) |
|
| 987 |
+ conf.ClusterAdvertise = advertise |
|
| 988 |
+ discoveryWatcher, err := discovery.Init(conf.ClusterStore, conf.ClusterAdvertise, conf.ClusterOpts) |
|
| 989 | 989 |
if err != nil {
|
| 990 | 990 |
return fmt.Errorf("discovery initialization failed (%v)", err)
|
| 991 | 991 |
} |
| ... | ... |
@@ -1005,60 +1007,60 @@ func (daemon *Daemon) initDiscovery(config *Config) error {
|
| 1005 | 1005 |
// - Daemon max concurrent uploads |
| 1006 | 1006 |
// - Cluster discovery (reconfigure and restart) |
| 1007 | 1007 |
// - Daemon live restore |
| 1008 |
-// - Daemon shutdown timeout (in seconds) |
|
| 1009 |
-func (daemon *Daemon) Reload(config *Config) (err error) {
|
|
| 1008 |
+// - Daemon shutdown timeout (in seconds). |
|
| 1009 |
+func (daemon *Daemon) Reload(conf *config.Config) (err error) {
|
|
| 1010 | 1010 |
|
| 1011 |
- daemon.configStore.reloadLock.Lock() |
|
| 1011 |
+ daemon.configStore.Lock() |
|
| 1012 | 1012 |
|
| 1013 |
- attributes := daemon.platformReload(config) |
|
| 1013 |
+ attributes := daemon.platformReload(conf) |
|
| 1014 | 1014 |
|
| 1015 | 1015 |
defer func() {
|
| 1016 | 1016 |
// we're unlocking here, because |
| 1017 | 1017 |
// LogDaemonEventWithAttributes() -> SystemInfo() -> GetAllRuntimes() |
| 1018 | 1018 |
// holds that lock too. |
| 1019 |
- daemon.configStore.reloadLock.Unlock() |
|
| 1019 |
+ daemon.configStore.Unlock() |
|
| 1020 | 1020 |
if err == nil {
|
| 1021 | 1021 |
daemon.LogDaemonEventWithAttributes("reload", attributes)
|
| 1022 | 1022 |
} |
| 1023 | 1023 |
}() |
| 1024 | 1024 |
|
| 1025 |
- if err := daemon.reloadClusterDiscovery(config); err != nil {
|
|
| 1025 |
+ if err := daemon.reloadClusterDiscovery(conf); err != nil {
|
|
| 1026 | 1026 |
return err |
| 1027 | 1027 |
} |
| 1028 | 1028 |
|
| 1029 |
- if config.IsValueSet("labels") {
|
|
| 1030 |
- daemon.configStore.Labels = config.Labels |
|
| 1029 |
+ if conf.IsValueSet("labels") {
|
|
| 1030 |
+ daemon.configStore.Labels = conf.Labels |
|
| 1031 | 1031 |
} |
| 1032 |
- if config.IsValueSet("debug") {
|
|
| 1033 |
- daemon.configStore.Debug = config.Debug |
|
| 1032 |
+ if conf.IsValueSet("debug") {
|
|
| 1033 |
+ daemon.configStore.Debug = conf.Debug |
|
| 1034 | 1034 |
} |
| 1035 |
- if config.IsValueSet("insecure-registries") {
|
|
| 1036 |
- daemon.configStore.InsecureRegistries = config.InsecureRegistries |
|
| 1037 |
- if err := daemon.RegistryService.LoadInsecureRegistries(config.InsecureRegistries); err != nil {
|
|
| 1035 |
+ if conf.IsValueSet("insecure-registries") {
|
|
| 1036 |
+ daemon.configStore.InsecureRegistries = conf.InsecureRegistries |
|
| 1037 |
+ if err := daemon.RegistryService.LoadInsecureRegistries(conf.InsecureRegistries); err != nil {
|
|
| 1038 | 1038 |
return err |
| 1039 | 1039 |
} |
| 1040 | 1040 |
} |
| 1041 | 1041 |
|
| 1042 |
- if config.IsValueSet("registry-mirrors") {
|
|
| 1043 |
- daemon.configStore.Mirrors = config.Mirrors |
|
| 1044 |
- if err := daemon.RegistryService.LoadMirrors(config.Mirrors); err != nil {
|
|
| 1042 |
+ if conf.IsValueSet("registry-mirrors") {
|
|
| 1043 |
+ daemon.configStore.Mirrors = conf.Mirrors |
|
| 1044 |
+ if err := daemon.RegistryService.LoadMirrors(conf.Mirrors); err != nil {
|
|
| 1045 | 1045 |
return err |
| 1046 | 1046 |
} |
| 1047 | 1047 |
} |
| 1048 | 1048 |
|
| 1049 |
- if config.IsValueSet("live-restore") {
|
|
| 1050 |
- daemon.configStore.LiveRestoreEnabled = config.LiveRestoreEnabled |
|
| 1051 |
- if err := daemon.containerdRemote.UpdateOptions(libcontainerd.WithLiveRestore(config.LiveRestoreEnabled)); err != nil {
|
|
| 1049 |
+ if conf.IsValueSet("live-restore") {
|
|
| 1050 |
+ daemon.configStore.LiveRestoreEnabled = conf.LiveRestoreEnabled |
|
| 1051 |
+ if err := daemon.containerdRemote.UpdateOptions(libcontainerd.WithLiveRestore(conf.LiveRestoreEnabled)); err != nil {
|
|
| 1052 | 1052 |
return err |
| 1053 | 1053 |
} |
| 1054 | 1054 |
} |
| 1055 | 1055 |
|
| 1056 | 1056 |
// If no value is set for max-concurrent-downloads we assume it is the default value |
| 1057 | 1057 |
// We always "reset" as the cost is lightweight and easy to maintain. |
| 1058 |
- if config.IsValueSet("max-concurrent-downloads") && config.MaxConcurrentDownloads != nil {
|
|
| 1059 |
- *daemon.configStore.MaxConcurrentDownloads = *config.MaxConcurrentDownloads |
|
| 1058 |
+ if conf.IsValueSet("max-concurrent-downloads") && conf.MaxConcurrentDownloads != nil {
|
|
| 1059 |
+ *daemon.configStore.MaxConcurrentDownloads = *conf.MaxConcurrentDownloads |
|
| 1060 | 1060 |
} else {
|
| 1061 |
- maxConcurrentDownloads := defaultMaxConcurrentDownloads |
|
| 1061 |
+ maxConcurrentDownloads := config.DefaultMaxConcurrentDownloads |
|
| 1062 | 1062 |
daemon.configStore.MaxConcurrentDownloads = &maxConcurrentDownloads |
| 1063 | 1063 |
} |
| 1064 | 1064 |
logrus.Debugf("Reset Max Concurrent Downloads: %d", *daemon.configStore.MaxConcurrentDownloads)
|
| ... | ... |
@@ -1068,10 +1070,10 @@ func (daemon *Daemon) Reload(config *Config) (err error) {
|
| 1068 | 1068 |
|
| 1069 | 1069 |
// If no value is set for max-concurrent-upload we assume it is the default value |
| 1070 | 1070 |
// We always "reset" as the cost is lightweight and easy to maintain. |
| 1071 |
- if config.IsValueSet("max-concurrent-uploads") && config.MaxConcurrentUploads != nil {
|
|
| 1072 |
- *daemon.configStore.MaxConcurrentUploads = *config.MaxConcurrentUploads |
|
| 1071 |
+ if conf.IsValueSet("max-concurrent-uploads") && conf.MaxConcurrentUploads != nil {
|
|
| 1072 |
+ *daemon.configStore.MaxConcurrentUploads = *conf.MaxConcurrentUploads |
|
| 1073 | 1073 |
} else {
|
| 1074 |
- maxConcurrentUploads := defaultMaxConcurrentUploads |
|
| 1074 |
+ maxConcurrentUploads := config.DefaultMaxConcurrentUploads |
|
| 1075 | 1075 |
daemon.configStore.MaxConcurrentUploads = &maxConcurrentUploads |
| 1076 | 1076 |
} |
| 1077 | 1077 |
logrus.Debugf("Reset Max Concurrent Uploads: %d", *daemon.configStore.MaxConcurrentUploads)
|
| ... | ... |
@@ -1079,8 +1081,8 @@ func (daemon *Daemon) Reload(config *Config) (err error) {
|
| 1079 | 1079 |
daemon.uploadManager.SetConcurrency(*daemon.configStore.MaxConcurrentUploads) |
| 1080 | 1080 |
} |
| 1081 | 1081 |
|
| 1082 |
- if config.IsValueSet("shutdown-timeout") {
|
|
| 1083 |
- daemon.configStore.ShutdownTimeout = config.ShutdownTimeout |
|
| 1082 |
+ if conf.IsValueSet("shutdown-timeout") {
|
|
| 1083 |
+ daemon.configStore.ShutdownTimeout = conf.ShutdownTimeout |
|
| 1084 | 1084 |
logrus.Debugf("Reset Shutdown Timeout: %d", daemon.configStore.ShutdownTimeout)
|
| 1085 | 1085 |
} |
| 1086 | 1086 |
|
| ... | ... |
@@ -1137,52 +1139,52 @@ func (daemon *Daemon) Reload(config *Config) (err error) {
|
| 1137 | 1137 |
return nil |
| 1138 | 1138 |
} |
| 1139 | 1139 |
|
| 1140 |
-func (daemon *Daemon) reloadClusterDiscovery(config *Config) error {
|
|
| 1140 |
+func (daemon *Daemon) reloadClusterDiscovery(conf *config.Config) error {
|
|
| 1141 | 1141 |
var err error |
| 1142 | 1142 |
newAdvertise := daemon.configStore.ClusterAdvertise |
| 1143 | 1143 |
newClusterStore := daemon.configStore.ClusterStore |
| 1144 |
- if config.IsValueSet("cluster-advertise") {
|
|
| 1145 |
- if config.IsValueSet("cluster-store") {
|
|
| 1146 |
- newClusterStore = config.ClusterStore |
|
| 1144 |
+ if conf.IsValueSet("cluster-advertise") {
|
|
| 1145 |
+ if conf.IsValueSet("cluster-store") {
|
|
| 1146 |
+ newClusterStore = conf.ClusterStore |
|
| 1147 | 1147 |
} |
| 1148 |
- newAdvertise, err = parseClusterAdvertiseSettings(newClusterStore, config.ClusterAdvertise) |
|
| 1149 |
- if err != nil && err != errDiscoveryDisabled {
|
|
| 1148 |
+ newAdvertise, err = config.ParseClusterAdvertiseSettings(newClusterStore, conf.ClusterAdvertise) |
|
| 1149 |
+ if err != nil && err != discovery.ErrDiscoveryDisabled {
|
|
| 1150 | 1150 |
return err |
| 1151 | 1151 |
} |
| 1152 | 1152 |
} |
| 1153 | 1153 |
|
| 1154 | 1154 |
if daemon.clusterProvider != nil {
|
| 1155 |
- if err := config.isSwarmCompatible(); err != nil {
|
|
| 1155 |
+ if err := conf.IsSwarmCompatible(); err != nil {
|
|
| 1156 | 1156 |
return err |
| 1157 | 1157 |
} |
| 1158 | 1158 |
} |
| 1159 | 1159 |
|
| 1160 | 1160 |
// check discovery modifications |
| 1161 |
- if !modifiedDiscoverySettings(daemon.configStore, newAdvertise, newClusterStore, config.ClusterOpts) {
|
|
| 1161 |
+ if !config.ModifiedDiscoverySettings(daemon.configStore, newAdvertise, newClusterStore, conf.ClusterOpts) {
|
|
| 1162 | 1162 |
return nil |
| 1163 | 1163 |
} |
| 1164 | 1164 |
|
| 1165 | 1165 |
// enable discovery for the first time if it was not previously enabled |
| 1166 | 1166 |
if daemon.discoveryWatcher == nil {
|
| 1167 |
- discoveryWatcher, err := initDiscovery(newClusterStore, newAdvertise, config.ClusterOpts) |
|
| 1167 |
+ discoveryWatcher, err := discovery.Init(newClusterStore, newAdvertise, conf.ClusterOpts) |
|
| 1168 | 1168 |
if err != nil {
|
| 1169 | 1169 |
return fmt.Errorf("discovery initialization failed (%v)", err)
|
| 1170 | 1170 |
} |
| 1171 | 1171 |
daemon.discoveryWatcher = discoveryWatcher |
| 1172 | 1172 |
} else {
|
| 1173 |
- if err == errDiscoveryDisabled {
|
|
| 1173 |
+ if err == discovery.ErrDiscoveryDisabled {
|
|
| 1174 | 1174 |
// disable discovery if it was previously enabled and it's disabled now |
| 1175 | 1175 |
daemon.discoveryWatcher.Stop() |
| 1176 | 1176 |
} else {
|
| 1177 | 1177 |
// reload discovery |
| 1178 |
- if err = daemon.discoveryWatcher.Reload(config.ClusterStore, newAdvertise, config.ClusterOpts); err != nil {
|
|
| 1178 |
+ if err = daemon.discoveryWatcher.Reload(conf.ClusterStore, newAdvertise, conf.ClusterOpts); err != nil {
|
|
| 1179 | 1179 |
return err |
| 1180 | 1180 |
} |
| 1181 | 1181 |
} |
| 1182 | 1182 |
} |
| 1183 | 1183 |
|
| 1184 | 1184 |
daemon.configStore.ClusterStore = newClusterStore |
| 1185 |
- daemon.configStore.ClusterOpts = config.ClusterOpts |
|
| 1185 |
+ daemon.configStore.ClusterOpts = conf.ClusterOpts |
|
| 1186 | 1186 |
daemon.configStore.ClusterAdvertise = newAdvertise |
| 1187 | 1187 |
|
| 1188 | 1188 |
if daemon.netController == nil {
|
| ... | ... |
@@ -1201,11 +1203,11 @@ func (daemon *Daemon) reloadClusterDiscovery(config *Config) error {
|
| 1201 | 1201 |
return nil |
| 1202 | 1202 |
} |
| 1203 | 1203 |
|
| 1204 |
-func isBridgeNetworkDisabled(config *Config) bool {
|
|
| 1205 |
- return config.bridgeConfig.Iface == disableNetworkBridge |
|
| 1204 |
+func isBridgeNetworkDisabled(conf *config.Config) bool {
|
|
| 1205 |
+ return conf.BridgeConfig.Iface == config.DisableNetworkBridge |
|
| 1206 | 1206 |
} |
| 1207 | 1207 |
|
| 1208 |
-func (daemon *Daemon) networkOptions(dconfig *Config, pg plugingetter.PluginGetter, activeSandboxes map[string]interface{}) ([]nwconfig.Option, error) {
|
|
| 1208 |
+func (daemon *Daemon) networkOptions(dconfig *config.Config, pg plugingetter.PluginGetter, activeSandboxes map[string]interface{}) ([]nwconfig.Option, error) {
|
|
| 1209 | 1209 |
options := []nwconfig.Option{}
|
| 1210 | 1210 |
if dconfig == nil {
|
| 1211 | 1211 |
return options, nil |
| ... | ... |
@@ -1297,7 +1299,7 @@ func (daemon *Daemon) PluginGetter() *plugin.Store {
|
| 1297 | 1297 |
} |
| 1298 | 1298 |
|
| 1299 | 1299 |
// CreateDaemonRoot creates the root for the daemon |
| 1300 |
-func CreateDaemonRoot(config *Config) error {
|
|
| 1300 |
+func CreateDaemonRoot(config *config.Config) error {
|
|
| 1301 | 1301 |
// get the canonical path to the Docker root directory |
| 1302 | 1302 |
var realRoot string |
| 1303 | 1303 |
if _, err := os.Stat(config.Root); err != nil && os.IsNotExist(err) {
|
| ... | ... |
@@ -12,6 +12,7 @@ import ( |
| 12 | 12 |
|
| 13 | 13 |
containertypes "github.com/docker/docker/api/types/container" |
| 14 | 14 |
"github.com/docker/docker/container" |
| 15 |
+ "github.com/docker/docker/daemon/config" |
|
| 15 | 16 |
"github.com/docker/docker/pkg/discovery" |
| 16 | 17 |
_ "github.com/docker/docker/pkg/discovery/memory" |
| 17 | 18 |
"github.com/docker/docker/pkg/registrar" |
| ... | ... |
@@ -316,18 +317,18 @@ func TestMerge(t *testing.T) {
|
| 316 | 316 |
|
| 317 | 317 |
func TestDaemonReloadLabels(t *testing.T) {
|
| 318 | 318 |
daemon := &Daemon{}
|
| 319 |
- daemon.configStore = &Config{
|
|
| 320 |
- CommonConfig: CommonConfig{
|
|
| 319 |
+ daemon.configStore = &config.Config{
|
|
| 320 |
+ CommonConfig: config.CommonConfig{
|
|
| 321 | 321 |
Labels: []string{"foo:bar"},
|
| 322 | 322 |
}, |
| 323 | 323 |
} |
| 324 | 324 |
|
| 325 | 325 |
valuesSets := make(map[string]interface{})
|
| 326 | 326 |
valuesSets["labels"] = "foo:baz" |
| 327 |
- newConfig := &Config{
|
|
| 328 |
- CommonConfig: CommonConfig{
|
|
| 327 |
+ newConfig := &config.Config{
|
|
| 328 |
+ CommonConfig: config.CommonConfig{
|
|
| 329 | 329 |
Labels: []string{"foo:baz"},
|
| 330 |
- valuesSet: valuesSets, |
|
| 330 |
+ ValuesSet: valuesSets, |
|
| 331 | 331 |
}, |
| 332 | 332 |
} |
| 333 | 333 |
|
| ... | ... |
@@ -353,7 +354,7 @@ func TestDaemonReloadMirrors(t *testing.T) {
|
| 353 | 353 |
}, |
| 354 | 354 |
}) |
| 355 | 355 |
|
| 356 |
- daemon.configStore = &Config{}
|
|
| 356 |
+ daemon.configStore = &config.Config{}
|
|
| 357 | 357 |
|
| 358 | 358 |
type pair struct {
|
| 359 | 359 |
valid bool |
| ... | ... |
@@ -388,12 +389,12 @@ func TestDaemonReloadMirrors(t *testing.T) {
|
| 388 | 388 |
valuesSets := make(map[string]interface{})
|
| 389 | 389 |
valuesSets["registry-mirrors"] = value.mirrors |
| 390 | 390 |
|
| 391 |
- newConfig := &Config{
|
|
| 392 |
- CommonConfig: CommonConfig{
|
|
| 391 |
+ newConfig := &config.Config{
|
|
| 392 |
+ CommonConfig: config.CommonConfig{
|
|
| 393 | 393 |
ServiceOptions: registry.ServiceOptions{
|
| 394 | 394 |
Mirrors: value.mirrors, |
| 395 | 395 |
}, |
| 396 |
- valuesSet: valuesSets, |
|
| 396 |
+ ValuesSet: valuesSets, |
|
| 397 | 397 |
}, |
| 398 | 398 |
} |
| 399 | 399 |
|
| ... | ... |
@@ -448,7 +449,7 @@ func TestDaemonReloadInsecureRegistries(t *testing.T) {
|
| 448 | 448 |
}, |
| 449 | 449 |
}) |
| 450 | 450 |
|
| 451 |
- daemon.configStore = &Config{}
|
|
| 451 |
+ daemon.configStore = &config.Config{}
|
|
| 452 | 452 |
|
| 453 | 453 |
insecureRegistries := []string{
|
| 454 | 454 |
"127.0.0.0/8", // this will be kept |
| ... | ... |
@@ -461,12 +462,12 @@ func TestDaemonReloadInsecureRegistries(t *testing.T) {
|
| 461 | 461 |
valuesSets := make(map[string]interface{})
|
| 462 | 462 |
valuesSets["insecure-registries"] = insecureRegistries |
| 463 | 463 |
|
| 464 |
- newConfig := &Config{
|
|
| 465 |
- CommonConfig: CommonConfig{
|
|
| 464 |
+ newConfig := &config.Config{
|
|
| 465 |
+ CommonConfig: config.CommonConfig{
|
|
| 466 | 466 |
ServiceOptions: registry.ServiceOptions{
|
| 467 | 467 |
InsecureRegistries: insecureRegistries, |
| 468 | 468 |
}, |
| 469 |
- valuesSet: valuesSets, |
|
| 469 |
+ ValuesSet: valuesSets, |
|
| 470 | 470 |
}, |
| 471 | 471 |
} |
| 472 | 472 |
|
| ... | ... |
@@ -523,8 +524,8 @@ func TestDaemonReloadInsecureRegistries(t *testing.T) {
|
| 523 | 523 |
|
| 524 | 524 |
func TestDaemonReloadNotAffectOthers(t *testing.T) {
|
| 525 | 525 |
daemon := &Daemon{}
|
| 526 |
- daemon.configStore = &Config{
|
|
| 527 |
- CommonConfig: CommonConfig{
|
|
| 526 |
+ daemon.configStore = &config.Config{
|
|
| 527 |
+ CommonConfig: config.CommonConfig{
|
|
| 528 | 528 |
Labels: []string{"foo:bar"},
|
| 529 | 529 |
Debug: true, |
| 530 | 530 |
}, |
| ... | ... |
@@ -532,10 +533,10 @@ func TestDaemonReloadNotAffectOthers(t *testing.T) {
|
| 532 | 532 |
|
| 533 | 533 |
valuesSets := make(map[string]interface{})
|
| 534 | 534 |
valuesSets["labels"] = "foo:baz" |
| 535 |
- newConfig := &Config{
|
|
| 536 |
- CommonConfig: CommonConfig{
|
|
| 535 |
+ newConfig := &config.Config{
|
|
| 536 |
+ CommonConfig: config.CommonConfig{
|
|
| 537 | 537 |
Labels: []string{"foo:baz"},
|
| 538 |
- valuesSet: valuesSets, |
|
| 538 |
+ ValuesSet: valuesSets, |
|
| 539 | 539 |
}, |
| 540 | 540 |
} |
| 541 | 541 |
|
| ... | ... |
@@ -555,8 +556,8 @@ func TestDaemonReloadNotAffectOthers(t *testing.T) {
|
| 555 | 555 |
|
| 556 | 556 |
func TestDaemonDiscoveryReload(t *testing.T) {
|
| 557 | 557 |
daemon := &Daemon{}
|
| 558 |
- daemon.configStore = &Config{
|
|
| 559 |
- CommonConfig: CommonConfig{
|
|
| 558 |
+ daemon.configStore = &config.Config{
|
|
| 559 |
+ CommonConfig: config.CommonConfig{
|
|
| 560 | 560 |
ClusterStore: "memory://127.0.0.1", |
| 561 | 561 |
ClusterAdvertise: "127.0.0.1:3333", |
| 562 | 562 |
}, |
| ... | ... |
@@ -594,11 +595,11 @@ func TestDaemonDiscoveryReload(t *testing.T) {
|
| 594 | 594 |
valuesSets := make(map[string]interface{})
|
| 595 | 595 |
valuesSets["cluster-store"] = "memory://127.0.0.1:2222" |
| 596 | 596 |
valuesSets["cluster-advertise"] = "127.0.0.1:5555" |
| 597 |
- newConfig := &Config{
|
|
| 598 |
- CommonConfig: CommonConfig{
|
|
| 597 |
+ newConfig := &config.Config{
|
|
| 598 |
+ CommonConfig: config.CommonConfig{
|
|
| 599 | 599 |
ClusterStore: "memory://127.0.0.1:2222", |
| 600 | 600 |
ClusterAdvertise: "127.0.0.1:5555", |
| 601 |
- valuesSet: valuesSets, |
|
| 601 |
+ ValuesSet: valuesSets, |
|
| 602 | 602 |
}, |
| 603 | 603 |
} |
| 604 | 604 |
|
| ... | ... |
@@ -632,16 +633,16 @@ func TestDaemonDiscoveryReload(t *testing.T) {
|
| 632 | 632 |
|
| 633 | 633 |
func TestDaemonDiscoveryReloadFromEmptyDiscovery(t *testing.T) {
|
| 634 | 634 |
daemon := &Daemon{}
|
| 635 |
- daemon.configStore = &Config{}
|
|
| 635 |
+ daemon.configStore = &config.Config{}
|
|
| 636 | 636 |
|
| 637 | 637 |
valuesSet := make(map[string]interface{})
|
| 638 | 638 |
valuesSet["cluster-store"] = "memory://127.0.0.1:2222" |
| 639 | 639 |
valuesSet["cluster-advertise"] = "127.0.0.1:5555" |
| 640 |
- newConfig := &Config{
|
|
| 641 |
- CommonConfig: CommonConfig{
|
|
| 640 |
+ newConfig := &config.Config{
|
|
| 641 |
+ CommonConfig: config.CommonConfig{
|
|
| 642 | 642 |
ClusterStore: "memory://127.0.0.1:2222", |
| 643 | 643 |
ClusterAdvertise: "127.0.0.1:5555", |
| 644 |
- valuesSet: valuesSet, |
|
| 644 |
+ ValuesSet: valuesSet, |
|
| 645 | 645 |
}, |
| 646 | 646 |
} |
| 647 | 647 |
|
| ... | ... |
@@ -677,17 +678,17 @@ func TestDaemonDiscoveryReloadFromEmptyDiscovery(t *testing.T) {
|
| 677 | 677 |
|
| 678 | 678 |
func TestDaemonDiscoveryReloadOnlyClusterAdvertise(t *testing.T) {
|
| 679 | 679 |
daemon := &Daemon{}
|
| 680 |
- daemon.configStore = &Config{
|
|
| 681 |
- CommonConfig: CommonConfig{
|
|
| 680 |
+ daemon.configStore = &config.Config{
|
|
| 681 |
+ CommonConfig: config.CommonConfig{
|
|
| 682 | 682 |
ClusterStore: "memory://127.0.0.1", |
| 683 | 683 |
}, |
| 684 | 684 |
} |
| 685 | 685 |
valuesSets := make(map[string]interface{})
|
| 686 | 686 |
valuesSets["cluster-advertise"] = "127.0.0.1:5555" |
| 687 |
- newConfig := &Config{
|
|
| 688 |
- CommonConfig: CommonConfig{
|
|
| 687 |
+ newConfig := &config.Config{
|
|
| 688 |
+ CommonConfig: config.CommonConfig{
|
|
| 689 | 689 |
ClusterAdvertise: "127.0.0.1:5555", |
| 690 |
- valuesSet: valuesSets, |
|
| 690 |
+ ValuesSet: valuesSets, |
|
| 691 | 691 |
}, |
| 692 | 692 |
} |
| 693 | 693 |
expected := discovery.Entries{
|
| ... | ... |
@@ -23,6 +23,7 @@ import ( |
| 23 | 23 |
pblkiodev "github.com/docker/docker/api/types/blkiodev" |
| 24 | 24 |
containertypes "github.com/docker/docker/api/types/container" |
| 25 | 25 |
"github.com/docker/docker/container" |
| 26 |
+ "github.com/docker/docker/daemon/config" |
|
| 26 | 27 |
"github.com/docker/docker/image" |
| 27 | 28 |
"github.com/docker/docker/opts" |
| 28 | 29 |
"github.com/docker/docker/pkg/idtools" |
| ... | ... |
@@ -256,7 +257,7 @@ func (daemon *Daemon) adaptContainerSettings(hostConfig *containertypes.HostConf |
| 256 | 256 |
hostConfig.MemorySwap = hostConfig.Memory * 2 |
| 257 | 257 |
} |
| 258 | 258 |
if hostConfig.ShmSize == 0 {
|
| 259 |
- hostConfig.ShmSize = defaultShmSize |
|
| 259 |
+ hostConfig.ShmSize = config.DefaultShmSize |
|
| 260 | 260 |
if daemon.configStore != nil {
|
| 261 | 261 |
hostConfig.ShmSize = int64(daemon.configStore.ShmSize) |
| 262 | 262 |
} |
| ... | ... |
@@ -474,7 +475,7 @@ func (daemon *Daemon) getCgroupDriver() string {
|
| 474 | 474 |
} |
| 475 | 475 |
|
| 476 | 476 |
// getCD gets the raw value of the native.cgroupdriver option, if set. |
| 477 |
-func getCD(config *Config) string {
|
|
| 477 |
+func getCD(config *config.Config) string {
|
|
| 478 | 478 |
for _, option := range config.ExecOptions {
|
| 479 | 479 |
key, val, err := parsers.ParseKeyValueOpt(option) |
| 480 | 480 |
if err != nil || !strings.EqualFold(key, "native.cgroupdriver") {
|
| ... | ... |
@@ -486,7 +487,7 @@ func getCD(config *Config) string {
|
| 486 | 486 |
} |
| 487 | 487 |
|
| 488 | 488 |
// VerifyCgroupDriver validates native.cgroupdriver |
| 489 |
-func VerifyCgroupDriver(config *Config) error {
|
|
| 489 |
+func VerifyCgroupDriver(config *config.Config) error {
|
|
| 490 | 490 |
cd := getCD(config) |
| 491 | 491 |
if cd == "" || cd == cgroupFsDriver || cd == cgroupSystemdDriver {
|
| 492 | 492 |
return nil |
| ... | ... |
@@ -495,7 +496,7 @@ func VerifyCgroupDriver(config *Config) error {
|
| 495 | 495 |
} |
| 496 | 496 |
|
| 497 | 497 |
// UsingSystemd returns true if cli option includes native.cgroupdriver=systemd |
| 498 |
-func UsingSystemd(config *Config) bool {
|
|
| 498 |
+func UsingSystemd(config *config.Config) bool {
|
|
| 499 | 499 |
return getCD(config) == cgroupSystemdDriver |
| 500 | 500 |
} |
| 501 | 501 |
|
| ... | ... |
@@ -568,19 +569,19 @@ func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes. |
| 568 | 568 |
} |
| 569 | 569 |
|
| 570 | 570 |
// platformReload updates configuration with platform specific options |
| 571 |
-func (daemon *Daemon) platformReload(config *Config) map[string]string {
|
|
| 572 |
- if config.IsValueSet("runtimes") {
|
|
| 573 |
- daemon.configStore.Runtimes = config.Runtimes |
|
| 571 |
+func (daemon *Daemon) platformReload(conf *config.Config) map[string]string {
|
|
| 572 |
+ if conf.IsValueSet("runtimes") {
|
|
| 573 |
+ daemon.configStore.Runtimes = conf.Runtimes |
|
| 574 | 574 |
// Always set the default one |
| 575 |
- daemon.configStore.Runtimes[stockRuntimeName] = types.Runtime{Path: DefaultRuntimeBinary}
|
|
| 575 |
+ daemon.configStore.Runtimes[config.StockRuntimeName] = types.Runtime{Path: DefaultRuntimeBinary}
|
|
| 576 | 576 |
} |
| 577 | 577 |
|
| 578 |
- if config.DefaultRuntime != "" {
|
|
| 579 |
- daemon.configStore.DefaultRuntime = config.DefaultRuntime |
|
| 578 |
+ if conf.DefaultRuntime != "" {
|
|
| 579 |
+ daemon.configStore.DefaultRuntime = conf.DefaultRuntime |
|
| 580 | 580 |
} |
| 581 | 581 |
|
| 582 |
- if config.IsValueSet("default-shm-size") {
|
|
| 583 |
- daemon.configStore.ShmSize = config.ShmSize |
|
| 582 |
+ if conf.IsValueSet("default-shm-size") {
|
|
| 583 |
+ daemon.configStore.ShmSize = conf.ShmSize |
|
| 584 | 584 |
} |
| 585 | 585 |
|
| 586 | 586 |
// Update attributes |
| ... | ... |
@@ -600,33 +601,33 @@ func (daemon *Daemon) platformReload(config *Config) map[string]string {
|
| 600 | 600 |
} |
| 601 | 601 |
|
| 602 | 602 |
// verifyDaemonSettings performs validation of daemon config struct |
| 603 |
-func verifyDaemonSettings(config *Config) error {
|
|
| 603 |
+func verifyDaemonSettings(conf *config.Config) error {
|
|
| 604 | 604 |
// Check for mutually incompatible config options |
| 605 |
- if config.bridgeConfig.Iface != "" && config.bridgeConfig.IP != "" {
|
|
| 605 |
+ if conf.BridgeConfig.Iface != "" && conf.BridgeConfig.IP != "" {
|
|
| 606 | 606 |
return fmt.Errorf("You specified -b & --bip, mutually exclusive options. Please specify only one")
|
| 607 | 607 |
} |
| 608 |
- if !config.bridgeConfig.EnableIPTables && !config.bridgeConfig.InterContainerCommunication {
|
|
| 608 |
+ if !conf.BridgeConfig.EnableIPTables && !conf.BridgeConfig.InterContainerCommunication {
|
|
| 609 | 609 |
return fmt.Errorf("You specified --iptables=false with --icc=false. ICC=false uses iptables to function. Please set --icc or --iptables to true")
|
| 610 | 610 |
} |
| 611 |
- if !config.bridgeConfig.EnableIPTables && config.bridgeConfig.EnableIPMasq {
|
|
| 612 |
- config.bridgeConfig.EnableIPMasq = false |
|
| 611 |
+ if !conf.BridgeConfig.EnableIPTables && conf.BridgeConfig.EnableIPMasq {
|
|
| 612 |
+ conf.BridgeConfig.EnableIPMasq = false |
|
| 613 | 613 |
} |
| 614 |
- if err := VerifyCgroupDriver(config); err != nil {
|
|
| 614 |
+ if err := VerifyCgroupDriver(conf); err != nil {
|
|
| 615 | 615 |
return err |
| 616 | 616 |
} |
| 617 |
- if config.CgroupParent != "" && UsingSystemd(config) {
|
|
| 618 |
- if len(config.CgroupParent) <= 6 || !strings.HasSuffix(config.CgroupParent, ".slice") {
|
|
| 617 |
+ if conf.CgroupParent != "" && UsingSystemd(conf) {
|
|
| 618 |
+ if len(conf.CgroupParent) <= 6 || !strings.HasSuffix(conf.CgroupParent, ".slice") {
|
|
| 619 | 619 |
return fmt.Errorf("cgroup-parent for systemd cgroup should be a valid slice named as \"xxx.slice\"")
|
| 620 | 620 |
} |
| 621 | 621 |
} |
| 622 | 622 |
|
| 623 |
- if config.DefaultRuntime == "" {
|
|
| 624 |
- config.DefaultRuntime = stockRuntimeName |
|
| 623 |
+ if conf.DefaultRuntime == "" {
|
|
| 624 |
+ conf.DefaultRuntime = config.StockRuntimeName |
|
| 625 | 625 |
} |
| 626 |
- if config.Runtimes == nil {
|
|
| 627 |
- config.Runtimes = make(map[string]types.Runtime) |
|
| 626 |
+ if conf.Runtimes == nil {
|
|
| 627 |
+ conf.Runtimes = make(map[string]types.Runtime) |
|
| 628 | 628 |
} |
| 629 |
- config.Runtimes[stockRuntimeName] = types.Runtime{Path: DefaultRuntimeBinary}
|
|
| 629 |
+ conf.Runtimes[config.StockRuntimeName] = types.Runtime{Path: DefaultRuntimeBinary}
|
|
| 630 | 630 |
|
| 631 | 631 |
return nil |
| 632 | 632 |
} |
| ... | ... |
@@ -641,7 +642,7 @@ func checkSystem() error {
|
| 641 | 641 |
|
| 642 | 642 |
// configureMaxThreads sets the Go runtime max threads threshold |
| 643 | 643 |
// which is 90% of the kernel setting from /proc/sys/kernel/threads-max |
| 644 |
-func configureMaxThreads(config *Config) error {
|
|
| 644 |
+func configureMaxThreads(config *config.Config) error {
|
|
| 645 | 645 |
mt, err := ioutil.ReadFile("/proc/sys/kernel/threads-max")
|
| 646 | 646 |
if err != nil {
|
| 647 | 647 |
return err |
| ... | ... |
@@ -688,7 +689,7 @@ func overlaySupportsSelinux() (bool, error) {
|
| 688 | 688 |
} |
| 689 | 689 |
|
| 690 | 690 |
// configureKernelSecuritySupport configures and validates security support for the kernel |
| 691 |
-func configureKernelSecuritySupport(config *Config, driverName string) error {
|
|
| 691 |
+func configureKernelSecuritySupport(config *config.Config, driverName string) error {
|
|
| 692 | 692 |
if config.EnableSelinuxSupport {
|
| 693 | 693 |
if !selinuxEnabled() {
|
| 694 | 694 |
logrus.Warn("Docker could not enable SELinux on the host system")
|
| ... | ... |
@@ -713,7 +714,7 @@ func configureKernelSecuritySupport(config *Config, driverName string) error {
|
| 713 | 713 |
return nil |
| 714 | 714 |
} |
| 715 | 715 |
|
| 716 |
-func (daemon *Daemon) initNetworkController(config *Config, activeSandboxes map[string]interface{}) (libnetwork.NetworkController, error) {
|
|
| 716 |
+func (daemon *Daemon) initNetworkController(config *config.Config, activeSandboxes map[string]interface{}) (libnetwork.NetworkController, error) {
|
|
| 717 | 717 |
netOptions, err := daemon.networkOptions(config, daemon.PluginStore, activeSandboxes) |
| 718 | 718 |
if err != nil {
|
| 719 | 719 |
return nil, err |
| ... | ... |
@@ -762,12 +763,12 @@ func (daemon *Daemon) initNetworkController(config *Config, activeSandboxes map[ |
| 762 | 762 |
return controller, nil |
| 763 | 763 |
} |
| 764 | 764 |
|
| 765 |
-func driverOptions(config *Config) []nwconfig.Option {
|
|
| 765 |
+func driverOptions(config *config.Config) []nwconfig.Option {
|
|
| 766 | 766 |
bridgeConfig := options.Generic{
|
| 767 |
- "EnableIPForwarding": config.bridgeConfig.EnableIPForward, |
|
| 768 |
- "EnableIPTables": config.bridgeConfig.EnableIPTables, |
|
| 769 |
- "EnableUserlandProxy": config.bridgeConfig.EnableUserlandProxy, |
|
| 770 |
- "UserlandProxyPath": config.bridgeConfig.UserlandProxyPath} |
|
| 767 |
+ "EnableIPForwarding": config.BridgeConfig.EnableIPForward, |
|
| 768 |
+ "EnableIPTables": config.BridgeConfig.EnableIPTables, |
|
| 769 |
+ "EnableUserlandProxy": config.BridgeConfig.EnableUserlandProxy, |
|
| 770 |
+ "UserlandProxyPath": config.BridgeConfig.UserlandProxyPath} |
|
| 771 | 771 |
bridgeOption := options.Generic{netlabel.GenericData: bridgeConfig}
|
| 772 | 772 |
|
| 773 | 773 |
dOptions := []nwconfig.Option{}
|
| ... | ... |
@@ -775,22 +776,22 @@ func driverOptions(config *Config) []nwconfig.Option {
|
| 775 | 775 |
return dOptions |
| 776 | 776 |
} |
| 777 | 777 |
|
| 778 |
-func initBridgeDriver(controller libnetwork.NetworkController, config *Config) error {
|
|
| 778 |
+func initBridgeDriver(controller libnetwork.NetworkController, config *config.Config) error {
|
|
| 779 | 779 |
bridgeName := bridge.DefaultBridgeName |
| 780 |
- if config.bridgeConfig.Iface != "" {
|
|
| 781 |
- bridgeName = config.bridgeConfig.Iface |
|
| 780 |
+ if config.BridgeConfig.Iface != "" {
|
|
| 781 |
+ bridgeName = config.BridgeConfig.Iface |
|
| 782 | 782 |
} |
| 783 | 783 |
netOption := map[string]string{
|
| 784 | 784 |
bridge.BridgeName: bridgeName, |
| 785 | 785 |
bridge.DefaultBridge: strconv.FormatBool(true), |
| 786 | 786 |
netlabel.DriverMTU: strconv.Itoa(config.Mtu), |
| 787 |
- bridge.EnableIPMasquerade: strconv.FormatBool(config.bridgeConfig.EnableIPMasq), |
|
| 788 |
- bridge.EnableICC: strconv.FormatBool(config.bridgeConfig.InterContainerCommunication), |
|
| 787 |
+ bridge.EnableIPMasquerade: strconv.FormatBool(config.BridgeConfig.EnableIPMasq), |
|
| 788 |
+ bridge.EnableICC: strconv.FormatBool(config.BridgeConfig.InterContainerCommunication), |
|
| 789 | 789 |
} |
| 790 | 790 |
|
| 791 | 791 |
// --ip processing |
| 792 |
- if config.bridgeConfig.DefaultIP != nil {
|
|
| 793 |
- netOption[bridge.DefaultBindingIP] = config.bridgeConfig.DefaultIP.String() |
|
| 792 |
+ if config.BridgeConfig.DefaultIP != nil {
|
|
| 793 |
+ netOption[bridge.DefaultBindingIP] = config.BridgeConfig.DefaultIP.String() |
|
| 794 | 794 |
} |
| 795 | 795 |
|
| 796 | 796 |
var ( |
| ... | ... |
@@ -806,8 +807,8 @@ func initBridgeDriver(controller libnetwork.NetworkController, config *Config) e |
| 806 | 806 |
} |
| 807 | 807 |
|
| 808 | 808 |
nw := nwList[0] |
| 809 |
- if len(nwList) > 1 && config.bridgeConfig.FixedCIDR != "" {
|
|
| 810 |
- _, fCIDR, err := net.ParseCIDR(config.bridgeConfig.FixedCIDR) |
|
| 809 |
+ if len(nwList) > 1 && config.BridgeConfig.FixedCIDR != "" {
|
|
| 810 |
+ _, fCIDR, err := net.ParseCIDR(config.BridgeConfig.FixedCIDR) |
|
| 811 | 811 |
if err != nil {
|
| 812 | 812 |
return errors.Wrap(err, "parse CIDR failed") |
| 813 | 813 |
} |
| ... | ... |
@@ -826,9 +827,9 @@ func initBridgeDriver(controller libnetwork.NetworkController, config *Config) e |
| 826 | 826 |
ipamV4Conf.Gateway = nw.IP.String() |
| 827 | 827 |
} |
| 828 | 828 |
|
| 829 |
- if config.bridgeConfig.IP != "" {
|
|
| 830 |
- ipamV4Conf.PreferredPool = config.bridgeConfig.IP |
|
| 831 |
- ip, _, err := net.ParseCIDR(config.bridgeConfig.IP) |
|
| 829 |
+ if config.BridgeConfig.IP != "" {
|
|
| 830 |
+ ipamV4Conf.PreferredPool = config.BridgeConfig.IP |
|
| 831 |
+ ip, _, err := net.ParseCIDR(config.BridgeConfig.IP) |
|
| 832 | 832 |
if err != nil {
|
| 833 | 833 |
return err |
| 834 | 834 |
} |
| ... | ... |
@@ -837,8 +838,8 @@ func initBridgeDriver(controller libnetwork.NetworkController, config *Config) e |
| 837 | 837 |
logrus.Infof("Default bridge (%s) is assigned with an IP address %s. Daemon option --bip can be used to set a preferred IP address", bridgeName, ipamV4Conf.PreferredPool)
|
| 838 | 838 |
} |
| 839 | 839 |
|
| 840 |
- if config.bridgeConfig.FixedCIDR != "" {
|
|
| 841 |
- _, fCIDR, err := net.ParseCIDR(config.bridgeConfig.FixedCIDR) |
|
| 840 |
+ if config.BridgeConfig.FixedCIDR != "" {
|
|
| 841 |
+ _, fCIDR, err := net.ParseCIDR(config.BridgeConfig.FixedCIDR) |
|
| 842 | 842 |
if err != nil {
|
| 843 | 843 |
return err |
| 844 | 844 |
} |
| ... | ... |
@@ -846,13 +847,13 @@ func initBridgeDriver(controller libnetwork.NetworkController, config *Config) e |
| 846 | 846 |
ipamV4Conf.SubPool = fCIDR.String() |
| 847 | 847 |
} |
| 848 | 848 |
|
| 849 |
- if config.bridgeConfig.DefaultGatewayIPv4 != nil {
|
|
| 850 |
- ipamV4Conf.AuxAddresses["DefaultGatewayIPv4"] = config.bridgeConfig.DefaultGatewayIPv4.String() |
|
| 849 |
+ if config.BridgeConfig.DefaultGatewayIPv4 != nil {
|
|
| 850 |
+ ipamV4Conf.AuxAddresses["DefaultGatewayIPv4"] = config.BridgeConfig.DefaultGatewayIPv4.String() |
|
| 851 | 851 |
} |
| 852 | 852 |
|
| 853 | 853 |
var deferIPv6Alloc bool |
| 854 |
- if config.bridgeConfig.FixedCIDRv6 != "" {
|
|
| 855 |
- _, fCIDRv6, err := net.ParseCIDR(config.bridgeConfig.FixedCIDRv6) |
|
| 854 |
+ if config.BridgeConfig.FixedCIDRv6 != "" {
|
|
| 855 |
+ _, fCIDRv6, err := net.ParseCIDR(config.BridgeConfig.FixedCIDRv6) |
|
| 856 | 856 |
if err != nil {
|
| 857 | 857 |
return err |
| 858 | 858 |
} |
| ... | ... |
@@ -882,11 +883,11 @@ func initBridgeDriver(controller libnetwork.NetworkController, config *Config) e |
| 882 | 882 |
} |
| 883 | 883 |
} |
| 884 | 884 |
|
| 885 |
- if config.bridgeConfig.DefaultGatewayIPv6 != nil {
|
|
| 885 |
+ if config.BridgeConfig.DefaultGatewayIPv6 != nil {
|
|
| 886 | 886 |
if ipamV6Conf == nil {
|
| 887 | 887 |
ipamV6Conf = &libnetwork.IpamConf{AuxAddresses: make(map[string]string)}
|
| 888 | 888 |
} |
| 889 |
- ipamV6Conf.AuxAddresses["DefaultGatewayIPv6"] = config.bridgeConfig.DefaultGatewayIPv6.String() |
|
| 889 |
+ ipamV6Conf.AuxAddresses["DefaultGatewayIPv6"] = config.BridgeConfig.DefaultGatewayIPv6.String() |
|
| 890 | 890 |
} |
| 891 | 891 |
|
| 892 | 892 |
v4Conf := []*libnetwork.IpamConf{ipamV4Conf}
|
| ... | ... |
@@ -896,7 +897,7 @@ func initBridgeDriver(controller libnetwork.NetworkController, config *Config) e |
| 896 | 896 |
} |
| 897 | 897 |
// Initialize default network on "bridge" with the same name |
| 898 | 898 |
_, err = controller.NewNetwork("bridge", "bridge", "",
|
| 899 |
- libnetwork.NetworkOptionEnableIPv6(config.bridgeConfig.EnableIPv6), |
|
| 899 |
+ libnetwork.NetworkOptionEnableIPv6(config.BridgeConfig.EnableIPv6), |
|
| 900 | 900 |
libnetwork.NetworkOptionDriverOpts(netOption), |
| 901 | 901 |
libnetwork.NetworkOptionIpam("default", "", v4Conf, v6Conf, nil),
|
| 902 | 902 |
libnetwork.NetworkOptionDeferIPv6Alloc(deferIPv6Alloc)) |
| ... | ... |
@@ -1012,7 +1013,7 @@ func parseRemappedRoot(usergrp string) (string, string, error) {
|
| 1012 | 1012 |
return username, groupname, nil |
| 1013 | 1013 |
} |
| 1014 | 1014 |
|
| 1015 |
-func setupRemappedRoot(config *Config) ([]idtools.IDMap, []idtools.IDMap, error) {
|
|
| 1015 |
+func setupRemappedRoot(config *config.Config) ([]idtools.IDMap, []idtools.IDMap, error) {
|
|
| 1016 | 1016 |
if runtime.GOOS != "linux" && config.RemappedRoot != "" {
|
| 1017 | 1017 |
return nil, nil, fmt.Errorf("User namespaces are only supported on Linux")
|
| 1018 | 1018 |
} |
| ... | ... |
@@ -1045,7 +1046,7 @@ func setupRemappedRoot(config *Config) ([]idtools.IDMap, []idtools.IDMap, error) |
| 1045 | 1045 |
return uidMaps, gidMaps, nil |
| 1046 | 1046 |
} |
| 1047 | 1047 |
|
| 1048 |
-func setupDaemonRoot(config *Config, rootDir string, rootUID, rootGID int) error {
|
|
| 1048 |
+func setupDaemonRoot(config *config.Config, rootDir string, rootUID, rootGID int) error {
|
|
| 1049 | 1049 |
config.Root = rootDir |
| 1050 | 1050 |
// the docker root metadata directory needs to have execute permissions for all users (g+x,o+x) |
| 1051 | 1051 |
// so that syscalls executing as non-root, operating on subdirectories of the graph root |
| ... | ... |
@@ -1219,7 +1220,7 @@ func rootFSToAPIType(rootfs *image.RootFS) types.RootFS {
|
| 1219 | 1219 |
} |
| 1220 | 1220 |
|
| 1221 | 1221 |
// setupDaemonProcess sets various settings for the daemon's process |
| 1222 |
-func setupDaemonProcess(config *Config) error {
|
|
| 1222 |
+func setupDaemonProcess(config *config.Config) error {
|
|
| 1223 | 1223 |
// setup the daemons oom_score_adj |
| 1224 | 1224 |
return setupOOMScoreAdj(config.OOMScoreAdjust) |
| 1225 | 1225 |
} |
| ... | ... |
@@ -10,6 +10,7 @@ import ( |
| 10 | 10 |
|
| 11 | 11 |
containertypes "github.com/docker/docker/api/types/container" |
| 12 | 12 |
"github.com/docker/docker/container" |
| 13 |
+ "github.com/docker/docker/daemon/config" |
|
| 13 | 14 |
"github.com/docker/docker/volume" |
| 14 | 15 |
"github.com/docker/docker/volume/drivers" |
| 15 | 16 |
"github.com/docker/docker/volume/local" |
| ... | ... |
@@ -181,8 +182,8 @@ func TestParseSecurityOpt(t *testing.T) {
|
| 181 | 181 |
|
| 182 | 182 |
func TestNetworkOptions(t *testing.T) {
|
| 183 | 183 |
daemon := &Daemon{}
|
| 184 |
- dconfigCorrect := &Config{
|
|
| 185 |
- CommonConfig: CommonConfig{
|
|
| 184 |
+ dconfigCorrect := &config.Config{
|
|
| 185 |
+ CommonConfig: config.CommonConfig{
|
|
| 186 | 186 |
ClusterStore: "consul://localhost:8500", |
| 187 | 187 |
ClusterAdvertise: "192.168.0.1:8000", |
| 188 | 188 |
}, |
| ... | ... |
@@ -192,8 +193,8 @@ func TestNetworkOptions(t *testing.T) {
|
| 192 | 192 |
t.Fatalf("Expect networkOptions success, got error: %v", err)
|
| 193 | 193 |
} |
| 194 | 194 |
|
| 195 |
- dconfigWrong := &Config{
|
|
| 196 |
- CommonConfig: CommonConfig{
|
|
| 195 |
+ dconfigWrong := &config.Config{
|
|
| 196 |
+ CommonConfig: config.CommonConfig{
|
|
| 197 | 197 |
ClusterStore: "consul://localhost:8500://test://bbb", |
| 198 | 198 |
}, |
| 199 | 199 |
} |
| ... | ... |
@@ -11,6 +11,7 @@ import ( |
| 11 | 11 |
"github.com/docker/docker/api/types" |
| 12 | 12 |
containertypes "github.com/docker/docker/api/types/container" |
| 13 | 13 |
"github.com/docker/docker/container" |
| 14 |
+ "github.com/docker/docker/daemon/config" |
|
| 14 | 15 |
"github.com/docker/docker/image" |
| 15 | 16 |
"github.com/docker/docker/pkg/idtools" |
| 16 | 17 |
"github.com/docker/docker/pkg/parsers" |
| ... | ... |
@@ -210,12 +211,12 @@ func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes. |
| 210 | 210 |
} |
| 211 | 211 |
|
| 212 | 212 |
// platformReload updates configuration with platform specific options |
| 213 |
-func (daemon *Daemon) platformReload(config *Config) map[string]string {
|
|
| 213 |
+func (daemon *Daemon) platformReload(config *config.Config) map[string]string {
|
|
| 214 | 214 |
return map[string]string{}
|
| 215 | 215 |
} |
| 216 | 216 |
|
| 217 | 217 |
// verifyDaemonSettings performs validation of daemon config struct |
| 218 |
-func verifyDaemonSettings(config *Config) error {
|
|
| 218 |
+func verifyDaemonSettings(config *config.Config) error {
|
|
| 219 | 219 |
return nil |
| 220 | 220 |
} |
| 221 | 221 |
|
| ... | ... |
@@ -239,16 +240,16 @@ func checkSystem() error {
|
| 239 | 239 |
} |
| 240 | 240 |
|
| 241 | 241 |
// configureKernelSecuritySupport configures and validate security support for the kernel |
| 242 |
-func configureKernelSecuritySupport(config *Config, driverName string) error {
|
|
| 242 |
+func configureKernelSecuritySupport(config *config.Config, driverName string) error {
|
|
| 243 | 243 |
return nil |
| 244 | 244 |
} |
| 245 | 245 |
|
| 246 | 246 |
// configureMaxThreads sets the Go runtime max threads threshold |
| 247 |
-func configureMaxThreads(config *Config) error {
|
|
| 247 |
+func configureMaxThreads(config *config.Config) error {
|
|
| 248 | 248 |
return nil |
| 249 | 249 |
} |
| 250 | 250 |
|
| 251 |
-func (daemon *Daemon) initNetworkController(config *Config, activeSandboxes map[string]interface{}) (libnetwork.NetworkController, error) {
|
|
| 251 |
+func (daemon *Daemon) initNetworkController(config *config.Config, activeSandboxes map[string]interface{}) (libnetwork.NetworkController, error) {
|
|
| 252 | 252 |
netOptions, err := daemon.networkOptions(config, nil, nil) |
| 253 | 253 |
if err != nil {
|
| 254 | 254 |
return nil, err |
| ... | ... |
@@ -376,7 +377,7 @@ func (daemon *Daemon) initNetworkController(config *Config, activeSandboxes map[ |
| 376 | 376 |
return controller, nil |
| 377 | 377 |
} |
| 378 | 378 |
|
| 379 |
-func initBridgeDriver(controller libnetwork.NetworkController, config *Config) error {
|
|
| 379 |
+func initBridgeDriver(controller libnetwork.NetworkController, config *config.Config) error {
|
|
| 380 | 380 |
if _, err := controller.NetworkByName(runconfig.DefaultDaemonNetworkMode().NetworkName()); err == nil {
|
| 381 | 381 |
return nil |
| 382 | 382 |
} |
| ... | ... |
@@ -388,8 +389,8 @@ func initBridgeDriver(controller libnetwork.NetworkController, config *Config) e |
| 388 | 388 |
var ipamOption libnetwork.NetworkOption |
| 389 | 389 |
var subnetPrefix string |
| 390 | 390 |
|
| 391 |
- if config.bridgeConfig.FixedCIDR != "" {
|
|
| 392 |
- subnetPrefix = config.bridgeConfig.FixedCIDR |
|
| 391 |
+ if config.BridgeConfig.FixedCIDR != "" {
|
|
| 392 |
+ subnetPrefix = config.BridgeConfig.FixedCIDR |
|
| 393 | 393 |
} else {
|
| 394 | 394 |
// TP5 doesn't support properly detecting subnet |
| 395 | 395 |
osv := system.GetOSVersion() |
| ... | ... |
@@ -434,11 +435,11 @@ func (daemon *Daemon) cleanupMounts() error {
|
| 434 | 434 |
return nil |
| 435 | 435 |
} |
| 436 | 436 |
|
| 437 |
-func setupRemappedRoot(config *Config) ([]idtools.IDMap, []idtools.IDMap, error) {
|
|
| 437 |
+func setupRemappedRoot(config *config.Config) ([]idtools.IDMap, []idtools.IDMap, error) {
|
|
| 438 | 438 |
return nil, nil, nil |
| 439 | 439 |
} |
| 440 | 440 |
|
| 441 |
-func setupDaemonRoot(config *Config, rootDir string, rootUID, rootGID int) error {
|
|
| 441 |
+func setupDaemonRoot(config *config.Config, rootDir string, rootUID, rootGID int) error {
|
|
| 442 | 442 |
config.Root = rootDir |
| 443 | 443 |
// Create the root directory if it doesn't exists |
| 444 | 444 |
if err := system.MkdirAllWithACL(config.Root, 0); err != nil && !os.IsExist(err) {
|
| ... | ... |
@@ -479,7 +480,7 @@ func (daemon *Daemon) conditionalUnmountOnCleanup(container *container.Container |
| 479 | 479 |
return nil |
| 480 | 480 |
} |
| 481 | 481 |
|
| 482 |
-func driverOptions(config *Config) []nwconfig.Option {
|
|
| 482 |
+func driverOptions(config *config.Config) []nwconfig.Option {
|
|
| 483 | 483 |
return []nwconfig.Option{}
|
| 484 | 484 |
} |
| 485 | 485 |
|
| ... | ... |
@@ -593,7 +594,7 @@ func rootFSToAPIType(rootfs *image.RootFS) types.RootFS {
|
| 593 | 593 |
} |
| 594 | 594 |
} |
| 595 | 595 |
|
| 596 |
-func setupDaemonProcess(config *Config) error {
|
|
| 596 |
+func setupDaemonProcess(config *config.Config) error {
|
|
| 597 | 597 |
return nil |
| 598 | 598 |
} |
| 599 | 599 |
|
| 600 | 600 |
deleted file mode 100644 |
| ... | ... |
@@ -1,215 +0,0 @@ |
| 1 |
-package daemon |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "errors" |
|
| 5 |
- "fmt" |
|
| 6 |
- "reflect" |
|
| 7 |
- "strconv" |
|
| 8 |
- "time" |
|
| 9 |
- |
|
| 10 |
- "github.com/Sirupsen/logrus" |
|
| 11 |
- "github.com/docker/docker/pkg/discovery" |
|
| 12 |
- |
|
| 13 |
- // Register the libkv backends for discovery. |
|
| 14 |
- _ "github.com/docker/docker/pkg/discovery/kv" |
|
| 15 |
-) |
|
| 16 |
- |
|
| 17 |
-const ( |
|
| 18 |
- // defaultDiscoveryHeartbeat is the default value for discovery heartbeat interval. |
|
| 19 |
- defaultDiscoveryHeartbeat = 20 * time.Second |
|
| 20 |
- // defaultDiscoveryTTLFactor is the default TTL factor for discovery |
|
| 21 |
- defaultDiscoveryTTLFactor = 3 |
|
| 22 |
-) |
|
| 23 |
- |
|
| 24 |
-var errDiscoveryDisabled = errors.New("discovery is disabled")
|
|
| 25 |
- |
|
| 26 |
-type discoveryReloader interface {
|
|
| 27 |
- discovery.Watcher |
|
| 28 |
- Stop() |
|
| 29 |
- Reload(backend, address string, clusterOpts map[string]string) error |
|
| 30 |
- ReadyCh() <-chan struct{}
|
|
| 31 |
-} |
|
| 32 |
- |
|
| 33 |
-type daemonDiscoveryReloader struct {
|
|
| 34 |
- backend discovery.Backend |
|
| 35 |
- ticker *time.Ticker |
|
| 36 |
- term chan bool |
|
| 37 |
- readyCh chan struct{}
|
|
| 38 |
-} |
|
| 39 |
- |
|
| 40 |
-func (d *daemonDiscoveryReloader) Watch(stopCh <-chan struct{}) (<-chan discovery.Entries, <-chan error) {
|
|
| 41 |
- return d.backend.Watch(stopCh) |
|
| 42 |
-} |
|
| 43 |
- |
|
| 44 |
-func (d *daemonDiscoveryReloader) ReadyCh() <-chan struct{} {
|
|
| 45 |
- return d.readyCh |
|
| 46 |
-} |
|
| 47 |
- |
|
| 48 |
-func discoveryOpts(clusterOpts map[string]string) (time.Duration, time.Duration, error) {
|
|
| 49 |
- var ( |
|
| 50 |
- heartbeat = defaultDiscoveryHeartbeat |
|
| 51 |
- ttl = defaultDiscoveryTTLFactor * defaultDiscoveryHeartbeat |
|
| 52 |
- ) |
|
| 53 |
- |
|
| 54 |
- if hb, ok := clusterOpts["discovery.heartbeat"]; ok {
|
|
| 55 |
- h, err := strconv.Atoi(hb) |
|
| 56 |
- if err != nil {
|
|
| 57 |
- return time.Duration(0), time.Duration(0), err |
|
| 58 |
- } |
|
| 59 |
- |
|
| 60 |
- if h <= 0 {
|
|
| 61 |
- return time.Duration(0), time.Duration(0), |
|
| 62 |
- fmt.Errorf("discovery.heartbeat must be positive")
|
|
| 63 |
- } |
|
| 64 |
- |
|
| 65 |
- heartbeat = time.Duration(h) * time.Second |
|
| 66 |
- ttl = defaultDiscoveryTTLFactor * heartbeat |
|
| 67 |
- } |
|
| 68 |
- |
|
| 69 |
- if tstr, ok := clusterOpts["discovery.ttl"]; ok {
|
|
| 70 |
- t, err := strconv.Atoi(tstr) |
|
| 71 |
- if err != nil {
|
|
| 72 |
- return time.Duration(0), time.Duration(0), err |
|
| 73 |
- } |
|
| 74 |
- |
|
| 75 |
- if t <= 0 {
|
|
| 76 |
- return time.Duration(0), time.Duration(0), |
|
| 77 |
- fmt.Errorf("discovery.ttl must be positive")
|
|
| 78 |
- } |
|
| 79 |
- |
|
| 80 |
- ttl = time.Duration(t) * time.Second |
|
| 81 |
- |
|
| 82 |
- if _, ok := clusterOpts["discovery.heartbeat"]; !ok {
|
|
| 83 |
- h := int(t / defaultDiscoveryTTLFactor) |
|
| 84 |
- heartbeat = time.Duration(h) * time.Second |
|
| 85 |
- } |
|
| 86 |
- |
|
| 87 |
- if ttl <= heartbeat {
|
|
| 88 |
- return time.Duration(0), time.Duration(0), |
|
| 89 |
- fmt.Errorf("discovery.ttl timer must be greater than discovery.heartbeat")
|
|
| 90 |
- } |
|
| 91 |
- } |
|
| 92 |
- |
|
| 93 |
- return heartbeat, ttl, nil |
|
| 94 |
-} |
|
| 95 |
- |
|
| 96 |
-// initDiscovery initializes the nodes discovery subsystem by connecting to the specified backend |
|
| 97 |
-// and starts a registration loop to advertise the current node under the specified address. |
|
| 98 |
-func initDiscovery(backendAddress, advertiseAddress string, clusterOpts map[string]string) (discoveryReloader, error) {
|
|
| 99 |
- heartbeat, backend, err := parseDiscoveryOptions(backendAddress, clusterOpts) |
|
| 100 |
- if err != nil {
|
|
| 101 |
- return nil, err |
|
| 102 |
- } |
|
| 103 |
- |
|
| 104 |
- reloader := &daemonDiscoveryReloader{
|
|
| 105 |
- backend: backend, |
|
| 106 |
- ticker: time.NewTicker(heartbeat), |
|
| 107 |
- term: make(chan bool), |
|
| 108 |
- readyCh: make(chan struct{}),
|
|
| 109 |
- } |
|
| 110 |
- // We call Register() on the discovery backend in a loop for the whole lifetime of the daemon, |
|
| 111 |
- // but we never actually Watch() for nodes appearing and disappearing for the moment. |
|
| 112 |
- go reloader.advertiseHeartbeat(advertiseAddress) |
|
| 113 |
- return reloader, nil |
|
| 114 |
-} |
|
| 115 |
- |
|
| 116 |
-// advertiseHeartbeat registers the current node against the discovery backend using the specified |
|
| 117 |
-// address. The function never returns, as registration against the backend comes with a TTL and |
|
| 118 |
-// requires regular heartbeats. |
|
| 119 |
-func (d *daemonDiscoveryReloader) advertiseHeartbeat(address string) {
|
|
| 120 |
- var ready bool |
|
| 121 |
- if err := d.initHeartbeat(address); err == nil {
|
|
| 122 |
- ready = true |
|
| 123 |
- close(d.readyCh) |
|
| 124 |
- } |
|
| 125 |
- |
|
| 126 |
- for {
|
|
| 127 |
- select {
|
|
| 128 |
- case <-d.ticker.C: |
|
| 129 |
- if err := d.backend.Register(address); err != nil {
|
|
| 130 |
- logrus.Warnf("Registering as %q in discovery failed: %v", address, err)
|
|
| 131 |
- } else {
|
|
| 132 |
- if !ready {
|
|
| 133 |
- close(d.readyCh) |
|
| 134 |
- ready = true |
|
| 135 |
- } |
|
| 136 |
- } |
|
| 137 |
- case <-d.term: |
|
| 138 |
- return |
|
| 139 |
- } |
|
| 140 |
- } |
|
| 141 |
-} |
|
| 142 |
- |
|
| 143 |
-// initHeartbeat is used to do the first heartbeat. It uses a tight loop until |
|
| 144 |
-// either the timeout period is reached or the heartbeat is successful and returns. |
|
| 145 |
-func (d *daemonDiscoveryReloader) initHeartbeat(address string) error {
|
|
| 146 |
- // Setup a short ticker until the first heartbeat has succeeded |
|
| 147 |
- t := time.NewTicker(500 * time.Millisecond) |
|
| 148 |
- defer t.Stop() |
|
| 149 |
- // timeout makes sure that after a period of time we stop being so aggressive trying to reach the discovery service |
|
| 150 |
- timeout := time.After(60 * time.Second) |
|
| 151 |
- |
|
| 152 |
- for {
|
|
| 153 |
- select {
|
|
| 154 |
- case <-timeout: |
|
| 155 |
- return errors.New("timeout waiting for initial discovery")
|
|
| 156 |
- case <-d.term: |
|
| 157 |
- return errors.New("terminated")
|
|
| 158 |
- case <-t.C: |
|
| 159 |
- if err := d.backend.Register(address); err == nil {
|
|
| 160 |
- return nil |
|
| 161 |
- } |
|
| 162 |
- } |
|
| 163 |
- } |
|
| 164 |
-} |
|
| 165 |
- |
|
| 166 |
-// Reload makes the watcher to stop advertising and reconfigures it to advertise in a new address. |
|
| 167 |
-func (d *daemonDiscoveryReloader) Reload(backendAddress, advertiseAddress string, clusterOpts map[string]string) error {
|
|
| 168 |
- d.Stop() |
|
| 169 |
- |
|
| 170 |
- heartbeat, backend, err := parseDiscoveryOptions(backendAddress, clusterOpts) |
|
| 171 |
- if err != nil {
|
|
| 172 |
- return err |
|
| 173 |
- } |
|
| 174 |
- |
|
| 175 |
- d.backend = backend |
|
| 176 |
- d.ticker = time.NewTicker(heartbeat) |
|
| 177 |
- d.readyCh = make(chan struct{})
|
|
| 178 |
- |
|
| 179 |
- go d.advertiseHeartbeat(advertiseAddress) |
|
| 180 |
- return nil |
|
| 181 |
-} |
|
| 182 |
- |
|
| 183 |
-// Stop terminates the discovery advertising. |
|
| 184 |
-func (d *daemonDiscoveryReloader) Stop() {
|
|
| 185 |
- d.ticker.Stop() |
|
| 186 |
- d.term <- true |
|
| 187 |
-} |
|
| 188 |
- |
|
| 189 |
-func parseDiscoveryOptions(backendAddress string, clusterOpts map[string]string) (time.Duration, discovery.Backend, error) {
|
|
| 190 |
- heartbeat, ttl, err := discoveryOpts(clusterOpts) |
|
| 191 |
- if err != nil {
|
|
| 192 |
- return 0, nil, err |
|
| 193 |
- } |
|
| 194 |
- |
|
| 195 |
- backend, err := discovery.New(backendAddress, heartbeat, ttl, clusterOpts) |
|
| 196 |
- if err != nil {
|
|
| 197 |
- return 0, nil, err |
|
| 198 |
- } |
|
| 199 |
- return heartbeat, backend, nil |
|
| 200 |
-} |
|
| 201 |
- |
|
| 202 |
-// modifiedDiscoverySettings returns whether the discovery configuration has been modified or not. |
|
| 203 |
-func modifiedDiscoverySettings(config *Config, backendType, advertise string, clusterOpts map[string]string) bool {
|
|
| 204 |
- if config.ClusterStore != backendType || config.ClusterAdvertise != advertise {
|
|
| 205 |
- return true |
|
| 206 |
- } |
|
| 207 |
- |
|
| 208 |
- if (config.ClusterOpts == nil && clusterOpts == nil) || |
|
| 209 |
- (config.ClusterOpts == nil && len(clusterOpts) == 0) || |
|
| 210 |
- (len(config.ClusterOpts) == 0 && clusterOpts == nil) {
|
|
| 211 |
- return false |
|
| 212 |
- } |
|
| 213 |
- |
|
| 214 |
- return !reflect.DeepEqual(config.ClusterOpts, clusterOpts) |
|
| 215 |
-} |
| 216 | 1 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,201 @@ |
| 0 |
+package discovery |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "errors" |
|
| 4 |
+ "fmt" |
|
| 5 |
+ "strconv" |
|
| 6 |
+ "time" |
|
| 7 |
+ |
|
| 8 |
+ "github.com/Sirupsen/logrus" |
|
| 9 |
+ "github.com/docker/docker/pkg/discovery" |
|
| 10 |
+ |
|
| 11 |
+ // Register the libkv backends for discovery. |
|
| 12 |
+ _ "github.com/docker/docker/pkg/discovery/kv" |
|
| 13 |
+) |
|
| 14 |
+ |
|
| 15 |
+const ( |
|
| 16 |
+ // defaultDiscoveryHeartbeat is the default value for discovery heartbeat interval. |
|
| 17 |
+ defaultDiscoveryHeartbeat = 20 * time.Second |
|
| 18 |
+ // defaultDiscoveryTTLFactor is the default TTL factor for discovery |
|
| 19 |
+ defaultDiscoveryTTLFactor = 3 |
|
| 20 |
+) |
|
| 21 |
+ |
|
| 22 |
+// ErrDiscoveryDisabled is an error returned if the discovery is disabled |
|
| 23 |
+var ErrDiscoveryDisabled = errors.New("discovery is disabled")
|
|
| 24 |
+ |
|
| 25 |
+// Reloader is the discovery reloader of the daemon |
|
| 26 |
+type Reloader interface {
|
|
| 27 |
+ discovery.Watcher |
|
| 28 |
+ Stop() |
|
| 29 |
+ Reload(backend, address string, clusterOpts map[string]string) error |
|
| 30 |
+ ReadyCh() <-chan struct{}
|
|
| 31 |
+} |
|
| 32 |
+ |
|
| 33 |
+type daemonDiscoveryReloader struct {
|
|
| 34 |
+ backend discovery.Backend |
|
| 35 |
+ ticker *time.Ticker |
|
| 36 |
+ term chan bool |
|
| 37 |
+ readyCh chan struct{}
|
|
| 38 |
+} |
|
| 39 |
+ |
|
| 40 |
+func (d *daemonDiscoveryReloader) Watch(stopCh <-chan struct{}) (<-chan discovery.Entries, <-chan error) {
|
|
| 41 |
+ return d.backend.Watch(stopCh) |
|
| 42 |
+} |
|
| 43 |
+ |
|
| 44 |
+func (d *daemonDiscoveryReloader) ReadyCh() <-chan struct{} {
|
|
| 45 |
+ return d.readyCh |
|
| 46 |
+} |
|
| 47 |
+ |
|
| 48 |
+func discoveryOpts(clusterOpts map[string]string) (time.Duration, time.Duration, error) {
|
|
| 49 |
+ var ( |
|
| 50 |
+ heartbeat = defaultDiscoveryHeartbeat |
|
| 51 |
+ ttl = defaultDiscoveryTTLFactor * defaultDiscoveryHeartbeat |
|
| 52 |
+ ) |
|
| 53 |
+ |
|
| 54 |
+ if hb, ok := clusterOpts["discovery.heartbeat"]; ok {
|
|
| 55 |
+ h, err := strconv.Atoi(hb) |
|
| 56 |
+ if err != nil {
|
|
| 57 |
+ return time.Duration(0), time.Duration(0), err |
|
| 58 |
+ } |
|
| 59 |
+ |
|
| 60 |
+ if h <= 0 {
|
|
| 61 |
+ return time.Duration(0), time.Duration(0), |
|
| 62 |
+ fmt.Errorf("discovery.heartbeat must be positive")
|
|
| 63 |
+ } |
|
| 64 |
+ |
|
| 65 |
+ heartbeat = time.Duration(h) * time.Second |
|
| 66 |
+ ttl = defaultDiscoveryTTLFactor * heartbeat |
|
| 67 |
+ } |
|
| 68 |
+ |
|
| 69 |
+ if tstr, ok := clusterOpts["discovery.ttl"]; ok {
|
|
| 70 |
+ t, err := strconv.Atoi(tstr) |
|
| 71 |
+ if err != nil {
|
|
| 72 |
+ return time.Duration(0), time.Duration(0), err |
|
| 73 |
+ } |
|
| 74 |
+ |
|
| 75 |
+ if t <= 0 {
|
|
| 76 |
+ return time.Duration(0), time.Duration(0), |
|
| 77 |
+ fmt.Errorf("discovery.ttl must be positive")
|
|
| 78 |
+ } |
|
| 79 |
+ |
|
| 80 |
+ ttl = time.Duration(t) * time.Second |
|
| 81 |
+ |
|
| 82 |
+ if _, ok := clusterOpts["discovery.heartbeat"]; !ok {
|
|
| 83 |
+ h := int(t / defaultDiscoveryTTLFactor) |
|
| 84 |
+ heartbeat = time.Duration(h) * time.Second |
|
| 85 |
+ } |
|
| 86 |
+ |
|
| 87 |
+ if ttl <= heartbeat {
|
|
| 88 |
+ return time.Duration(0), time.Duration(0), |
|
| 89 |
+ fmt.Errorf("discovery.ttl timer must be greater than discovery.heartbeat")
|
|
| 90 |
+ } |
|
| 91 |
+ } |
|
| 92 |
+ |
|
| 93 |
+ return heartbeat, ttl, nil |
|
| 94 |
+} |
|
| 95 |
+ |
|
| 96 |
+// Init initializes the nodes discovery subsystem by connecting to the specified backend |
|
| 97 |
+// and starts a registration loop to advertise the current node under the specified address. |
|
| 98 |
+func Init(backendAddress, advertiseAddress string, clusterOpts map[string]string) (Reloader, error) {
|
|
| 99 |
+ heartbeat, backend, err := parseDiscoveryOptions(backendAddress, clusterOpts) |
|
| 100 |
+ if err != nil {
|
|
| 101 |
+ return nil, err |
|
| 102 |
+ } |
|
| 103 |
+ |
|
| 104 |
+ reloader := &daemonDiscoveryReloader{
|
|
| 105 |
+ backend: backend, |
|
| 106 |
+ ticker: time.NewTicker(heartbeat), |
|
| 107 |
+ term: make(chan bool), |
|
| 108 |
+ readyCh: make(chan struct{}),
|
|
| 109 |
+ } |
|
| 110 |
+ // We call Register() on the discovery backend in a loop for the whole lifetime of the daemon, |
|
| 111 |
+ // but we never actually Watch() for nodes appearing and disappearing for the moment. |
|
| 112 |
+ go reloader.advertiseHeartbeat(advertiseAddress) |
|
| 113 |
+ return reloader, nil |
|
| 114 |
+} |
|
| 115 |
+ |
|
| 116 |
+// advertiseHeartbeat registers the current node against the discovery backend using the specified |
|
| 117 |
+// address. The function never returns, as registration against the backend comes with a TTL and |
|
| 118 |
+// requires regular heartbeats. |
|
| 119 |
+func (d *daemonDiscoveryReloader) advertiseHeartbeat(address string) {
|
|
| 120 |
+ var ready bool |
|
| 121 |
+ if err := d.initHeartbeat(address); err == nil {
|
|
| 122 |
+ ready = true |
|
| 123 |
+ close(d.readyCh) |
|
| 124 |
+ } |
|
| 125 |
+ |
|
| 126 |
+ for {
|
|
| 127 |
+ select {
|
|
| 128 |
+ case <-d.ticker.C: |
|
| 129 |
+ if err := d.backend.Register(address); err != nil {
|
|
| 130 |
+ logrus.Warnf("Registering as %q in discovery failed: %v", address, err)
|
|
| 131 |
+ } else {
|
|
| 132 |
+ if !ready {
|
|
| 133 |
+ close(d.readyCh) |
|
| 134 |
+ ready = true |
|
| 135 |
+ } |
|
| 136 |
+ } |
|
| 137 |
+ case <-d.term: |
|
| 138 |
+ return |
|
| 139 |
+ } |
|
| 140 |
+ } |
|
| 141 |
+} |
|
| 142 |
+ |
|
| 143 |
+// initHeartbeat is used to do the first heartbeat. It uses a tight loop until |
|
| 144 |
+// either the timeout period is reached or the heartbeat is successful and returns. |
|
| 145 |
+func (d *daemonDiscoveryReloader) initHeartbeat(address string) error {
|
|
| 146 |
+ // Setup a short ticker until the first heartbeat has succeeded |
|
| 147 |
+ t := time.NewTicker(500 * time.Millisecond) |
|
| 148 |
+ defer t.Stop() |
|
| 149 |
+ // timeout makes sure that after a period of time we stop being so aggressive trying to reach the discovery service |
|
| 150 |
+ timeout := time.After(60 * time.Second) |
|
| 151 |
+ |
|
| 152 |
+ for {
|
|
| 153 |
+ select {
|
|
| 154 |
+ case <-timeout: |
|
| 155 |
+ return errors.New("timeout waiting for initial discovery")
|
|
| 156 |
+ case <-d.term: |
|
| 157 |
+ return errors.New("terminated")
|
|
| 158 |
+ case <-t.C: |
|
| 159 |
+ if err := d.backend.Register(address); err == nil {
|
|
| 160 |
+ return nil |
|
| 161 |
+ } |
|
| 162 |
+ } |
|
| 163 |
+ } |
|
| 164 |
+} |
|
| 165 |
+ |
|
| 166 |
+// Reload makes the watcher to stop advertising and reconfigures it to advertise in a new address. |
|
| 167 |
+func (d *daemonDiscoveryReloader) Reload(backendAddress, advertiseAddress string, clusterOpts map[string]string) error {
|
|
| 168 |
+ d.Stop() |
|
| 169 |
+ |
|
| 170 |
+ heartbeat, backend, err := parseDiscoveryOptions(backendAddress, clusterOpts) |
|
| 171 |
+ if err != nil {
|
|
| 172 |
+ return err |
|
| 173 |
+ } |
|
| 174 |
+ |
|
| 175 |
+ d.backend = backend |
|
| 176 |
+ d.ticker = time.NewTicker(heartbeat) |
|
| 177 |
+ d.readyCh = make(chan struct{})
|
|
| 178 |
+ |
|
| 179 |
+ go d.advertiseHeartbeat(advertiseAddress) |
|
| 180 |
+ return nil |
|
| 181 |
+} |
|
| 182 |
+ |
|
| 183 |
+// Stop terminates the discovery advertising. |
|
| 184 |
+func (d *daemonDiscoveryReloader) Stop() {
|
|
| 185 |
+ d.ticker.Stop() |
|
| 186 |
+ d.term <- true |
|
| 187 |
+} |
|
| 188 |
+ |
|
| 189 |
+func parseDiscoveryOptions(backendAddress string, clusterOpts map[string]string) (time.Duration, discovery.Backend, error) {
|
|
| 190 |
+ heartbeat, ttl, err := discoveryOpts(clusterOpts) |
|
| 191 |
+ if err != nil {
|
|
| 192 |
+ return 0, nil, err |
|
| 193 |
+ } |
|
| 194 |
+ |
|
| 195 |
+ backend, err := discovery.New(backendAddress, heartbeat, ttl, clusterOpts) |
|
| 196 |
+ if err != nil {
|
|
| 197 |
+ return 0, nil, err |
|
| 198 |
+ } |
|
| 199 |
+ return heartbeat, backend, nil |
|
| 200 |
+} |
| 0 | 201 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,103 @@ |
| 0 |
+package discovery |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "testing" |
|
| 4 |
+ "time" |
|
| 5 |
+) |
|
| 6 |
+ |
|
| 7 |
+func TestDiscoveryOpts(t *testing.T) {
|
|
| 8 |
+ clusterOpts := map[string]string{"discovery.heartbeat": "10", "discovery.ttl": "5"}
|
|
| 9 |
+ heartbeat, ttl, err := discoveryOpts(clusterOpts) |
|
| 10 |
+ if err == nil {
|
|
| 11 |
+ t.Fatalf("discovery.ttl < discovery.heartbeat must fail")
|
|
| 12 |
+ } |
|
| 13 |
+ |
|
| 14 |
+ clusterOpts = map[string]string{"discovery.heartbeat": "10", "discovery.ttl": "10"}
|
|
| 15 |
+ heartbeat, ttl, err = discoveryOpts(clusterOpts) |
|
| 16 |
+ if err == nil {
|
|
| 17 |
+ t.Fatalf("discovery.ttl == discovery.heartbeat must fail")
|
|
| 18 |
+ } |
|
| 19 |
+ |
|
| 20 |
+ clusterOpts = map[string]string{"discovery.heartbeat": "-10", "discovery.ttl": "10"}
|
|
| 21 |
+ heartbeat, ttl, err = discoveryOpts(clusterOpts) |
|
| 22 |
+ if err == nil {
|
|
| 23 |
+ t.Fatalf("negative discovery.heartbeat must fail")
|
|
| 24 |
+ } |
|
| 25 |
+ |
|
| 26 |
+ clusterOpts = map[string]string{"discovery.heartbeat": "10", "discovery.ttl": "-10"}
|
|
| 27 |
+ heartbeat, ttl, err = discoveryOpts(clusterOpts) |
|
| 28 |
+ if err == nil {
|
|
| 29 |
+ t.Fatalf("negative discovery.ttl must fail")
|
|
| 30 |
+ } |
|
| 31 |
+ |
|
| 32 |
+ clusterOpts = map[string]string{"discovery.heartbeat": "invalid"}
|
|
| 33 |
+ heartbeat, ttl, err = discoveryOpts(clusterOpts) |
|
| 34 |
+ if err == nil {
|
|
| 35 |
+ t.Fatalf("invalid discovery.heartbeat must fail")
|
|
| 36 |
+ } |
|
| 37 |
+ |
|
| 38 |
+ clusterOpts = map[string]string{"discovery.ttl": "invalid"}
|
|
| 39 |
+ heartbeat, ttl, err = discoveryOpts(clusterOpts) |
|
| 40 |
+ if err == nil {
|
|
| 41 |
+ t.Fatalf("invalid discovery.ttl must fail")
|
|
| 42 |
+ } |
|
| 43 |
+ |
|
| 44 |
+ clusterOpts = map[string]string{"discovery.heartbeat": "10", "discovery.ttl": "20"}
|
|
| 45 |
+ heartbeat, ttl, err = discoveryOpts(clusterOpts) |
|
| 46 |
+ if err != nil {
|
|
| 47 |
+ t.Fatal(err) |
|
| 48 |
+ } |
|
| 49 |
+ |
|
| 50 |
+ if heartbeat != 10*time.Second {
|
|
| 51 |
+ t.Fatalf("Heartbeat - Expected : %v, Actual : %v", 10*time.Second, heartbeat)
|
|
| 52 |
+ } |
|
| 53 |
+ |
|
| 54 |
+ if ttl != 20*time.Second {
|
|
| 55 |
+ t.Fatalf("TTL - Expected : %v, Actual : %v", 20*time.Second, ttl)
|
|
| 56 |
+ } |
|
| 57 |
+ |
|
| 58 |
+ clusterOpts = map[string]string{"discovery.heartbeat": "10"}
|
|
| 59 |
+ heartbeat, ttl, err = discoveryOpts(clusterOpts) |
|
| 60 |
+ if err != nil {
|
|
| 61 |
+ t.Fatal(err) |
|
| 62 |
+ } |
|
| 63 |
+ |
|
| 64 |
+ if heartbeat != 10*time.Second {
|
|
| 65 |
+ t.Fatalf("Heartbeat - Expected : %v, Actual : %v", 10*time.Second, heartbeat)
|
|
| 66 |
+ } |
|
| 67 |
+ |
|
| 68 |
+ expected := 10 * defaultDiscoveryTTLFactor * time.Second |
|
| 69 |
+ if ttl != expected {
|
|
| 70 |
+ t.Fatalf("TTL - Expected : %v, Actual : %v", expected, ttl)
|
|
| 71 |
+ } |
|
| 72 |
+ |
|
| 73 |
+ clusterOpts = map[string]string{"discovery.ttl": "30"}
|
|
| 74 |
+ heartbeat, ttl, err = discoveryOpts(clusterOpts) |
|
| 75 |
+ if err != nil {
|
|
| 76 |
+ t.Fatal(err) |
|
| 77 |
+ } |
|
| 78 |
+ |
|
| 79 |
+ if ttl != 30*time.Second {
|
|
| 80 |
+ t.Fatalf("TTL - Expected : %v, Actual : %v", 30*time.Second, ttl)
|
|
| 81 |
+ } |
|
| 82 |
+ |
|
| 83 |
+ expected = 30 * time.Second / defaultDiscoveryTTLFactor |
|
| 84 |
+ if heartbeat != expected {
|
|
| 85 |
+ t.Fatalf("Heartbeat - Expected : %v, Actual : %v", expected, heartbeat)
|
|
| 86 |
+ } |
|
| 87 |
+ |
|
| 88 |
+ clusterOpts = map[string]string{}
|
|
| 89 |
+ heartbeat, ttl, err = discoveryOpts(clusterOpts) |
|
| 90 |
+ if err != nil {
|
|
| 91 |
+ t.Fatal(err) |
|
| 92 |
+ } |
|
| 93 |
+ |
|
| 94 |
+ if heartbeat != defaultDiscoveryHeartbeat {
|
|
| 95 |
+ t.Fatalf("Heartbeat - Expected : %v, Actual : %v", defaultDiscoveryHeartbeat, heartbeat)
|
|
| 96 |
+ } |
|
| 97 |
+ |
|
| 98 |
+ expected = defaultDiscoveryHeartbeat * defaultDiscoveryTTLFactor |
|
| 99 |
+ if ttl != expected {
|
|
| 100 |
+ t.Fatalf("TTL - Expected : %v, Actual : %v", expected, ttl)
|
|
| 101 |
+ } |
|
| 102 |
+} |
| 0 | 103 |
deleted file mode 100644 |
| ... | ... |
@@ -1,164 +0,0 @@ |
| 1 |
-package daemon |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "testing" |
|
| 5 |
- "time" |
|
| 6 |
-) |
|
| 7 |
- |
|
| 8 |
-func TestDiscoveryOpts(t *testing.T) {
|
|
| 9 |
- clusterOpts := map[string]string{"discovery.heartbeat": "10", "discovery.ttl": "5"}
|
|
| 10 |
- heartbeat, ttl, err := discoveryOpts(clusterOpts) |
|
| 11 |
- if err == nil {
|
|
| 12 |
- t.Fatalf("discovery.ttl < discovery.heartbeat must fail")
|
|
| 13 |
- } |
|
| 14 |
- |
|
| 15 |
- clusterOpts = map[string]string{"discovery.heartbeat": "10", "discovery.ttl": "10"}
|
|
| 16 |
- heartbeat, ttl, err = discoveryOpts(clusterOpts) |
|
| 17 |
- if err == nil {
|
|
| 18 |
- t.Fatalf("discovery.ttl == discovery.heartbeat must fail")
|
|
| 19 |
- } |
|
| 20 |
- |
|
| 21 |
- clusterOpts = map[string]string{"discovery.heartbeat": "-10", "discovery.ttl": "10"}
|
|
| 22 |
- heartbeat, ttl, err = discoveryOpts(clusterOpts) |
|
| 23 |
- if err == nil {
|
|
| 24 |
- t.Fatalf("negative discovery.heartbeat must fail")
|
|
| 25 |
- } |
|
| 26 |
- |
|
| 27 |
- clusterOpts = map[string]string{"discovery.heartbeat": "10", "discovery.ttl": "-10"}
|
|
| 28 |
- heartbeat, ttl, err = discoveryOpts(clusterOpts) |
|
| 29 |
- if err == nil {
|
|
| 30 |
- t.Fatalf("negative discovery.ttl must fail")
|
|
| 31 |
- } |
|
| 32 |
- |
|
| 33 |
- clusterOpts = map[string]string{"discovery.heartbeat": "invalid"}
|
|
| 34 |
- heartbeat, ttl, err = discoveryOpts(clusterOpts) |
|
| 35 |
- if err == nil {
|
|
| 36 |
- t.Fatalf("invalid discovery.heartbeat must fail")
|
|
| 37 |
- } |
|
| 38 |
- |
|
| 39 |
- clusterOpts = map[string]string{"discovery.ttl": "invalid"}
|
|
| 40 |
- heartbeat, ttl, err = discoveryOpts(clusterOpts) |
|
| 41 |
- if err == nil {
|
|
| 42 |
- t.Fatalf("invalid discovery.ttl must fail")
|
|
| 43 |
- } |
|
| 44 |
- |
|
| 45 |
- clusterOpts = map[string]string{"discovery.heartbeat": "10", "discovery.ttl": "20"}
|
|
| 46 |
- heartbeat, ttl, err = discoveryOpts(clusterOpts) |
|
| 47 |
- if err != nil {
|
|
| 48 |
- t.Fatal(err) |
|
| 49 |
- } |
|
| 50 |
- |
|
| 51 |
- if heartbeat != 10*time.Second {
|
|
| 52 |
- t.Fatalf("Heartbeat - Expected : %v, Actual : %v", 10*time.Second, heartbeat)
|
|
| 53 |
- } |
|
| 54 |
- |
|
| 55 |
- if ttl != 20*time.Second {
|
|
| 56 |
- t.Fatalf("TTL - Expected : %v, Actual : %v", 20*time.Second, ttl)
|
|
| 57 |
- } |
|
| 58 |
- |
|
| 59 |
- clusterOpts = map[string]string{"discovery.heartbeat": "10"}
|
|
| 60 |
- heartbeat, ttl, err = discoveryOpts(clusterOpts) |
|
| 61 |
- if err != nil {
|
|
| 62 |
- t.Fatal(err) |
|
| 63 |
- } |
|
| 64 |
- |
|
| 65 |
- if heartbeat != 10*time.Second {
|
|
| 66 |
- t.Fatalf("Heartbeat - Expected : %v, Actual : %v", 10*time.Second, heartbeat)
|
|
| 67 |
- } |
|
| 68 |
- |
|
| 69 |
- expected := 10 * defaultDiscoveryTTLFactor * time.Second |
|
| 70 |
- if ttl != expected {
|
|
| 71 |
- t.Fatalf("TTL - Expected : %v, Actual : %v", expected, ttl)
|
|
| 72 |
- } |
|
| 73 |
- |
|
| 74 |
- clusterOpts = map[string]string{"discovery.ttl": "30"}
|
|
| 75 |
- heartbeat, ttl, err = discoveryOpts(clusterOpts) |
|
| 76 |
- if err != nil {
|
|
| 77 |
- t.Fatal(err) |
|
| 78 |
- } |
|
| 79 |
- |
|
| 80 |
- if ttl != 30*time.Second {
|
|
| 81 |
- t.Fatalf("TTL - Expected : %v, Actual : %v", 30*time.Second, ttl)
|
|
| 82 |
- } |
|
| 83 |
- |
|
| 84 |
- expected = 30 * time.Second / defaultDiscoveryTTLFactor |
|
| 85 |
- if heartbeat != expected {
|
|
| 86 |
- t.Fatalf("Heartbeat - Expected : %v, Actual : %v", expected, heartbeat)
|
|
| 87 |
- } |
|
| 88 |
- |
|
| 89 |
- clusterOpts = map[string]string{}
|
|
| 90 |
- heartbeat, ttl, err = discoveryOpts(clusterOpts) |
|
| 91 |
- if err != nil {
|
|
| 92 |
- t.Fatal(err) |
|
| 93 |
- } |
|
| 94 |
- |
|
| 95 |
- if heartbeat != defaultDiscoveryHeartbeat {
|
|
| 96 |
- t.Fatalf("Heartbeat - Expected : %v, Actual : %v", defaultDiscoveryHeartbeat, heartbeat)
|
|
| 97 |
- } |
|
| 98 |
- |
|
| 99 |
- expected = defaultDiscoveryHeartbeat * defaultDiscoveryTTLFactor |
|
| 100 |
- if ttl != expected {
|
|
| 101 |
- t.Fatalf("TTL - Expected : %v, Actual : %v", expected, ttl)
|
|
| 102 |
- } |
|
| 103 |
-} |
|
| 104 |
- |
|
| 105 |
-func TestModifiedDiscoverySettings(t *testing.T) {
|
|
| 106 |
- cases := []struct {
|
|
| 107 |
- current *Config |
|
| 108 |
- modified *Config |
|
| 109 |
- expected bool |
|
| 110 |
- }{
|
|
| 111 |
- {
|
|
| 112 |
- current: discoveryConfig("foo", "bar", map[string]string{}),
|
|
| 113 |
- modified: discoveryConfig("foo", "bar", map[string]string{}),
|
|
| 114 |
- expected: false, |
|
| 115 |
- }, |
|
| 116 |
- {
|
|
| 117 |
- current: discoveryConfig("foo", "bar", map[string]string{"foo": "bar"}),
|
|
| 118 |
- modified: discoveryConfig("foo", "bar", map[string]string{"foo": "bar"}),
|
|
| 119 |
- expected: false, |
|
| 120 |
- }, |
|
| 121 |
- {
|
|
| 122 |
- current: discoveryConfig("foo", "bar", map[string]string{}),
|
|
| 123 |
- modified: discoveryConfig("foo", "bar", nil),
|
|
| 124 |
- expected: false, |
|
| 125 |
- }, |
|
| 126 |
- {
|
|
| 127 |
- current: discoveryConfig("foo", "bar", nil),
|
|
| 128 |
- modified: discoveryConfig("foo", "bar", map[string]string{}),
|
|
| 129 |
- expected: false, |
|
| 130 |
- }, |
|
| 131 |
- {
|
|
| 132 |
- current: discoveryConfig("foo", "bar", nil),
|
|
| 133 |
- modified: discoveryConfig("baz", "bar", nil),
|
|
| 134 |
- expected: true, |
|
| 135 |
- }, |
|
| 136 |
- {
|
|
| 137 |
- current: discoveryConfig("foo", "bar", nil),
|
|
| 138 |
- modified: discoveryConfig("foo", "baz", nil),
|
|
| 139 |
- expected: true, |
|
| 140 |
- }, |
|
| 141 |
- {
|
|
| 142 |
- current: discoveryConfig("foo", "bar", nil),
|
|
| 143 |
- modified: discoveryConfig("foo", "bar", map[string]string{"foo": "bar"}),
|
|
| 144 |
- expected: true, |
|
| 145 |
- }, |
|
| 146 |
- } |
|
| 147 |
- |
|
| 148 |
- for _, c := range cases {
|
|
| 149 |
- got := modifiedDiscoverySettings(c.current, c.modified.ClusterStore, c.modified.ClusterAdvertise, c.modified.ClusterOpts) |
|
| 150 |
- if c.expected != got {
|
|
| 151 |
- t.Fatalf("expected %v, got %v: current config %v, new config %v", c.expected, got, c.current, c.modified)
|
|
| 152 |
- } |
|
| 153 |
- } |
|
| 154 |
-} |
|
| 155 |
- |
|
| 156 |
-func discoveryConfig(backendAddr, advertiseAddr string, opts map[string]string) *Config {
|
|
| 157 |
- return &Config{
|
|
| 158 |
- CommonConfig: CommonConfig{
|
|
| 159 |
- ClusterStore: backendAddr, |
|
| 160 |
- ClusterAdvertise: advertiseAddr, |
|
| 161 |
- ClusterOpts: opts, |
|
| 162 |
- }, |
|
| 163 |
- } |
|
| 164 |
-} |