If an invalid logger address is provided on daemon start it will
silently fail. As syslog driver is doing, this check should be done on
daemon start and prevent it from starting even in other drivers.
This patch also adds integration tests for this behavior.
Signed-off-by: Antonio Murdaca <runcom@linux.com>
... | ... |
@@ -38,44 +38,20 @@ func init() { |
38 | 38 |
} |
39 | 39 |
} |
40 | 40 |
|
41 |
-func parseConfig(ctx logger.Context) (string, int, string, error) { |
|
42 |
- host := defaultHostName |
|
43 |
- port := defaultPort |
|
44 |
- |
|
45 |
- config := ctx.Config |
|
46 |
- |
|
47 |
- tag, err := loggerutils.ParseLogTag(ctx, "docker.{{.ID}}") |
|
48 |
- if err != nil { |
|
49 |
- return "", 0, "", err |
|
50 |
- } |
|
51 |
- |
|
52 |
- if address := config["fluentd-address"]; address != "" { |
|
53 |
- if h, p, err := net.SplitHostPort(address); err != nil { |
|
54 |
- if !strings.Contains(err.Error(), "missing port in address") { |
|
55 |
- return "", 0, "", err |
|
56 |
- } |
|
57 |
- host = h |
|
58 |
- } else { |
|
59 |
- portnum, err := strconv.Atoi(p) |
|
60 |
- if err != nil { |
|
61 |
- return "", 0, "", err |
|
62 |
- } |
|
63 |
- host = h |
|
64 |
- port = portnum |
|
65 |
- } |
|
66 |
- } |
|
67 |
- |
|
68 |
- return host, port, tag, nil |
|
69 |
-} |
|
70 |
- |
|
71 | 41 |
// New creates a fluentd logger using the configuration passed in on |
72 | 42 |
// the context. Supported context configuration variables are |
73 | 43 |
// fluentd-address & fluentd-tag. |
74 | 44 |
func New(ctx logger.Context) (logger.Logger, error) { |
75 |
- host, port, tag, err := parseConfig(ctx) |
|
45 |
+ host, port, err := parseAddress(ctx.Config["fluentd-address"]) |
|
46 |
+ if err != nil { |
|
47 |
+ return nil, err |
|
48 |
+ } |
|
49 |
+ |
|
50 |
+ tag, err := loggerutils.ParseLogTag(ctx, "docker.{{.ID}}") |
|
76 | 51 |
if err != nil { |
77 | 52 |
return nil, err |
78 | 53 |
} |
54 |
+ |
|
79 | 55 |
logrus.Debugf("logging driver fluentd configured for container:%s, host:%s, port:%d, tag:%s.", ctx.ContainerID, host, port, tag) |
80 | 56 |
|
81 | 57 |
// logger tries to recoonect 2**32 - 1 times |
... | ... |
@@ -104,6 +80,14 @@ func (f *fluentd) Log(msg *logger.Message) error { |
104 | 104 |
return f.writer.PostWithTime(f.tag, msg.Timestamp, data) |
105 | 105 |
} |
106 | 106 |
|
107 |
+func (f *fluentd) Close() error { |
|
108 |
+ return f.writer.Close() |
|
109 |
+} |
|
110 |
+ |
|
111 |
+func (f *fluentd) Name() string { |
|
112 |
+ return name |
|
113 |
+} |
|
114 |
+ |
|
107 | 115 |
// ValidateLogOpt looks for fluentd specific log options fluentd-address & fluentd-tag. |
108 | 116 |
func ValidateLogOpt(cfg map[string]string) error { |
109 | 117 |
for key := range cfg { |
... | ... |
@@ -115,13 +99,30 @@ func ValidateLogOpt(cfg map[string]string) error { |
115 | 115 |
return fmt.Errorf("unknown log opt '%s' for fluentd log driver", key) |
116 | 116 |
} |
117 | 117 |
} |
118 |
+ |
|
119 |
+ if _, _, err := parseAddress(cfg["fluentd-address"]); err != nil { |
|
120 |
+ return err |
|
121 |
+ } |
|
122 |
+ |
|
118 | 123 |
return nil |
119 | 124 |
} |
120 | 125 |
|
121 |
-func (f *fluentd) Close() error { |
|
122 |
- return f.writer.Close() |
|
123 |
-} |
|
126 |
+func parseAddress(address string) (string, int, error) { |
|
127 |
+ if address == "" { |
|
128 |
+ return defaultHostName, defaultPort, nil |
|
129 |
+ } |
|
124 | 130 |
|
125 |
-func (f *fluentd) Name() string { |
|
126 |
- return name |
|
131 |
+ host, port, err := net.SplitHostPort(address) |
|
132 |
+ if err != nil { |
|
133 |
+ if !strings.Contains(err.Error(), "missing port in address") { |
|
134 |
+ return "", 0, fmt.Errorf("invalid fluentd-address %s: %s", address, err) |
|
135 |
+ } |
|
136 |
+ return host, defaultPort, nil |
|
137 |
+ } |
|
138 |
+ |
|
139 |
+ portnum, err := strconv.Atoi(port) |
|
140 |
+ if err != nil { |
|
141 |
+ return "", 0, fmt.Errorf("invalid fluentd-address %s: %s", address, err) |
|
142 |
+ } |
|
143 |
+ return host, portnum, nil |
|
127 | 144 |
} |
... | ... |
@@ -147,28 +147,35 @@ func ValidateLogOpt(cfg map[string]string) error { |
147 | 147 |
return fmt.Errorf("unknown log opt '%s' for gelf log driver", key) |
148 | 148 |
} |
149 | 149 |
} |
150 |
+ |
|
151 |
+ if _, err := parseAddress(cfg["gelf-address"]); err != nil { |
|
152 |
+ return err |
|
153 |
+ } |
|
154 |
+ |
|
150 | 155 |
return nil |
151 | 156 |
} |
152 | 157 |
|
153 | 158 |
func parseAddress(address string) (string, error) { |
154 |
- if urlutil.IsTransportURL(address) { |
|
155 |
- url, err := url.Parse(address) |
|
156 |
- if err != nil { |
|
157 |
- return "", err |
|
158 |
- } |
|
159 |
- |
|
160 |
- // we support only udp |
|
161 |
- if url.Scheme != "udp" { |
|
162 |
- return "", fmt.Errorf("gelf: endpoint needs to be UDP") |
|
163 |
- } |
|
159 |
+ if address == "" { |
|
160 |
+ return "", nil |
|
161 |
+ } |
|
162 |
+ if !urlutil.IsTransportURL(address) { |
|
163 |
+ return "", fmt.Errorf("gelf-address should be in form proto://address, got %v", address) |
|
164 |
+ } |
|
165 |
+ url, err := url.Parse(address) |
|
166 |
+ if err != nil { |
|
167 |
+ return "", err |
|
168 |
+ } |
|
164 | 169 |
|
165 |
- // get host and port |
|
166 |
- if _, _, err = net.SplitHostPort(url.Host); err != nil { |
|
167 |
- return "", fmt.Errorf("gelf: please provide gelf-address as udp://host:port") |
|
168 |
- } |
|
170 |
+ // we support only udp |
|
171 |
+ if url.Scheme != "udp" { |
|
172 |
+ return "", fmt.Errorf("gelf: endpoint needs to be UDP") |
|
173 |
+ } |
|
169 | 174 |
|
170 |
- return url.Host, nil |
|
175 |
+ // get host and port |
|
176 |
+ if _, _, err = net.SplitHostPort(url.Host); err != nil { |
|
177 |
+ return "", fmt.Errorf("gelf: please provide gelf-address as udp://host:port") |
|
171 | 178 |
} |
172 | 179 |
|
173 |
- return "", nil |
|
180 |
+ return url.Host, nil |
|
174 | 181 |
} |
... | ... |
@@ -1609,14 +1609,6 @@ func (s *DockerDaemonSuite) TestDaemonRestartWithContainerWithRestartPolicyAlway |
1609 | 1609 |
c.Assert(strings.TrimSpace(out), check.Equals, id[:12]) |
1610 | 1610 |
} |
1611 | 1611 |
|
1612 |
-func (s *DockerDaemonSuite) TestDaemonCorruptedSyslogAddress(c *check.C) { |
|
1613 |
- c.Assert(s.d.Start("--log-driver=syslog", "--log-opt", "syslog-address=corrupted:1234"), check.NotNil) |
|
1614 |
- runCmd := exec.Command("grep", "Failed to set log opts: syslog-address should be in form proto://address", s.d.LogfileName()) |
|
1615 |
- if out, _, err := runCommandWithOutput(runCmd); err != nil { |
|
1616 |
- c.Fatalf("Expected 'Error starting daemon' message; but doesn't exist in log: %q, err: %v", out, err) |
|
1617 |
- } |
|
1618 |
-} |
|
1619 |
- |
|
1620 | 1612 |
func (s *DockerDaemonSuite) TestDaemonWideLogConfig(c *check.C) { |
1621 | 1613 |
c.Assert(s.d.Start("--log-driver=json-file", "--log-opt=max-size=1k"), check.IsNil) |
1622 | 1614 |
out, err := s.d.Cmd("run", "-d", "--name=logtest", "busybox", "top") |
... | ... |
@@ -1689,3 +1681,27 @@ func (s *DockerDaemonSuite) TestDaemonRestartLocalVolumes(c *check.C) { |
1689 | 1689 |
_, err = s.d.Cmd("volume", "inspect", "test") |
1690 | 1690 |
c.Assert(err, check.IsNil) |
1691 | 1691 |
} |
1692 |
+ |
|
1693 |
+func (s *DockerDaemonSuite) TestDaemonCorruptedLogDriverAddress(c *check.C) { |
|
1694 |
+ for _, driver := range []string{ |
|
1695 |
+ "syslog", |
|
1696 |
+ "gelf", |
|
1697 |
+ } { |
|
1698 |
+ args := []string{"--log-driver=" + driver, "--log-opt", driver + "-address=corrupted:42"} |
|
1699 |
+ c.Assert(s.d.Start(args...), check.NotNil, check.Commentf(fmt.Sprintf("Expected daemon not to start with invalid %s-address provided", driver))) |
|
1700 |
+ expected := fmt.Sprintf("Failed to set log opts: %s-address should be in form proto://address", driver) |
|
1701 |
+ runCmd := exec.Command("grep", expected, s.d.LogfileName()) |
|
1702 |
+ if out, _, err := runCommandWithOutput(runCmd); err != nil { |
|
1703 |
+ c.Fatalf("Expected %q message; but doesn't exist in log: %q, err: %v", expected, out, err) |
|
1704 |
+ } |
|
1705 |
+ } |
|
1706 |
+} |
|
1707 |
+ |
|
1708 |
+func (s *DockerDaemonSuite) TestDaemonCorruptedFluentdAddress(c *check.C) { |
|
1709 |
+ c.Assert(s.d.Start("--log-driver=fluentd", "--log-opt", "fluentd-address=corrupted:c"), check.NotNil) |
|
1710 |
+ expected := "Failed to set log opts: invalid fluentd-address corrupted:c: " |
|
1711 |
+ runCmd := exec.Command("grep", expected, s.d.LogfileName()) |
|
1712 |
+ if out, _, err := runCommandWithOutput(runCmd); err != nil { |
|
1713 |
+ c.Fatalf("Expected %q message; but doesn't exist in log: %q, err: %v", expected, out, err) |
|
1714 |
+ } |
|
1715 |
+} |