2018-02-05 16:05:59 -05:00
|
|
|
package syslog // import "github.com/docker/docker/daemon/logger/syslog"
|
2016-02-03 15:59:27 -05:00
|
|
|
|
|
|
|
import (
|
2022-04-09 09:18:43 -04:00
|
|
|
"log"
|
2017-12-27 08:11:21 -05:00
|
|
|
"net"
|
2022-04-09 09:18:43 -04:00
|
|
|
"os"
|
|
|
|
"path/filepath"
|
2016-02-03 15:59:27 -05:00
|
|
|
"reflect"
|
2022-04-09 09:18:43 -04:00
|
|
|
"runtime"
|
|
|
|
"strings"
|
2016-02-03 15:59:27 -05:00
|
|
|
"testing"
|
2016-08-15 16:25:05 -04:00
|
|
|
|
|
|
|
syslog "github.com/RackSec/srslog"
|
2016-02-03 15:59:27 -05:00
|
|
|
)
|
|
|
|
|
|
|
|
func functionMatches(expectedFun interface{}, actualFun interface{}) bool {
|
|
|
|
return reflect.ValueOf(expectedFun).Pointer() == reflect.ValueOf(actualFun).Pointer()
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestParseLogFormat(t *testing.T) {
|
2016-06-29 11:44:00 -04:00
|
|
|
formatter, framer, err := parseLogFormat("rfc5424", "udp")
|
|
|
|
if err != nil || !functionMatches(rfc5424formatterWithAppNameAsTag, formatter) ||
|
|
|
|
!functionMatches(syslog.DefaultFramer, framer) {
|
|
|
|
t.Fatal("Failed to parse rfc5424 format", err, formatter, framer)
|
|
|
|
}
|
|
|
|
|
|
|
|
formatter, framer, err = parseLogFormat("rfc5424", "tcp+tls")
|
2016-02-03 15:59:27 -05:00
|
|
|
if err != nil || !functionMatches(rfc5424formatterWithAppNameAsTag, formatter) ||
|
|
|
|
!functionMatches(syslog.RFC5425MessageLengthFramer, framer) {
|
|
|
|
t.Fatal("Failed to parse rfc5424 format", err, formatter, framer)
|
|
|
|
}
|
|
|
|
|
2016-06-29 11:44:00 -04:00
|
|
|
formatter, framer, err = parseLogFormat("rfc5424micro", "udp")
|
|
|
|
if err != nil || !functionMatches(rfc5424microformatterWithAppNameAsTag, formatter) ||
|
|
|
|
!functionMatches(syslog.DefaultFramer, framer) {
|
|
|
|
t.Fatal("Failed to parse rfc5424 (microsecond) format", err, formatter, framer)
|
|
|
|
}
|
|
|
|
|
|
|
|
formatter, framer, err = parseLogFormat("rfc5424micro", "tcp+tls")
|
2016-04-07 02:03:28 -04:00
|
|
|
if err != nil || !functionMatches(rfc5424microformatterWithAppNameAsTag, formatter) ||
|
|
|
|
!functionMatches(syslog.RFC5425MessageLengthFramer, framer) {
|
|
|
|
t.Fatal("Failed to parse rfc5424 (microsecond) format", err, formatter, framer)
|
|
|
|
}
|
|
|
|
|
2016-06-29 11:44:00 -04:00
|
|
|
formatter, framer, err = parseLogFormat("rfc3164", "")
|
2016-02-03 15:59:27 -05:00
|
|
|
if err != nil || !functionMatches(syslog.RFC3164Formatter, formatter) ||
|
|
|
|
!functionMatches(syslog.DefaultFramer, framer) {
|
|
|
|
t.Fatal("Failed to parse rfc3164 format", err, formatter, framer)
|
|
|
|
}
|
|
|
|
|
2016-06-29 11:44:00 -04:00
|
|
|
formatter, framer, err = parseLogFormat("", "")
|
2016-02-03 15:59:27 -05:00
|
|
|
if err != nil || !functionMatches(syslog.UnixFormatter, formatter) ||
|
|
|
|
!functionMatches(syslog.DefaultFramer, framer) {
|
|
|
|
t.Fatal("Failed to parse empty format", err, formatter, framer)
|
|
|
|
}
|
|
|
|
|
2016-06-29 11:44:00 -04:00
|
|
|
formatter, framer, err = parseLogFormat("invalid", "")
|
2016-02-03 15:59:27 -05:00
|
|
|
if err == nil {
|
|
|
|
t.Fatal("Failed to parse invalid format", err, formatter, framer)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestValidateLogOptEmpty(t *testing.T) {
|
|
|
|
emptyConfig := make(map[string]string)
|
|
|
|
if err := ValidateLogOpt(emptyConfig); err != nil {
|
|
|
|
t.Fatal("Failed to parse empty config", err)
|
|
|
|
}
|
|
|
|
}
|
2017-12-27 08:11:21 -05:00
|
|
|
|
|
|
|
func TestValidateSyslogAddress(t *testing.T) {
|
2022-04-09 09:18:43 -04:00
|
|
|
const sockPlaceholder = "/TEMPDIR/socket.sock"
|
|
|
|
s, err := os.Create(filepath.Join(t.TempDir(), "socket.sock"))
|
2017-12-27 08:11:21 -05:00
|
|
|
if err != nil {
|
2022-04-09 09:18:43 -04:00
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
socketPath := s.Name()
|
|
|
|
_ = s.Close()
|
|
|
|
|
|
|
|
tests := []struct {
|
|
|
|
address string
|
|
|
|
expectedErr string
|
|
|
|
skipOn string
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
address: "this is not an uri",
|
|
|
|
expectedErr: "unsupported scheme: ''",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
address: "corrupted:42",
|
|
|
|
expectedErr: "unsupported scheme: 'corrupted'",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
address: "unix://" + sockPlaceholder,
|
|
|
|
skipOn: "windows", // doesn't work with unix:// sockets
|
|
|
|
},
|
|
|
|
{
|
|
|
|
address: "unix:///does_not_exist",
|
|
|
|
expectedErr: "no such file or directory",
|
|
|
|
skipOn: "windows", // error message differs
|
|
|
|
},
|
|
|
|
{
|
|
|
|
address: "tcp://1.2.3.4",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
address: "udp://1.2.3.4",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
address: "http://1.2.3.4",
|
|
|
|
expectedErr: "unsupported scheme: 'http'",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tc := range tests {
|
|
|
|
tc := tc
|
|
|
|
if tc.skipOn == runtime.GOOS {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
t.Run(tc.address, func(t *testing.T) {
|
|
|
|
address := strings.Replace(tc.address, sockPlaceholder, socketPath, 1)
|
|
|
|
err := ValidateLogOpt(map[string]string{"syslog-address": address})
|
|
|
|
if tc.expectedErr != "" {
|
|
|
|
if err == nil {
|
|
|
|
t.Fatal("expected an error, got nil")
|
|
|
|
}
|
|
|
|
if !strings.Contains(err.Error(), tc.expectedErr) {
|
|
|
|
t.Fatalf("expected error to contain '%s', got: '%s'", tc.expectedErr, err)
|
|
|
|
}
|
|
|
|
} else if err != nil {
|
|
|
|
t.Fatalf("unexpected error: '%s'", err)
|
|
|
|
}
|
|
|
|
})
|
2017-12-27 08:11:21 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestParseAddressDefaultPort(t *testing.T) {
|
|
|
|
_, address, err := parseAddress("tcp://1.2.3.4")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
_, port, _ := net.SplitHostPort(address)
|
2022-04-09 09:18:43 -04:00
|
|
|
if port != defaultPort {
|
|
|
|
t.Fatalf("Expected to default to port %s. It used port %s", defaultPort, port)
|
2017-12-27 08:11:21 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestValidateSyslogFacility(t *testing.T) {
|
|
|
|
err := ValidateLogOpt(map[string]string{
|
|
|
|
"syslog-facility": "Invalid facility",
|
|
|
|
})
|
|
|
|
if err == nil {
|
|
|
|
t.Fatal("Expected error if facility level is invalid")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestValidateLogOptSyslogFormat(t *testing.T) {
|
|
|
|
err := ValidateLogOpt(map[string]string{
|
|
|
|
"syslog-format": "Invalid format",
|
|
|
|
})
|
|
|
|
if err == nil {
|
|
|
|
t.Fatal("Expected error if format is invalid")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestValidateLogOpt(t *testing.T) {
|
|
|
|
err := ValidateLogOpt(map[string]string{
|
|
|
|
"env": "http://127.0.0.1",
|
|
|
|
"env-regex": "abc",
|
|
|
|
"labels": "labelA",
|
2019-01-16 16:52:22 -05:00
|
|
|
"labels-regex": "def",
|
2017-12-27 08:11:21 -05:00
|
|
|
"syslog-address": "udp://1.2.3.4:1111",
|
|
|
|
"syslog-facility": "daemon",
|
|
|
|
"syslog-tls-ca-cert": "/etc/ca-certificates/custom/ca.pem",
|
|
|
|
"syslog-tls-cert": "/etc/ca-certificates/custom/cert.pem",
|
|
|
|
"syslog-tls-key": "/etc/ca-certificates/custom/key.pem",
|
|
|
|
"syslog-tls-skip-verify": "true",
|
|
|
|
"tag": "true",
|
|
|
|
"syslog-format": "rfc3164",
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
err = ValidateLogOpt(map[string]string{
|
|
|
|
"not-supported-option": "a",
|
|
|
|
})
|
|
|
|
if err == nil {
|
|
|
|
t.Fatal("Expecting error on unsupported options")
|
|
|
|
}
|
|
|
|
}
|