diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml new file mode 100644 index 00000000..6fcde23e --- /dev/null +++ b/.github/workflows/golangci-lint.yml @@ -0,0 +1,34 @@ +name: CI Lint + +on: + pull_request: + branches: + - main + paths: + - "**/*.go" + - ".github/workflows/golangci.lint.yml" + +env: + GO_VERSION: "1.20" + +jobs: + + analysis: + runs-on: ubuntu-latest + steps: + + - name: Set up Go + uses: actions/setup-go@v4 + with: + go-version: ${{ env.GO_VERSION }} + + - name: Check out code into the Go module directory + uses: actions/checkout@v3 + + - name: golangci-lint + uses: golangci/golangci-lint-action@v3 + with: + version: v1.54 + # no errcheck, and no check for deprecated code. + # since some deprecated code is used in the project and no perfect replacement is available yet. + args: --timeout=30m --disable=errcheck --exclude=SA1019 \ No newline at end of file diff --git a/channel/channel.go b/channel/channel.go index d3aded98..3fc8e8ec 100644 --- a/channel/channel.go +++ b/channel/channel.go @@ -129,7 +129,7 @@ func (c *Channel) WatchEvent(wg *sync.WaitGroup) { defer wg.Done() // check if the channel is watching - if atomic.CompareAndSwapInt32(&(c.isWatch), 0, 1) == false { + if !atomic.CompareAndSwapInt32(&(c.isWatch), 0, 1) { log.Warnf("[%s/ %s]: Channel is already watching!", kind, c.Name) return } @@ -168,7 +168,7 @@ func (c *Channel) WatchEvent(wg *sync.WaitGroup) { // if the status is DOWN, check the notification strategy if result.Status == probe.StatusDown { - if result.Stat.NotificationStrategyData.NeedToSendNotification() == false { + if !result.Stat.NotificationStrategyData.NeedToSendNotification() { log.Debugf("[%s / %s]: %s (%s) - Don't meet the notification condition [max=%d, notified=%d, failed=%d, next=%d], no notification.", kind, c.Name, result.Name, result.Endpoint, nsd.MaxTimes, nsd.Notified, nsd.Failed, nsd.Next) continue @@ -184,7 +184,7 @@ func (c *Channel) WatchEvent(wg *sync.WaitGroup) { } for _, n := range c.Notifiers { - if IsDryNotify() == true { + if IsDryNotify() { n.DryNotify(result) } else { go n.Notify(result) diff --git a/conf/conf_test.go b/conf/conf_test.go index dc38ded4..188ec8ec 100644 --- a/conf/conf_test.go +++ b/conf/conf_test.go @@ -175,16 +175,6 @@ func checkHTTPProbe(t *testing.T, probe httpProbe.HTTP) { } } -const confTCP = ` -tcp: - - name: Example SSH - host: example.com:22 - timeout: 10s - interval: 2m - - name: Example HTTP - host: example.com:80 -` - func checkTCPProbe(t *testing.T, probe tcp.TCP) { switch probe.ProbeName { case "Example SSH": @@ -198,32 +188,6 @@ func checkTCPProbe(t *testing.T, probe tcp.TCP) { } } -const confShell = ` -shell: - - name: Google Service - cmd: "./resources/scripts/probe/proxy.curl.sh" - args: - - "socks5://127.0.0.1:1085" - - "www.google.com" - timeout: 20s - interval: 1m - channels: - - "telegram#Dev" - - name: Redis (Local) - cmd: "redis-cli" - args: - - "-h" - - "127.0.0.1" - - "-p" - - 6379 - - "ping" - env: - - "REDISCLI_AUTH=abc123" - contain: "PONG" - channels: - - "slack" -` - func checkShellProbe(t *testing.T, probe shell.Shell) { switch probe.ProbeName { case "Google Service": diff --git a/conf/log.go b/conf/log.go index 924c2657..f1534316 100644 --- a/conf/log.go +++ b/conf/log.go @@ -122,7 +122,7 @@ func (l *Log) Open() { return } // using lumberjack if self rotate - if l.SelfRotate == true { + if l.SelfRotate { log.Debugf("[Log] Self Rotate log file %s", l.File) l.IsStdout = false l.Writer = &lumberjack.Logger{ @@ -167,7 +167,7 @@ func (l *Log) GetWriter() io.Writer { // Rotate rotate the log file func (l *Log) Rotate() { - if l.Writer == nil || l.IsStdout == true { + if l.Writer == nil || l.IsStdout { return } if lumberjackLogger, ok := l.Writer.(*lumberjack.Logger); ok { diff --git a/daemon/daemon_test.go b/daemon/daemon_test.go index b2895c37..22b3daca 100644 --- a/daemon/daemon_test.go +++ b/daemon/daemon_test.go @@ -100,12 +100,12 @@ func TestPIDFileFailed(t *testing.T) { assert.NotNil(t, err) file = "./" - conf, err = NewPIDFile(file) + NewPIDFile(file) assert.FileExists(t, global.DefaultPIDFile) os.RemoveAll(global.DefaultPIDFile) file = "dir/easedprobe.pid" - conf, err = NewPIDFile(file) + conf, _ = NewPIDFile(file) assert.FileExists(t, file) conf.RemovePIDFile() os.RemoveAll("dir") diff --git a/eval/eval.go b/eval/eval.go index 5aa27e99..c49a3110 100644 --- a/eval/eval.go +++ b/eval/eval.go @@ -199,15 +199,15 @@ func (e *Evaluator) Evaluate() (bool, error) { if err != nil { return false, err } - switch result.(type) { + switch r := result.(type) { case bool: - return result.(bool), nil + return r, nil case float64: - return result.(float64) != 0, nil + return r != 0, nil case string: - return result.(string) != "", nil + return r != "", nil } - return false, fmt.Errorf("Unsupported type: %T", result) + return false, fmt.Errorf("unsupported type: %T", result) } // Extract is the function to extract the value from the document diff --git a/global/global.go b/global/global.go index ab722245..309df690 100644 --- a/global/global.go +++ b/global/global.go @@ -192,7 +192,7 @@ func EnumUnmarshalJSON[T comparable](b []byte, m map[string]T, v *T, init T, typ func (t *TLS) Config() (*tls.Config, error) { if len(t.CA) <= 0 { // the insecure is true but no ca/cert/key, then return a tls config - if t.Insecure == true { + if t.Insecure { log.Debug("[TLS] Insecure is true but the CA is empty, return a tls config") return &tls.Config{InsecureSkipVerify: true}, nil } diff --git a/metric/prometheus.go b/metric/prometheus.go index 42a1ae20..cd6996f8 100644 --- a/metric/prometheus.go +++ b/metric/prometheus.go @@ -34,11 +34,8 @@ type MetricsType interface { } var ( - registries = make([]*prometheus.Registry, 0) - counterMap = make(map[string]*prometheus.CounterVec) - gaugeMap = make(map[string]*prometheus.GaugeVec) - histogramMap = make(map[string]*prometheus.HistogramVec) - summaryMap = make(map[string]*prometheus.SummaryVec) + counterMap = make(map[string]*prometheus.CounterVec) + gaugeMap = make(map[string]*prometheus.GaugeVec) ) var ( @@ -127,12 +124,12 @@ func mergeLabels(labels []string, constLabels prometheus.Labels) []string { func getAndValid(namespace, subsystem, name, metric string, labels []string, constLabels prometheus.Labels) (string, error) { metricName := GetName(namespace, subsystem, name, metric) - if ValidMetricName(metricName) == false { + if !ValidMetricName(metricName) { return "", fmt.Errorf("invalid metric name: %s", metricName) } for _, l := range labels { - if ValidLabelName(l) == false { + if !ValidLabelName(l) { return "", fmt.Errorf("invalid label name: %s", l) } } diff --git a/notify/email/email_test.go b/notify/email/email_test.go index 77e7c917..1975e14a 100644 --- a/notify/email/email_test.go +++ b/notify/email/email_test.go @@ -37,10 +37,6 @@ func (mwc *MyWriteCloser) Close() error { func (mwc *MyWriteCloser) Write(p []byte) (n int, err error) { return len(p), nil } -func assertError(t *testing.T, err error, msg string) { - assert.Error(t, err) - assert.Equal(t, msg, err.Error()) -} func TestEmail(t *testing.T) { conf := &NotifyConfig{} diff --git a/notify/log/log_unix.go b/notify/log/log_unix.go index 13b350da..844aeb55 100644 --- a/notify/log/log_unix.go +++ b/notify/log/log_unix.go @@ -65,7 +65,7 @@ func (c *NotifyConfig) IsSyslog() bool { // HasNetwork returns true if the log has network configuration func (c *NotifyConfig) HasNetwork() bool { // if is not syslog, then return false - if c.IsSyslog() == false { + if !c.IsSyslog() { return false } // if is syslog, but not configured network, then return false @@ -88,7 +88,7 @@ func (c *NotifyConfig) ConfigLog() error { hasNetwork := c.HasNetwork() // syslog && network configuration error - if isSyslog == true && hasNetwork == true { // remote syslog + if isSyslog && hasNetwork { // remote syslog c.NotifyKind = syslogIdentifier c.Type = SysLog if err := c.checkNetworkProtocol(); err != nil { @@ -101,7 +101,7 @@ func (c *NotifyConfig) ConfigLog() error { } c.logger.SetOutput(writer) log.Infof("[%s / %s] - remote syslog (%s:%s) configured", c.Kind(), c.Name(), c.Network, c.Host) - } else if isSyslog == true { // only for local syslog + } else if isSyslog { // only for local syslog c.NotifyKind = syslogIdentifier c.Type = SysLog writer, err := syslog.New(syslog.LOG_NOTICE, global.GetEaseProbe().Name) diff --git a/notify/shell/shell.go b/notify/shell/shell.go index cd46d7a7..cba7dde6 100644 --- a/notify/shell/shell.go +++ b/notify/shell/shell.go @@ -71,7 +71,7 @@ func (c *NotifyConfig) RunShell(title, msg string) error { env = append(env, fmt.Sprintf("%s=%s", k, v)) } cmd.Stdin = strings.NewReader(envMap["EASEPROBE_CSV"]) - if c.CleanEnv == false { + if !c.CleanEnv { cmd.Env = append(os.Environ(), env...) } else { log.Infof("[%s / %s] clean the environment variables", c.NotifyKind, c.NotifyName) diff --git a/probe/base/base.go b/probe/base/base.go index 3ff1caec..de617962 100644 --- a/probe/base/base.go +++ b/probe/base/base.go @@ -118,21 +118,21 @@ func (d *DefaultProbe) CheckStatusThreshold() probe.Status { log.Debugf("%s - Status Threshold Checking - Current[%v], StatusCnt[%d], FailureThread[%d], SuccessThread[%d]", title, c.CurrentStatus, c.StatusCount, s.Failure, s.Success) - if c.CurrentStatus == true && c.StatusCount >= s.Success { + if c.CurrentStatus && c.StatusCount >= s.Success { if d.ProbeResult.Status != probe.StatusUp { cnt := math.Max(float64(c.StatusCount), float64(s.Success)) log.Infof("%s - Status is UP! Threshold reached for success [%d/%d]", title, int(cnt), s.Success) } return probe.StatusUp } - if c.CurrentStatus == false && c.StatusCount >= s.Failure { + if !c.CurrentStatus && c.StatusCount >= s.Failure { if d.ProbeResult.Status != probe.StatusDown { cnt := math.Max(float64(c.StatusCount), float64(s.Failure)) log.Infof("%s - Status is DOWN! Threshold reached for failure [%d/%d]", title, int(cnt), s.Failure) } return probe.StatusDown } - if c.CurrentStatus == true { + if c.CurrentStatus { log.Infof("%s - Status unchanged [%s]! Threshold is not reached for success [%d/%d].", title, d.ProbeResult.PreStatus, c.StatusCount, s.Success) } else { diff --git a/probe/client/memcache/memcache_test.go b/probe/client/memcache/memcache_test.go index 49457e4d..df73113e 100644 --- a/probe/client/memcache/memcache_test.go +++ b/probe/client/memcache/memcache_test.go @@ -108,7 +108,7 @@ func TestMemcache(t *testing.T) { m.Data = map[string]string{} m.ProbeTimeout = time.Second - s, msg = m.Probe() + s, _ = m.Probe() assert.False(t, s) monkey.PatchInstanceMethod(reflect.TypeOf(mc), "Ping", func(*memcache.Client) error { diff --git a/probe/client/mongo/mongo_test.go b/probe/client/mongo/mongo_test.go index 0cff3a7f..aa7a580c 100644 --- a/probe/client/mongo/mongo_test.go +++ b/probe/client/mongo/mongo_test.go @@ -78,6 +78,7 @@ func TestMongo(t *testing.T) { conf.Password = "" mg, err = New(conf) + assert.Nil(t, err) connStr = fmt.Sprintf("mongodb://%s/?connectTimeoutMS=%d", conf.Host, conf.Timeout().Milliseconds()) assert.Equal(t, connStr, mg.ConnStr) @@ -92,6 +93,7 @@ func TestMongo(t *testing.T) { }) mg, err = New(conf) + assert.Nil(t, err) assert.Equal(t, "Mongo", mg.Kind()) assert.Equal(t, connStr, mg.ConnStr) assert.NotNil(t, mg.ClientOpt.TLSConfig) @@ -175,6 +177,7 @@ func TestDta(t *testing.T) { "database:collection": "{\"key\" : \"value\"}", } mg, err = New(conf) + assert.Nil(t, err) s, m := mg.Probe() assert.True(t, s) assert.Contains(t, m, "Successfully") diff --git a/probe/client/mysql/mysql_test.go b/probe/client/mysql/mysql_test.go index c553908c..9f5d170e 100644 --- a/probe/client/mysql/mysql_test.go +++ b/probe/client/mysql/mysql_test.go @@ -59,7 +59,7 @@ func TestMySQL(t *testing.T) { assert.Equal(t, connStr, my.ConnStr) conf.Password = "" - my, err = New(conf) + my, _ = New(conf) connStr = fmt.Sprintf("%s@tcp(%s)/?timeout=%s", conf.Username, conf.Host, conf.Timeout().Round(time.Second)) assert.Equal(t, connStr, my.ConnStr) @@ -95,7 +95,7 @@ func TestMySQL(t *testing.T) { return nil }) - my, err = New(conf) + my, _ = New(conf) assert.NotNil(t, my.tls) s, m = my.Probe() assert.True(t, s) @@ -146,21 +146,24 @@ func TestData(t *testing.T) { "": "", }, } - my, err := New(conf) + var my *MySQL + var err error + + _, err = New(conf) assert.NotNil(t, err) assert.Contains(t, err.Error(), "Empty SQL data") conf.Data = map[string]string{ "key": "value", } - my, err = New(conf) + _, err = New(conf) assert.NotNil(t, err) assert.Contains(t, err.Error(), "Invalid SQL data") conf.Data = map[string]string{ "database:table:column:key:value": "expected", } - my, err = New(conf) + _, err = New(conf) assert.NotNil(t, err) assert.Contains(t, err.Error(), "the value must be int") @@ -186,7 +189,7 @@ func TestData(t *testing.T) { conf.Data = map[string]string{ "database:table:column:key:1": "expected", } - my, err = New(conf) + my, _ = New(conf) s, m := my.Probe() assert.True(t, s) assert.Contains(t, m, "Successfully") diff --git a/probe/client/postgres/postgres_test.go b/probe/client/postgres/postgres_test.go index f77d3596..d09ce8d2 100644 --- a/probe/client/postgres/postgres_test.go +++ b/probe/client/postgres/postgres_test.go @@ -96,7 +96,7 @@ func TestPostgreSQL(t *testing.T) { return &tls.Config{}, nil }) - pg, err = New(conf) + pg, _ = New(conf) pgd = pgdriver.NewConnector(pg.ClientOptions...) assert.True(t, pgd.Config().TLSConfig.InsecureSkipVerify) @@ -186,7 +186,7 @@ func TestData(t *testing.T) { conf.Data = map[string]string{ "database:table:column:key:1": "expected", } - pg, err = New(conf) + pg, _ = New(conf) s, m := pg.Probe() assert.True(t, s) assert.Contains(t, m, "Successfully") diff --git a/probe/client/zookeeper/zookeeper_test.go b/probe/client/zookeeper/zookeeper_test.go index 6e4163af..30bee936 100644 --- a/probe/client/zookeeper/zookeeper_test.go +++ b/probe/client/zookeeper/zookeeper_test.go @@ -66,7 +66,6 @@ func TestZooKeeper(t *testing.T) { return []byte("test"), &zk.Stat{}, nil }) monkey.PatchInstanceMethod(reflect.TypeOf(conn), "Close", func(_ *zk.Conn) { - return }) monkey.Patch(zk.ConnectWithDialer, func(servers []string, sessionTimeout time.Duration, dialer zk.Dialer) (*zk.Conn, <-chan zk.Event, error) { @@ -178,7 +177,6 @@ func TestData(t *testing.T) { }) var conn *zk.Conn monkey.PatchInstanceMethod(reflect.TypeOf(conn), "Close", func(_ *zk.Conn) { - return }) monkey.PatchInstanceMethod(reflect.TypeOf(conn), "Get", func(_ *zk.Conn, path string) ([]byte, *zk.Stat, error) { return []byte("test"), &zk.Stat{}, nil diff --git a/probe/data_test.go b/probe/data_test.go index 56ebe514..dfff9b16 100644 --- a/probe/data_test.go +++ b/probe/data_test.go @@ -109,10 +109,6 @@ func isDataFileExisted(file string) bool { return true } -func removeDataFile(file string) { - os.Remove(file) -} - func makeAllDir(file string) { dir, _ := filepath.Split(file) os.MkdirAll(dir, 0755) diff --git a/probe/host/host.go b/probe/host/host.go index 49fbab0f..051f1d03 100644 --- a/probe/host/host.go +++ b/probe/host/host.go @@ -121,7 +121,7 @@ func (s *Server) CheckThreshold(info Info) (bool, string) { for _, metric := range s.hostMetrics { s, m := metric.CheckThreshold() - if s == false { + if !s { status = false message = addMessage(message, m) } diff --git a/probe/notification_strategy.go b/probe/notification_strategy.go index cf74cfe5..f1cd35c3 100644 --- a/probe/notification_strategy.go +++ b/probe/notification_strategy.go @@ -123,7 +123,7 @@ func (n *NotificationStrategyData) NextNotification() { // ProcessStatus processes the probe status func (n *NotificationStrategyData) ProcessStatus(status bool) { n.IsSent = false - if status == true { + if status { n.Reset() return } diff --git a/probe/shell/shell.go b/probe/shell/shell.go index be5c1e95..5099ef44 100644 --- a/probe/shell/shell.go +++ b/probe/shell/shell.go @@ -75,7 +75,7 @@ func (s *Shell) DoProbe() (bool, string) { defer cancel() cmd := exec.CommandContext(ctx, s.Command, s.Args...) - if s.CleanEnv == false { + if !s.CleanEnv { cmd.Env = append(os.Environ(), s.Env...) } else { log.Infof("[%s / %s] clean the environment variables", s.ProbeKind, s.ProbeName) diff --git a/probe/ssh/ssh_test.go b/probe/ssh/ssh_test.go index ccae8ebc..f37f72ec 100644 --- a/probe/ssh/ssh_test.go +++ b/probe/ssh/ssh_test.go @@ -174,8 +174,8 @@ func TestSSH(t *testing.T) { return &ssh.Client{Conn: c}, nil }) monkey.Patch(ssh.NewClient, func(c ssh.Conn, chans <-chan ssh.NewChannel, reqs <-chan *ssh.Request) *ssh.Client { - c, _, _, _ = ssh.NewClientConn(nil, "", nil) - return &ssh.Client{Conn: c} + conn, _, _, _ := ssh.NewClientConn(nil, "", nil) + return &ssh.Client{Conn: conn} }) var client *ssh.Client monkey.PatchInstanceMethod(reflect.TypeOf(client), "Dial", func(c *ssh.Client, n, a string) (net.Conn, error) { diff --git a/report/sla.go b/report/sla.go index 367e78f7..b2172861 100644 --- a/report/sla.go +++ b/report/sla.go @@ -360,7 +360,7 @@ func SLAStatusText(s probe.Stat, t Format) string { // sort status var statusKeys []int - for statusKey, _ := range s.Status { + for statusKey := range s.Status { statusKeys = append(statusKeys, int(statusKey)) } sort.Ints(statusKeys) diff --git a/web/log.go b/web/log.go index 8dceb140..789440ba 100644 --- a/web/log.go +++ b/web/log.go @@ -63,7 +63,7 @@ type PlainFormatter struct { // Format formats the log entry func (f *PlainFormatter) Format(entry *logrus.Entry) ([]byte, error) { - timestamp := fmt.Sprintf(entry.Time.Format(f.TimestampFormat)) + timestamp := entry.Time.Format(f.TimestampFormat) return []byte(fmt.Sprintf("%s %s\n", timestamp, entry.Message)), nil }