Browse code

inherit the daemon log options when creating containers

Signed-off-by: Shijiang Wei <mountkin@gmail.com>

Shijiang Wei authored on 2016/03/12 21:50:37
Showing 6 changed files
... ...
@@ -69,6 +69,10 @@ func (daemon *Daemon) create(params types.ContainerCreateConfig) (retC *containe
69 69
 		return nil, err
70 70
 	}
71 71
 
72
+	if err := daemon.mergeAndVerifyLogConfig(&params.HostConfig.LogConfig); err != nil {
73
+		return nil, err
74
+	}
75
+
72 76
 	if container, err = daemon.newContainer(params.Name, params.Config, imgID); err != nil {
73 77
 		return nil, err
74 78
 	}
... ...
@@ -35,7 +35,6 @@ import (
35 35
 	"github.com/docker/engine-api/types/strslice"
36 36
 	// register graph drivers
37 37
 	_ "github.com/docker/docker/daemon/graphdriver/register"
38
-	"github.com/docker/docker/daemon/logger"
39 38
 	"github.com/docker/docker/daemon/network"
40 39
 	dmetadata "github.com/docker/docker/distribution/metadata"
41 40
 	"github.com/docker/docker/distribution/xfer"
... ...
@@ -669,12 +668,6 @@ func NewDaemon(config *Config, registryService *registry.Service, containerdRemo
669 669
 		return nil, fmt.Errorf("error setting default isolation mode: %v", err)
670 670
 	}
671 671
 
672
-	// Verify logging driver type
673
-	if config.LogConfig.Type != "none" {
674
-		if _, err := logger.GetLogDriver(config.LogConfig.Type); err != nil {
675
-			return nil, fmt.Errorf("error finding the logging driver: %v", err)
676
-		}
677
-	}
678 672
 	logrus.Debugf("Using default logging driver %s", config.LogConfig.Type)
679 673
 
680 674
 	if err := configureMaxThreads(config); err != nil {
... ...
@@ -1351,11 +1344,6 @@ func (daemon *Daemon) verifyContainerSettings(hostConfig *containertypes.HostCon
1351 1351
 		return nil, nil
1352 1352
 	}
1353 1353
 
1354
-	logCfg := daemon.getLogConfig(hostConfig.LogConfig)
1355
-	if err := logger.ValidateLogOpts(logCfg.Type, logCfg.Config); err != nil {
1356
-		return nil, err
1357
-	}
1358
-
1359 1354
 	for port := range hostConfig.PortBindings {
1360 1355
 		_, portStr := nat.SplitProtoPort(string(port))
1361 1356
 		if _, err := nat.ParsePort(portStr); err != nil {
... ...
@@ -19,16 +19,23 @@ type logdriverFactory struct {
19 19
 }
20 20
 
21 21
 func (lf *logdriverFactory) register(name string, c Creator) error {
22
-	lf.m.Lock()
23
-	defer lf.m.Unlock()
24
-
25
-	if _, ok := lf.registry[name]; ok {
22
+	if lf.driverRegistered(name) {
26 23
 		return fmt.Errorf("logger: log driver named '%s' is already registered", name)
27 24
 	}
25
+
26
+	lf.m.Lock()
28 27
 	lf.registry[name] = c
28
+	lf.m.Unlock()
29 29
 	return nil
30 30
 }
31 31
 
32
+func (lf *logdriverFactory) driverRegistered(name string) bool {
33
+	lf.m.Lock()
34
+	_, ok := lf.registry[name]
35
+	lf.m.Unlock()
36
+	return ok
37
+}
38
+
32 39
 func (lf *logdriverFactory) registerLogOptValidator(name string, l LogOptValidator) error {
33 40
 	lf.m.Lock()
34 41
 	defer lf.m.Unlock()
... ...
@@ -81,9 +88,17 @@ func GetLogDriver(name string) (Creator, error) {
81 81
 // ValidateLogOpts checks the options for the given log driver. The
82 82
 // options supported are specific to the LogDriver implementation.
83 83
 func ValidateLogOpts(name string, cfg map[string]string) error {
84
-	l := factory.getLogOptValidator(name)
85
-	if l != nil {
86
-		return l(cfg)
84
+	if name == "none" {
85
+		return nil
86
+	}
87
+
88
+	if !factory.driverRegistered(name) {
89
+		return fmt.Errorf("logger: no log driver named '%s' is registered", name)
90
+	}
91
+
92
+	validator := factory.getLogOptValidator(name)
93
+	if validator != nil {
94
+		return validator(cfg)
87 95
 	}
88 96
 	return nil
89 97
 }
... ...
@@ -107,24 +107,16 @@ func (daemon *Daemon) getLogger(container *container.Container) (logger.Logger,
107 107
 	if container.LogDriver != nil && container.IsRunning() {
108 108
 		return container.LogDriver, nil
109 109
 	}
110
-	cfg := daemon.getLogConfig(container.HostConfig.LogConfig)
111
-	if err := logger.ValidateLogOpts(cfg.Type, cfg.Config); err != nil {
112
-		return nil, err
113
-	}
114
-	return container.StartLogger(cfg)
110
+	return container.StartLogger(container.HostConfig.LogConfig)
115 111
 }
116 112
 
117 113
 // StartLogging initializes and starts the container logging stream.
118 114
 func (daemon *Daemon) StartLogging(container *container.Container) error {
119
-	cfg := daemon.getLogConfig(container.HostConfig.LogConfig)
120
-	if cfg.Type == "none" {
115
+	if container.HostConfig.LogConfig.Type == "none" {
121 116
 		return nil // do not start logging routines
122 117
 	}
123 118
 
124
-	if err := logger.ValidateLogOpts(cfg.Type, cfg.Config); err != nil {
125
-		return err
126
-	}
127
-	l, err := container.StartLogger(cfg)
119
+	l, err := container.StartLogger(container.HostConfig.LogConfig)
128 120
 	if err != nil {
129 121
 		return fmt.Errorf("Failed to initialize logging driver: %v", err)
130 122
 	}
... ...
@@ -142,15 +134,19 @@ func (daemon *Daemon) StartLogging(container *container.Container) error {
142 142
 	return nil
143 143
 }
144 144
 
145
-// getLogConfig returns the log configuration for the container.
146
-func (daemon *Daemon) getLogConfig(cfg containertypes.LogConfig) containertypes.LogConfig {
147
-	if cfg.Type != "" || len(cfg.Config) > 0 { // container has log driver configured
148
-		if cfg.Type == "" {
149
-			cfg.Type = jsonfilelog.Name
145
+// mergeLogConfig merges the daemon log config to the container's log config if the container's log driver is not specified.
146
+func (daemon *Daemon) mergeAndVerifyLogConfig(cfg *containertypes.LogConfig) error {
147
+	if cfg.Type == "" {
148
+		cfg.Type = daemon.defaultLogConfig.Type
149
+	}
150
+
151
+	if cfg.Type == daemon.defaultLogConfig.Type {
152
+		for k, v := range daemon.defaultLogConfig.Config {
153
+			if _, ok := cfg.Config[k]; !ok {
154
+				cfg.Config[k] = v
155
+			}
150 156
 		}
151
-		return cfg
152 157
 	}
153 158
 
154
-	// Use daemon's default log config for containers
155
-	return daemon.defaultLogConfig
159
+	return logger.ValidateLogOpts(cfg.Type, cfg.Config)
156 160
 }
... ...
@@ -41,6 +41,9 @@ func (daemon *Daemon) ContainerStart(name string, hostConfig *containertypes.Hos
41 41
 			if err := daemon.setSecurityOptions(container, hostConfig); err != nil {
42 42
 				return err
43 43
 			}
44
+			if err := daemon.mergeAndVerifyLogConfig(&hostConfig.LogConfig); err != nil {
45
+				return err
46
+			}
44 47
 			if err := daemon.setHostConfig(container, hostConfig); err != nil {
45 48
 				return err
46 49
 			}
... ...
@@ -1748,17 +1748,21 @@ func (s *DockerDaemonSuite) TestDaemonRestartWithContainerWithRestartPolicyAlway
1748 1748
 }
1749 1749
 
1750 1750
 func (s *DockerDaemonSuite) TestDaemonWideLogConfig(c *check.C) {
1751
-	if err := s.d.StartWithBusybox("--log-driver=json-file", "--log-opt=max-size=1k"); err != nil {
1751
+	if err := s.d.StartWithBusybox("--log-opt=max-size=1k"); err != nil {
1752 1752
 		c.Fatal(err)
1753 1753
 	}
1754
-	out, err := s.d.Cmd("run", "-d", "--name=logtest", "busybox", "top")
1754
+	name := "logtest"
1755
+	out, err := s.d.Cmd("run", "-d", "--log-opt=max-file=5", "--name", name, "busybox", "top")
1755 1756
 	c.Assert(err, check.IsNil, check.Commentf("Output: %s, err: %v", out, err))
1756
-	out, err = s.d.Cmd("inspect", "-f", "{{ .HostConfig.LogConfig.Config }}", "logtest")
1757
+
1758
+	out, err = s.d.Cmd("inspect", "-f", "{{ .HostConfig.LogConfig.Config }}", name)
1757 1759
 	c.Assert(err, check.IsNil, check.Commentf("Output: %s", out))
1758
-	cfg := strings.TrimSpace(out)
1759
-	if cfg != "map[max-size:1k]" {
1760
-		c.Fatalf("Unexpected log-opt: %s, expected map[max-size:1k]", cfg)
1761
-	}
1760
+	c.Assert(out, checker.Contains, "max-size:1k")
1761
+	c.Assert(out, checker.Contains, "max-file:5")
1762
+
1763
+	out, err = s.d.Cmd("inspect", "-f", "{{ .HostConfig.LogConfig.Type }}", name)
1764
+	c.Assert(err, check.IsNil, check.Commentf("Output: %s", out))
1765
+	c.Assert(strings.TrimSpace(out), checker.Equals, "json-file")
1762 1766
 }
1763 1767
 
1764 1768
 func (s *DockerDaemonSuite) TestDaemonRestartWithPausedContainer(c *check.C) {