From 4fc1d07cfb251ffdd0d9eb17211d1c76996623dd Mon Sep 17 00:00:00 2001 From: Markus Opolka Date: Thu, 24 Aug 2023 16:11:51 +0200 Subject: [PATCH 1/2] Update golangci-lint config --- .golangci.yml | 56 ++++++++++++++++++++++++++------------------------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 53a1bcf..098fcb7 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,30 +1,32 @@ run: timeout: 5m - skip-files: - - '(.+)_test\.go' - + tests: false linters: - disable-all: false - enable: - - funlen - - dogsled - - dupl - # - lll - - whitespace - - wsl - - exportloopref - disable: - - scopelint - - bodyclose - - contextcheck - - nilerr - - noctx - - rowserrcheck - - sqlclosecheck - - structcheck - - unparam - presets: - - bugs - - unused - # - style - fast: false + enable-all: true + disable: + - cyclop + - depguard + - exhaustivestruct + - exhaustruct + - forbidigo + - gci + - gochecknoglobals + - gochecknoinits + - godox + - goerr113 + - gofumpt + - gomnd + - lll + - musttag + - nakedret + - nlreturn + - nolintlint + - nonamedreturns + - tagliatelle + - varnamelen + - wrapcheck +linters-settings: + estif: + min-complexity: 4 + maligned: + suggest-new: true From ea93c8d8819d3ca1a584c81da861c69761a35950 Mon Sep 17 00:00:00 2001 From: Markus Opolka Date: Thu, 24 Aug 2023 16:12:32 +0200 Subject: [PATCH 2/2] Fix various lint issues --- .golangci.yml | 1 + cmd/alert.go | 7 ++++--- cmd/config.go | 10 +++++----- cmd/config_test.go | 4 ++-- cmd/health.go | 3 ++- cmd/health_test.go | 4 ++-- cmd/query.go | 23 +++++++++++------------ cmd/query_test.go | 4 ++-- cmd/root.go | 5 +++-- internal/alert/alert.go | 19 ++++++++++--------- internal/alert/alert_test.go | 5 +++-- internal/client/client.go | 33 ++++++++++++++++++--------------- main.go | 4 ++-- 13 files changed, 65 insertions(+), 57 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 098fcb7..f90a24d 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -9,6 +9,7 @@ linters: - exhaustivestruct - exhaustruct - forbidigo + - forcetypeassert - gci - gochecknoglobals - gochecknoinits diff --git a/cmd/alert.go b/cmd/alert.go index 17f170d..7624de4 100644 --- a/cmd/alert.go +++ b/cmd/alert.go @@ -2,12 +2,13 @@ package cmd import ( "fmt" + "strings" + "github.com/NETWAYS/check_prometheus/internal/alert" "github.com/NETWAYS/go-check" "github.com/NETWAYS/go-check/perfdata" "github.com/NETWAYS/go-check/result" "github.com/spf13/cobra" - "strings" ) func generateOutput(rl alert.Rule, cfg AlertConfig) (output string) { @@ -78,7 +79,7 @@ inactive = 0`, // We use the Rules endpoint since it contains // the state of inactive Alert Rules, unlike the Alert endpoint // Search requested Alert in all Groups and all Rules - alerts, err := c.Api.Rules(ctx) + alerts, err := c.API.Rules(ctx) if err != nil { check.ExitError(err) } @@ -89,7 +90,7 @@ inactive = 0`, // Set initial capacity to reduce memory allocations var l int for _, rl := range rules { - l = l * len(rl.AlertingRule.Alerts) + l *= len(rl.AlertingRule.Alerts) } rStates := make([]int, 0, l) diff --git a/cmd/config.go b/cmd/config.go index 2008b36..675fc3e 100644 --- a/cmd/config.go +++ b/cmd/config.go @@ -28,10 +28,10 @@ type Config struct { CertFile string KeyFile string Hostname string + Port int Info bool Insecure bool PReady bool - Port int Secure bool } @@ -95,7 +95,7 @@ func (c *Config) NewClient() *client.Client { // Using a Bearer Token for authentication if c.Bearer != "" { - var t config.Secret = config.Secret(c.Bearer) + var t = config.Secret(c.Bearer) rt = config.NewAuthorizationCredentialsRoundTripper("Bearer", t, rt) } @@ -103,12 +103,12 @@ func (c *Config) NewClient() *client.Client { if c.BasicAuth != "" { s := strings.Split(c.BasicAuth, ":") if len(s) != 2 { - check.ExitError(fmt.Errorf("Specify the user name and password for server authentication ")) + check.ExitError(fmt.Errorf("specify the user name and password for server authentication ")) } - var u string = s[0] + var u = s[0] - var p config.Secret = config.Secret(s[1]) + var p = config.Secret(s[1]) rt = config.NewBasicAuthRoundTripper(u, p, "", rt) } diff --git a/cmd/config_test.go b/cmd/config_test.go index baf4e9f..07d74b4 100644 --- a/cmd/config_test.go +++ b/cmd/config_test.go @@ -7,7 +7,7 @@ import ( func TestConfig(t *testing.T) { c := cliConfig.NewClient() expected := "http://localhost:9090" - if c.Url != "http://localhost:9090" { - t.Error("\nActual: ", c.Url, "\nExpected: ", expected) + if c.URL != "http://localhost:9090" { + t.Error("\nActual: ", c.URL, "\nExpected: ", expected) } } diff --git a/cmd/health.go b/cmd/health.go index 8ad3ca1..59a47fd 100644 --- a/cmd/health.go +++ b/cmd/health.go @@ -2,6 +2,7 @@ package cmd import ( "fmt" + "github.com/NETWAYS/go-check" "github.com/NETWAYS/go-check/perfdata" "github.com/spf13/cobra" @@ -53,7 +54,7 @@ Ready: Checks the readiness of an endpoint, which returns OK if the Prometheus s if cliConfig.Info { // Displays various build information properties about the Prometheus server - info, err := c.Api.Buildinfo(ctx) + info, err := c.API.Buildinfo(ctx) if err != nil { check.ExitError(err) } diff --git a/cmd/health_test.go b/cmd/health_test.go index 911c5bd..71e9e00 100644 --- a/cmd/health_test.go +++ b/cmd/health_test.go @@ -15,7 +15,7 @@ func TestHealth_ConnectionRefused(t *testing.T) { out, _ := cmd.CombinedOutput() actual := string(out) - expected := "[UNKNOWN] - Could not get status: Get \"http://localhost:9999/-/healthy\": dial" + expected := "[UNKNOWN] - could not get status: Get \"http://localhost:9999/-/healthy\": dial" if !strings.Contains(actual, expected) { t.Error("\nActual: ", actual, "\nExpected: ", expected) @@ -133,7 +133,7 @@ func TestHealthCmd(t *testing.T) { w.Write([]byte(`Access Denied!`)) })), args: []string{"run", "../main.go", "--user", "passwordmissing", "health"}, - expected: "[UNKNOWN] - Specify the user name and password for server authentication (*errors.errorString)\nexit status 3\n", + expected: "[UNKNOWN] - specify the user name and password for server authentication (*errors.errorString)\nexit status 3\n", }, } diff --git a/cmd/query.go b/cmd/query.go index b8fb405..8559720 100644 --- a/cmd/query.go +++ b/cmd/query.go @@ -2,13 +2,14 @@ package cmd import ( "fmt" + "strings" + "time" + "github.com/NETWAYS/go-check" "github.com/NETWAYS/go-check/perfdata" goresult "github.com/NETWAYS/go-check/result" "github.com/prometheus/common/model" "github.com/spf13/cobra" - "strings" - "time" ) type QueryConfig struct { @@ -54,7 +55,7 @@ Note: Time range values e.G. 'go_memstats_alloc_bytes_total[0s]' only the latest | value_go_gc_duration_seconds_count_localhost:9090_prometheus=1599 value_go_gc_duration_seconds_count_node-exporter:9100_node-exporter=79610`, PreRun: func(cmd *cobra.Command, args []string) { if cliQueryConfig.Warning == "" || cliQueryConfig.Critical == "" { - check.ExitError(fmt.Errorf("Please specify warning and critical thresholds")) + check.ExitError(fmt.Errorf("please specify warning and critical thresholds")) } }, Run: func(cmd *cobra.Command, args []string) { @@ -89,26 +90,26 @@ Note: Time range values e.G. 'go_memstats_alloc_bytes_total[0s]' only the latest ctx, cancel := cliConfig.timeoutContext() defer cancel() - result, warnings, err := c.Api.Query(ctx, cliQueryConfig.RawQuery, time.Now()) + result, warnings, err := c.API.Query(ctx, cliQueryConfig.RawQuery, time.Now()) if err != nil { if strings.Contains(err.Error(), "unmarshalerDecoder: unexpected value type \"string\"") { - err = fmt.Errorf("String value results are not supported") + err = fmt.Errorf("string value results are not supported") } check.ExitError(err) } switch result.Type() { default: - check.ExitError(fmt.Errorf("None value results are not supported")) + check.ExitError(fmt.Errorf("none value results are not supported")) // Scalar - a simple numeric floating point value case model.ValScalar: - check.ExitError(fmt.Errorf("Scalar value results are not supported")) + check.ExitError(fmt.Errorf("scalar value results are not supported")) case model.ValNone: - check.ExitError(fmt.Errorf("None value results are not supported")) + check.ExitError(fmt.Errorf("none value results are not supported")) case model.ValString: // String - a simple string value; currently unused - check.ExitError(fmt.Errorf("String value results are not supported")) + check.ExitError(fmt.Errorf("string value results are not supported")) case model.ValVector: // Instant vector - a set of time series containing a single sample for each time series, all sharing the same timestamp vectorVal := result.(model.Vector) @@ -175,9 +176,7 @@ Note: Time range values e.G. 'go_memstats_alloc_bytes_total[0s]' only the latest states = mStates } - // The worst state of all metrics determines the final return state. Example: - // OK, OK, OK > OK - // Critical, OK, OK > Critical + // The worst state of all metrics determines the final return state. worstState := goresult.WorstState(states...) if worstState == check.OK { summary.WriteString(fmt.Sprintf("%d Metrics OK", metricsCounter)) diff --git a/cmd/query_test.go b/cmd/query_test.go index 2fe6456..b6efecd 100644 --- a/cmd/query_test.go +++ b/cmd/query_test.go @@ -79,7 +79,7 @@ func TestQueryCmd(t *testing.T) { w.Write([]byte(`{"status":"success","data":{"resultType":"scalar","result":[1670339013.992,"1"]}}`)) })), args: []string{"run", "../main.go", "query", "--query", "1"}, - expected: "[UNKNOWN] - Scalar value results are not supported (*errors.errorString)\nexit status 3\n", + expected: "[UNKNOWN] - scalar value results are not supported (*errors.errorString)\nexit status 3\n", }, { name: "query-string", @@ -88,7 +88,7 @@ func TestQueryCmd(t *testing.T) { w.Write([]byte(`{"status":"success","data":{"resultType":"string","result":[1670339013.992,"up"]}}`)) })), args: []string{"run", "../main.go", "query", "--query", "up"}, - expected: "[UNKNOWN] - String value results are not supported (*errors.errorString)\nexit status 3\n", + expected: "[UNKNOWN] - string value results are not supported (*errors.errorString)\nexit status 3\n", }, { name: "query-matrix-exists", diff --git a/cmd/root.go b/cmd/root.go index d2c777f..0c33342 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -1,9 +1,10 @@ package cmd import ( + "os" + "github.com/NETWAYS/go-check" "github.com/spf13/cobra" - "os" ) var Timeout = 30 @@ -66,7 +67,7 @@ func init() { rootCmd.SetHelpTemplate(help + Copyright) } -func Usage(cmd *cobra.Command, strings []string) { +func Usage(cmd *cobra.Command, _ []string) { _ = cmd.Usage() os.Exit(3) diff --git a/internal/alert/alert.go b/internal/alert/alert.go index 8ecb69d..097a705 100644 --- a/internal/alert/alert.go +++ b/internal/alert/alert.go @@ -2,15 +2,16 @@ package alert import ( "fmt" + "strconv" + "strings" + "github.com/NETWAYS/go-check" v1 "github.com/prometheus/client_golang/api/prometheus/v1" "github.com/prometheus/common/model" - "strconv" - "strings" ) -// Internal representation of Prometheus Rules -// Alert attribute will be used when iterating over multiple AlertingRules +// Internal representation of Prometheus Rules. +// Alert attribute will be used when iterating over multiple AlertingRules. type Rule struct { AlertingRule v1.AlertingRule Alert *v1.Alert @@ -18,11 +19,11 @@ type Rule struct { func FlattenRules(groups []v1.RuleGroup) []Rule { // Flattens a list of RuleGroup containing a list of Rules into - // a list of internal Alertingrules + // a list of internal Alertingrules. var l int - // Set initial capacity to reduce memory allocations + // Set initial capacity to reduce memory allocations. for _, grp := range groups { - l = l + len(grp.Rules) + l += len(grp.Rules) } rules := make([]Rule, 0, l) @@ -31,8 +32,8 @@ func FlattenRules(groups []v1.RuleGroup) []Rule { for _, grp := range groups { for _, rl := range grp.Rules { - // For now we only care about AlertingRules - // since RecodingRules can simply be queried + // For now we only care about AlertingRules, + // since RecodingRules can simply be queried. if _, ok := rl.(v1.AlertingRule); ok { r.AlertingRule = rl.(v1.AlertingRule) rules = append(rules, r) diff --git a/internal/alert/alert_test.go b/internal/alert/alert_test.go index 32c7d20..697da24 100644 --- a/internal/alert/alert_test.go +++ b/internal/alert/alert_test.go @@ -1,11 +1,12 @@ package alert import ( + "testing" + "time" + "github.com/NETWAYS/go-check" v1 "github.com/prometheus/client_golang/api/prometheus/v1" "github.com/prometheus/common/model" - "testing" - "time" ) func TestGetStatus(t *testing.T) { diff --git a/internal/client/client.go b/internal/client/client.go index 88174d4..1dbd782 100644 --- a/internal/client/client.go +++ b/internal/client/client.go @@ -3,24 +3,25 @@ package client import ( "context" "fmt" - "github.com/NETWAYS/go-check" - "github.com/prometheus/client_golang/api" - v1 "github.com/prometheus/client_golang/api/prometheus/v1" "net/http" "net/url" "strings" + + "github.com/NETWAYS/go-check" + "github.com/prometheus/client_golang/api" + v1 "github.com/prometheus/client_golang/api/prometheus/v1" ) type Client struct { - Url string + URL string Client api.Client - Api v1.API + API v1.API RoundTripper http.RoundTripper } func NewClient(url string, rt http.RoundTripper) *Client { return &Client{ - Url: url, + URL: url, RoundTripper: rt, } } @@ -28,16 +29,16 @@ func NewClient(url string, rt http.RoundTripper) *Client { // nolint: gosec func (c *Client) Connect() error { cfg, err := api.NewClient(api.Config{ - Address: c.Url, + Address: c.URL, RoundTripper: c.RoundTripper, }) if err != nil { - return fmt.Errorf("Error creating client: %w\n", err) + return fmt.Errorf("error creating client: %w", err) } c.Client = cfg - c.Api = v1.NewAPI(c.Client) + c.API = v1.NewAPI(c.Client) return nil } @@ -46,11 +47,11 @@ func (c *Client) GetStatus(ctx context.Context, endpoint string) (returncode int // Parses the response from the Prometheus /healthy and /ready endpoint // Return: Exit Status Code, HTTP Status Code, HTTP Body, Error // Building the final URL with the endpoint parameter - u, _ := url.JoinPath(c.Url, "/-/", endpoint) - req, err := http.NewRequest(http.MethodGet, u, nil) + u, _ := url.JoinPath(c.URL, "/-/", endpoint) + req, err := http.NewRequestWithContext(ctx, http.MethodGet, u, nil) if err != nil { - e := fmt.Sprintf("Could not create request: %s", err) + e := fmt.Sprintf("could not create request: %s", err) return check.Unknown, 0, e, err } @@ -59,10 +60,12 @@ func (c *Client) GetStatus(ctx context.Context, endpoint string) (returncode int resp, b, err := c.Client.Do(ctx, req) if err != nil { - e := fmt.Sprintf("Could not get status: %s", err) + e := fmt.Sprintf("could not get status: %s", err) return check.Unknown, 0, e, err } + defer resp.Body.Close() + // Getting the response body respBody := strings.TrimSpace(string(b)) @@ -72,11 +75,11 @@ func (c *Client) GetStatus(ctx context.Context, endpoint string) (returncode int statusOk = "Prometheus Server is Ready." } - if resp.StatusCode == 200 && respBody == statusOk { + if resp.StatusCode == http.StatusOK && respBody == statusOk { return check.OK, resp.StatusCode, respBody, err } - if resp.StatusCode != 200 { + if resp.StatusCode != http.StatusOK { return check.Critical, resp.StatusCode, respBody, err } diff --git a/main.go b/main.go index dd09443..86b91c0 100644 --- a/main.go +++ b/main.go @@ -2,12 +2,13 @@ package main import ( "fmt" + "github.com/NETWAYS/check_prometheus/cmd" ) // nolint: gochecknoglobals var ( - // These get filled at build time with the proper vaules + // These get filled at build time with the proper vaules. version = "development" commit = "HEAD" date = "latest" @@ -17,7 +18,6 @@ func main() { cmd.Execute(buildVersion()) } -//goland:noinspection GoBoolExpressions func buildVersion() string { result := version