plugins/inputs/dovecot: Add support for unix domain sockets (#9223)

It's safer for dovecot to export metrics via a UDS instead of tcp port,
this will add support for that option.

### Required for all PRs:

<!-- Complete the tasks in the following list. Change [ ] to [x] to
show completion. -->

- [x] Updated associated README.md.
- [x] Wrote appropriate unit tests.

resolves #9215 

dovecot: Add support for unix domain sockets as well
This commit is contained in:
Josef Johansson 2021-05-04 23:09:55 +02:00 committed by GitHub
parent 175cd16f19
commit 537bc9d21d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 66 additions and 7 deletions

View File

@ -14,6 +14,9 @@ the [upgrading steps][upgrading].
## specify dovecot servers via an address:port list
## e.g.
## localhost:24242
## or as an UDS socket
## e.g.
## /var/run/dovecot/old-stats
##
## If no servers are specified, then localhost is used as the host.
servers = ["localhost:24242"]

View File

@ -78,12 +78,20 @@ func (d *Dovecot) Gather(acc telegraf.Accumulator) error {
}
func (d *Dovecot) gatherServer(addr string, acc telegraf.Accumulator, qtype string, filter string) error {
_, _, err := net.SplitHostPort(addr)
if err != nil {
return fmt.Errorf("%q on url %s", err.Error(), addr)
var proto string
if strings.HasPrefix(addr, "/") {
proto = "unix"
} else {
proto = "tcp"
_, _, err := net.SplitHostPort(addr)
if err != nil {
return fmt.Errorf("%q on url %s", err.Error(), addr)
}
}
c, err := net.DialTimeout("tcp", addr, defaultTimeout)
c, err := net.DialTimeout(proto, addr, defaultTimeout)
if err != nil {
return fmt.Errorf("enable to connect to dovecot server '%s': %s", addr, err)
}
@ -108,7 +116,12 @@ func (d *Dovecot) gatherServer(addr string, acc telegraf.Accumulator, qtype stri
return fmt.Errorf("copying message failed for dovecot server '%s': %s", addr, err)
}
host, _, _ := net.SplitHostPort(addr)
var host string
if strings.HasPrefix(addr, "/") {
host = addr
} else {
host, _, _ = net.SplitHostPort(addr)
}
return gatherStats(&buf, acc, host, qtype)
}

View File

@ -1,7 +1,12 @@
package dovecot
import (
"bufio"
"bytes"
"io"
"net"
"net/textproto"
"os"
"testing"
"time"
@ -42,11 +47,49 @@ func TestDovecotIntegration(t *testing.T) {
var acc testutil.Accumulator
// Test type=global server=unix
addr := "/tmp/socket"
wait := make(chan int)
go func() {
defer close(wait)
la, err := net.ResolveUnixAddr("unix", addr)
require.NoError(t, err)
l, err := net.ListenUnix("unix", la)
require.NoError(t, err)
defer l.Close()
defer os.Remove(addr)
wait <- 0
conn, err := l.Accept()
require.NoError(t, err)
defer conn.Close()
readertp := textproto.NewReader(bufio.NewReader(conn))
_, err = readertp.ReadLine()
require.NoError(t, err)
buf := bytes.NewBufferString(sampleGlobal)
_, err = io.Copy(conn, buf)
require.NoError(t, err)
}()
// Wait for server to start
<-wait
d := &Dovecot{Servers: []string{addr}, Type: "global"}
err := d.Gather(&acc)
require.NoError(t, err)
tags := map[string]string{"server": addr, "type": "global"}
acc.AssertContainsTaggedFields(t, "dovecot", fields, tags)
// Test type=global
tags := map[string]string{"server": "dovecot.test", "type": "global"}
tags = map[string]string{"server": "dovecot.test", "type": "global"}
buf := bytes.NewBufferString(sampleGlobal)
err := gatherStats(buf, &acc, "dovecot.test", "global")
err = gatherStats(buf, &acc, "dovecot.test", "global")
require.NoError(t, err)
acc.AssertContainsTaggedFields(t, "dovecot", fields, tags)