Skip to content

Commit 2b8643e

Browse files
committed
Support Windows
The syslog logrus hook does not support Windows: https://github.com/sirupsen/logrus/blob/master/hooks/syslog/syslog.go So we have to work around that. While at it, ensure logger initialization errors are really bubbling up, and prevent healthcheck tests from depending on our logger implementation.
1 parent fe136d3 commit 2b8643e

File tree

7 files changed

+152
-82
lines changed

7 files changed

+152
-82
lines changed

.goreleaser.yml

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ builds:
66
goos:
77
- darwin
88
- linux
9+
- windows
910
goarch:
1011
- amd64
1112
- arm

cmd/execute.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,10 @@ var (
3535
)
3636

3737
func runE(cmd *cobra.Command, args []string) (err error) {
38-
logger := log.New(logLevel, logServer, logOutput)
38+
logger, err := log.New(logLevel, logServer, logOutput)
39+
if err != nil {
40+
return fmt.Errorf("failed to create a logger: %v", err)
41+
}
3942

4043
if restcfg == nil {
4144
restcfg, err = client.New(apiServer, kubeConf)

pkg/health/health_test.go

+8-7
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,16 @@ import (
44
"net/http"
55
"net/http/httptest"
66
"testing"
7+
)
78

8-
"github.com/sirupsen/logrus"
9-
"github.com/sirupsen/logrus/hooks/test"
9+
type mockLog struct {
10+
count int
11+
}
1012

11-
"github.com/bpineau/katafygio/pkg/log"
12-
)
13+
func (m *mockLog) Infof(format string, args ...interface{}) {}
14+
func (m *mockLog) Errorf(format string, args ...interface{}) { m.count++ }
1315

14-
var logs = log.New("error", "", "test")
16+
var logs = new(mockLog)
1517

1618
func TestNoopHealth(t *testing.T) {
1719

@@ -23,8 +25,7 @@ func TestNoopHealth(t *testing.T) {
2325
hc = New(logs, -42)
2426
_ = hc.Start()
2527
hc.Stop()
26-
hook := logs.Hooks[logrus.InfoLevel][0].(*test.Hook)
27-
if len(hook.Entries) != 1 {
28+
if logs.count != 1 {
2829
t.Error("Failed to log an issue with a bogus port")
2930
}
3031
}

pkg/log/log.go

+20-41
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,33 @@
22
package log
33

44
import (
5-
"io"
6-
"io/ioutil"
7-
"os"
8-
9-
"log/syslog"
5+
"fmt"
106

117
"github.com/sirupsen/logrus"
12-
ls "github.com/sirupsen/logrus/hooks/syslog"
13-
"github.com/sirupsen/logrus/hooks/test"
8+
)
9+
10+
const (
11+
outputStdout = "stdout"
12+
outputStderr = "stderr"
13+
outputTest = "test"
14+
outputSyslog = "syslog"
1415
)
1516

1617
// New initialize logrus and return a new logger.
17-
func New(logLevel string, logServer string, logOutput string) *logrus.Logger {
18+
func New(logLevel string, logServer string, logOutput string) (*logrus.Logger, error) {
19+
if logLevel == "" {
20+
logLevel = "info"
21+
}
22+
1823
level, err := logrus.ParseLevel(logLevel)
1924
if err != nil {
20-
level = logrus.InfoLevel
25+
return nil, err
2126
}
2227

23-
output, hook := getOutput(logServer, logOutput)
28+
output, hook, err := getOutput(logServer, logOutput)
29+
if err != nil {
30+
return nil, fmt.Errorf("failed to init logger: %v", err)
31+
}
2432

2533
formatter := &logrus.TextFormatter{
2634
FullTimestamp: true,
@@ -34,38 +42,9 @@ func New(logLevel string, logServer string, logOutput string) *logrus.Logger {
3442
Level: level,
3543
}
3644

37-
if logOutput == "syslog" || logOutput == "test" {
45+
if logOutput == outputSyslog || logOutput == outputTest {
3846
log.Hooks.Add(hook)
3947
}
4048

41-
return log
42-
}
43-
44-
func getOutput(logServer string, logOutput string) (io.Writer, logrus.Hook) {
45-
var output io.Writer
46-
var hook logrus.Hook
47-
var err error
48-
49-
switch logOutput {
50-
case "stdout":
51-
output = os.Stdout
52-
case "stderr":
53-
output = os.Stderr
54-
case "test":
55-
output = ioutil.Discard
56-
_, hook = test.NewNullLogger()
57-
case "syslog":
58-
output = os.Stderr // does not matter ?
59-
if logServer == "" {
60-
panic("syslog output needs a log server (ie. 127.0.0.1:514)")
61-
}
62-
hook, err = ls.NewSyslogHook("udp", logServer, syslog.LOG_INFO, "katafygio")
63-
if err != nil {
64-
panic(err)
65-
}
66-
default:
67-
output = os.Stderr
68-
}
69-
70-
return output, hook
49+
return log, nil
7150
}

pkg/log/log_test.go

+41-33
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package log
33
import (
44
"fmt"
55
"os"
6+
"runtime"
67
"testing"
78

89
"github.com/sirupsen/logrus"
@@ -21,7 +22,10 @@ var (
2122
)
2223

2324
func TestLog(t *testing.T) {
24-
logger := New("warning", "", "test")
25+
logger, err := New("warning", "", "test")
26+
if err != nil {
27+
t.Errorf("Creating a new test logger shouldn't fail: %v", err)
28+
}
2529

2630
logger.Info("Changed: foo")
2731
logger.Warn("Changed: bar")
@@ -37,55 +41,59 @@ func TestLog(t *testing.T) {
3741
t.Errorf("Unexpected log entry: %s", hook.LastEntry().Message)
3842
}
3943

40-
logger = New("", "", "test")
41-
if logger.Level != logrus.InfoLevel {
42-
t.Error("The default loglevel should be info")
44+
for _, level := range levels {
45+
lg, err2 := New(level, "", "test")
46+
if err2 != nil || fmt.Sprintf("%T", lg) != "*logrus.Logger" {
47+
t.Errorf("Failed to instantiate at %s level: %v", level, err2)
48+
}
4349
}
4450

45-
logger = New("", "", "")
46-
if logger.Out != os.Stderr {
47-
t.Error("The default output should be stderr")
51+
logger, err = New("", "", "test")
52+
if err != nil || logger.Level != logrus.InfoLevel {
53+
t.Errorf("The default loglevel should be info %v", err)
4854
}
4955

50-
logger = New("info", "127.0.0.1:514", "syslog")
51-
if fmt.Sprintf("%T", logger) != "*logrus.Logger" {
52-
t.Error("Failed to instantiate a syslog logger")
56+
logger, err = New("", "", "")
57+
if err != nil || logger.Out != os.Stderr {
58+
t.Errorf("The default output should be stderr %v", err)
5359
}
5460

55-
logger = New("info", "", "stdout")
56-
if fmt.Sprintf("%T", logger) != "*logrus.Logger" {
57-
t.Error("Failed to instantiate a stdout logger")
61+
if runtime.GOOS != "windows" {
62+
logger, err = New("info", "127.0.0.1:514", "syslog")
63+
if err != nil || fmt.Sprintf("%T", logger) != "*logrus.Logger" {
64+
t.Errorf("Failed to instantiate a syslog logger %v", err)
65+
}
5866
}
5967

60-
logger = New("info", "", "stderr")
61-
if fmt.Sprintf("%T", logger) != "*logrus.Logger" {
62-
t.Error("Failed to instantiate a stderr logger")
68+
logger, err = New("info", "", "stdout")
69+
if err != nil || fmt.Sprintf("%T", logger) != "*logrus.Logger" {
70+
t.Errorf("Failed to instantiate a stdout logger %v", err)
6371
}
6472

65-
for _, level := range levels {
66-
lg := New(level, "", "test")
67-
if fmt.Sprintf("%T", lg) != "*logrus.Logger" {
68-
t.Errorf("Failed to instantiate at %s level", level)
69-
}
73+
logger, err = New("info", "", "stderr")
74+
if err != nil || fmt.Sprintf("%T", logger) != "*logrus.Logger" {
75+
t.Errorf("Failed to instantiate a stderr logger %v", err)
7076
}
7177
}
7278

7379
func TestSyslogMissingArg(t *testing.T) {
74-
defer func() {
75-
if r := recover(); r == nil {
76-
t.Errorf("syslog logger should panic without a server")
77-
}
78-
}()
80+
if runtime.GOOS == "windows" {
81+
t.Skip("syslog is not supported on Windows")
82+
}
7983

80-
_ = New("info", "", "syslog")
84+
_, err := New("info", "", "syslog")
85+
if err == nil {
86+
t.Errorf("syslog logger should fail without a server")
87+
}
8188
}
8289

8390
func TestSyslogWrongArg(t *testing.T) {
84-
defer func() {
85-
if r := recover(); r == nil {
86-
t.Errorf("syslog logger should panic on wrong server address")
87-
}
88-
}()
91+
if runtime.GOOS == "windows" {
92+
t.Skip("syslog is not supported on Windows")
93+
}
8994

90-
_ = New("info", "wrong server", "syslog")
95+
_, err := New("info", "wrong server", "syslog")
96+
if err == nil {
97+
t.Errorf("syslog logger should fail with a broken server address")
98+
}
9199
}

pkg/log/output.go

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// +build !windows
2+
3+
package log
4+
5+
import (
6+
"fmt"
7+
"io"
8+
"io/ioutil"
9+
"log/syslog"
10+
"os"
11+
12+
"github.com/sirupsen/logrus"
13+
ls "github.com/sirupsen/logrus/hooks/syslog"
14+
"github.com/sirupsen/logrus/hooks/test"
15+
)
16+
17+
func getOutput(logServer string, logOutput string) (io.Writer, logrus.Hook, error) {
18+
var output io.Writer
19+
var hook logrus.Hook
20+
var err error
21+
22+
switch logOutput {
23+
case outputStdout:
24+
output = os.Stdout
25+
case outputStderr:
26+
output = os.Stderr
27+
case outputTest:
28+
output = ioutil.Discard
29+
_, hook = test.NewNullLogger()
30+
case outputSyslog:
31+
output = os.Stderr
32+
if logServer == "" {
33+
return nil, nil, fmt.Errorf("syslog output needs a log server (ie. 127.0.0.1:514)")
34+
}
35+
hook, err = ls.NewSyslogHook("udp", logServer, syslog.LOG_INFO, "katafygio")
36+
if err != nil {
37+
return nil, nil, fmt.Errorf("failed to hook syslog output")
38+
}
39+
default:
40+
output = os.Stderr
41+
}
42+
43+
return output, hook, nil
44+
}

pkg/log/output_windows.go

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// +build windows
2+
3+
package log
4+
5+
import (
6+
"fmt"
7+
"io"
8+
"io/ioutil"
9+
"os"
10+
11+
"github.com/sirupsen/logrus"
12+
"github.com/sirupsen/logrus/hooks/test"
13+
)
14+
15+
func getOutput(logServer string, logOutput string) (io.Writer, logrus.Hook, error) {
16+
var output io.Writer
17+
var hook logrus.Hook
18+
19+
switch logOutput {
20+
case outputStdout:
21+
output = os.Stdout
22+
case outputStderr:
23+
output = os.Stderr
24+
case outputTest:
25+
output = ioutil.Discard
26+
_, hook = test.NewNullLogger()
27+
case outputSyslog:
28+
return nil, nil, fmt.Errorf("Syslog output isn't supported on Windows")
29+
default:
30+
output = os.Stderr
31+
}
32+
33+
return output, hook, nil
34+
}

0 commit comments

Comments
 (0)