From 618ae3b7f4a3b6a447a29a12c6f7eb13901e60c8 Mon Sep 17 00:00:00 2001 From: Frederik Mogensen Date: Tue, 17 Mar 2020 09:13:21 +0100 Subject: [PATCH 1/2] Upgrade to newest golangci-lint Upgrading to newest version of golangci-lint, v1.24.0. Using the install link from the officiel Readme, https://github.com/golangci/golangci-lint --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index d9d6877..c5f1c4c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,7 +12,7 @@ env: - GO111MODULE=on before_script: - - curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(go env GOPATH)/bin v1.17.1 + - curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.24.0 script: - golangci-lint run # Run a bunch of code checkers/linters in parallel From faffb16698e6754d84cf3936a0586edd6aed076d Mon Sep 17 00:00:00 2001 From: Lesterpig Date: Tue, 17 Mar 2020 17:24:44 +0100 Subject: [PATCH 2/2] Fix lint errors --- .golangci.yml | 1 + config.go | 6 ++++++ config_test.go | 1 + main.go | 4 ++++ manager.go | 4 ++++ probe/dns.go | 2 ++ probe/http.go | 3 +++ probe/http_test.go | 14 +++++++++++++- probe/minecraft.go | 22 +++++++++++++++++----- probe/port.go | 4 ++++ probe/probe.go | 2 ++ probe/smtp.go | 4 ++++ 12 files changed, 61 insertions(+), 6 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 1844377..929c457 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -5,6 +5,7 @@ linters-settings: linters: enable-all: true disable: + - gomnd - gochecknoinits - gochecknoglobals diff --git a/config.go b/config.go index 6f202c8..d064490 100644 --- a/config.go +++ b/config.go @@ -49,6 +49,7 @@ func parseConfigString(cnf string) (dir string, name string) { dir = filepath.Dir(cnf) basename := filepath.Base(cnf) name = strings.TrimSuffix(basename, filepath.Ext(basename)) + return } @@ -62,6 +63,7 @@ func loadConfig(configPath, configName string) (*Manager, error) { } sc := make([]serviceConfig, 0) + err = viper.UnmarshalKey("services", &sc) if err != nil { return nil, err @@ -69,6 +71,7 @@ func loadConfig(configPath, configName string) (*Manager, error) { manager := Manager{} manager.Services = make(map[string]([]*Service)) + for _, c := range sc { constructor := probeConstructors[c.Probe] if constructor == nil { @@ -78,6 +81,7 @@ func loadConfig(configPath, configName string) (*Manager, error) { c.Config = setProbeConfigDefaults(c.Config) prober := constructor() + err = prober.Init(c.Config) if err != nil { return nil, err @@ -91,12 +95,14 @@ func loadConfig(configPath, configName string) (*Manager, error) { } ac := make([]alertConfig, 0) + err = viper.UnmarshalKey("alerts", &ac) if err != nil { return nil, err } alerters = make([]alert.Alerter, 0) + for _, c := range ac { constructor := alertConstructors[c.Type] if constructor == nil { diff --git a/config_test.go b/config_test.go index 8aac93f..cbb2be1 100644 --- a/config_test.go +++ b/config_test.go @@ -21,6 +21,7 @@ func Test_parseConfigString(t *testing.T) { }, } for _, tt := range tests { + tt := tt t.Run(tt.args, func(t *testing.T) { gotDir, gotName := parseConfigString(tt.args) if gotDir != tt.wantDir { diff --git a/main.go b/main.go index 57d2876..c1ef1fb 100644 --- a/main.go +++ b/main.go @@ -22,6 +22,7 @@ var log = logrus.StandardLogger() func main() { flag.Parse() + interval := getInterval() log.Infof("Probe interval: %d", interval) @@ -48,11 +49,13 @@ func main() { func getInterval() int { intervalEnv := getInt(envy.Get("INTERVAL", "")) + if *intervalCli != 0 { return *intervalCli } else if intervalEnv != 0 { return intervalEnv } + return 10 } @@ -61,5 +64,6 @@ func getInt(s string) int { if nil != err { return 0 } + return int(i) } diff --git a/manager.go b/manager.go index da9db04..819f2d6 100644 --- a/manager.go +++ b/manager.go @@ -24,6 +24,7 @@ type Manager struct { // ProbeLoop starts the main loop that will call ProbeAll regularly. func (manager *Manager) ProbeLoop(interval time.Duration) { manager.ProbeAll() + c := time.Tick(interval) for range c { manager.ProbeAll() @@ -34,7 +35,9 @@ func (manager *Manager) ProbeLoop(interval time.Duration) { // Everything is done asynchronously. func (manager *Manager) ProbeAll() { log.Debug("Probing all") + manager.LastUpdate = time.Now() + for category, services := range manager.Services { for _, service := range services { go func(category string, service *Service) { @@ -57,6 +60,7 @@ func (manager *Manager) ProbeAll() { // It uses global configuration for list of alert (`A` variable). func AlertAll(category string, service *Service) { date := time.Now().Format("15:04:05 MST") + for _, alert := range alerters { alert.Alert(service.Status, category, service.Name, service.Message, service.Target, date) } diff --git a/probe/dns.go b/probe/dns.go index c4fbdc0..689064b 100644 --- a/probe/dns.go +++ b/probe/dns.go @@ -17,6 +17,7 @@ type DNS struct { func (d *DNS) Init(c Config) error { err := mapstructure.Decode(c.Options, d) d.Config = c + return err } @@ -29,6 +30,7 @@ func (d *DNS) Probe() (status Status, message string) { c := new(dns.Client) r, rtt, err := c.Exchange(m, d.Target+":53") + if err != nil { return StatusError, err.Error() } diff --git a/probe/http.go b/probe/http.go index 6083591..24a5258 100644 --- a/probe/http.go +++ b/probe/http.go @@ -29,7 +29,9 @@ type HTTPOptions struct { // Init configures the probe. func (h *HTTP) Init(c Config) error { h.Config = c + var opts HTTPOptions + err := mapstructure.Decode(c.Options, &opts) if err != nil { return err @@ -45,6 +47,7 @@ func (h *HTTP) Init(c Config) error { Transport: tr, } h.regex, err = regexp.Compile(opts.Regex) + return err } diff --git a/probe/http_test.go b/probe/http_test.go index fe92203..67516d9 100644 --- a/probe/http_test.go +++ b/probe/http_test.go @@ -15,7 +15,9 @@ func TestHTTPSuccess(t *testing.T) { Fatal: 10 * time.Second, Options: map[string]interface{}{"Regex": "Loïck"}, })) + s, m := h.Probe() + assert.True(t, StatusOK == s) t.Log(m) } @@ -27,7 +29,9 @@ func TestHTTPWarning(t *testing.T) { Warning: time.Microsecond, Fatal: 10 * time.Second, })) + s, _ := h.Probe() + assert.True(t, StatusWarning == s) } @@ -38,7 +42,9 @@ func TestHTTP404(t *testing.T) { Warning: 5 * time.Second, Fatal: 10 * time.Second, })) + s, _ := h.Probe() + assert.True(t, StatusError == s) } @@ -49,7 +55,9 @@ func TestHTTPError(t *testing.T) { Warning: 5 * time.Second, Fatal: 10 * time.Second, })) + s, _ := h.Probe() + assert.True(t, StatusError == s) } @@ -60,7 +68,9 @@ func TestHTTPTimeout(t *testing.T) { Warning: 5 * time.Second, Fatal: time.Microsecond, })) + s, _ := h.Probe() + assert.True(t, StatusError == s) } @@ -72,7 +82,9 @@ func TestHTTPUnexpected(t *testing.T) { Fatal: 10 * time.Second, Options: map[string]interface{}{"Regex": "Unexpected"}, })) + s, m := h.Probe() + assert.True(t, StatusError == s) - assert.True(t, "Unexpected result" == m) + assert.True(t, m == "Unexpected result") } diff --git a/probe/minecraft.go b/probe/minecraft.go index 4b9c4c4..4f7e6e7 100644 --- a/probe/minecraft.go +++ b/probe/minecraft.go @@ -28,6 +28,7 @@ func (m *Minecraft) Probe() (status Status, message string) { if err != nil { return StatusError, defaultConnectErrorMsg } + defer func() { _ = conn.Close() }() // Handshake @@ -40,6 +41,7 @@ func (m *Minecraft) Probe() (status Status, message string) { 0x00, 0x01, // Ask for status } + _, err = conn.Write(handshake) if err != nil { return StatusError, "Error during handshake" @@ -47,15 +49,17 @@ func (m *Minecraft) Probe() (status Status, message string) { // Status stat := []byte{0x01, 0x00} + _, err = conn.Write(stat) if err != nil { return StatusError, "Error during status" } // Result - _, _ = readVarInt(conn) // Packet length - _, _ = readVarInt(conn) // PacketID + _ = readVarInt(conn) // Packet length + _ = readVarInt(conn) // PacketID data := make([]byte, 10000) + read, err := conn.Read(data) if err != nil || read < 2 { return StatusError, "No stat received" @@ -63,6 +67,7 @@ func (m *Minecraft) Probe() (status Status, message string) { // Try to parse data result := new(minecraftServerStats) + err = json.Unmarshal(data[2:read], result) if err != nil { return StatusError, "Invalid stats" @@ -70,6 +75,7 @@ func (m *Minecraft) Probe() (status Status, message string) { message = fmt.Sprintf("%d / %d - %s", result.Players.Online, result.Players.Max, result.Version.Name) status = StatusOK + if result.Players.Online == result.Players.Max { status = StatusWarning } @@ -87,18 +93,24 @@ type minecraftServerStats struct { } `json:"players"` } -func readVarInt(c io.Reader) (res int, err error) { +func readVarInt(c io.Reader) (err error) { buf := []byte{0x00} + res := 0 + for i := 0; i < 5; i++ { _, err := c.Read(buf) if err != nil { - return 0, err + return err } res |= int((buf[0] & 0x7F) << uint(i*7)) - if 0x00 == buf[0]&0x80 { + + if buf[0]&0x80 == 0x00 { break } } + + _ = res + return } diff --git a/probe/port.go b/probe/port.go index af2d0f5..77907f1 100644 --- a/probe/port.go +++ b/probe/port.go @@ -15,6 +15,7 @@ type Port struct { // Init configures the probe. func (p *Port) Init(c Config) error { p.Config = c + u, err := url.Parse(p.Target) if err != nil { return err @@ -22,6 +23,7 @@ func (p *Port) Init(c Config) error { p.network = u.Scheme p.addrport = u.Host + return nil } @@ -30,11 +32,13 @@ func (p *Port) Init(c Config) error { // Otherwise, an error message is returned. func (p *Port) Probe() (status Status, message string) { start := time.Now() + conn, err := net.DialTimeout(p.network, p.addrport, p.Fatal) if err != nil { return StatusError, defaultConnectErrorMsg } _ = conn.Close() + return EvaluateDuration(time.Since(start), p.Warning) } diff --git a/probe/probe.go b/probe/probe.go index e09cda0..98cfe7b 100644 --- a/probe/probe.go +++ b/probe/probe.go @@ -43,6 +43,8 @@ func EvaluateDuration(duration time.Duration, warning time.Duration) (status Sta } else { status = StatusOK } + message = fmt.Sprintf("%d ms", duration.Nanoseconds()/1000000) + return } diff --git a/probe/smtp.go b/probe/smtp.go index 3a6af25..0ebbcb9 100644 --- a/probe/smtp.go +++ b/probe/smtp.go @@ -24,22 +24,26 @@ func (s *SMTP) Init(c Config) error { // Otherwise, an error message is returned. func (s *SMTP) Probe() (status Status, message string) { start := time.Now() + conn, err := net.DialTimeout("tcp", s.Target, s.Fatal) if err != nil { return StatusError, defaultConnectErrorMsg } defer func() { _ = conn.Close() }() + host, _, _ := net.SplitHostPort(s.Target) secure := tls.Client(conn, &tls.Config{ ServerName: host, }) data := make([]byte, 4) + _, err = secure.Read(data) if err != nil { return StatusError, "TLS Error" } + if fmt.Sprintf("%s", data) != "220 " { return StatusError, "Unexpected reply" }