Signed-off-by: Shijiang Wei <mountkin@gmail.com>
| ... | ... |
@@ -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(¶ms.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) {
|