From eaf94d3a5ed77f7671585ddcb44492e9e8caea6e Mon Sep 17 00:00:00 2001 From: SuperQ Date: Tue, 5 Oct 2021 13:21:42 +0200 Subject: [PATCH] Update build * Update to Go 1.17. * Update modules. * Enable golint CI test. * Fixup golint issues. Signed-off-by: SuperQ --- .circleci/config.yml | 2 +- .golangci.yml | 2 ++ .promu.yml | 2 +- cmd/main.go | 10 +++++----- cmd/main_test.go | 32 ++++++++++++++++---------------- config/config.go | 4 ++-- exporter/collector.go | 42 +++++++++++++++++++++--------------------- exporter/util.go | 40 +++++++++++++++++++--------------------- go.mod | 4 ++-- go.sum | 14 +++++++------- 10 files changed, 76 insertions(+), 76 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 7ff284f..be78a97 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -8,7 +8,7 @@ executors: # This must match .promu.yml. golang: docker: - - image: circleci/golang:1.16 + - image: circleci/golang:1.17 jobs: test: diff --git a/.golangci.yml b/.golangci.yml index d050972..9d7f0ee 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,4 +1,6 @@ linters: + enable: + - golint disable: # Disable soon to deprecated[1] linters that lead to false # positives when build tags disable certain files[2] diff --git a/.promu.yml b/.promu.yml index 7cf6a9c..4860544 100644 --- a/.promu.yml +++ b/.promu.yml @@ -1,6 +1,6 @@ go: # This must match .circle/config.yml. - version: 1.16 + version: 1.17 repository: path: github.com/prometheus-community/json_exporter build: diff --git a/cmd/main.go b/cmd/main.go index b03b02a..3f4bcb1 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -58,11 +58,11 @@ func Run() { level.Error(logger).Log("msg", "Error loading config", "err", err) os.Exit(1) } - configJson, err := json.Marshal(config) + configJSON, err := json.Marshal(config) if err != nil { level.Error(logger).Log("msg", "Failed to marshal config to JSON", "err", err) } - level.Info(logger).Log("msg", "Loaded config file", "config", string(configJson)) + level.Info(logger).Log("msg", "Loaded config file", "config", string(configJSON)) if *configCheck { os.Exit(0) @@ -93,7 +93,7 @@ func probeHandler(w http.ResponseWriter, r *http.Request, logger log.Logger, con level.Error(logger).Log("msg", "Failed to create metrics list from config", "err", err) } - jsonMetricCollector := exporter.JsonMetricCollector{JsonMetrics: metrics} + jsonMetricCollector := exporter.JSONMetricCollector{JSONMetrics: metrics} jsonMetricCollector.Logger = logger target := r.URL.Query().Get("target") @@ -102,8 +102,8 @@ func probeHandler(w http.ResponseWriter, r *http.Request, logger log.Logger, con return } - fetcher := exporter.NewJsonFetcher(ctx, logger, config, r.URL.Query()) - data, err := fetcher.FetchJson(target) + fetcher := exporter.NewJSONFetcher(ctx, logger, config, r.URL.Query()) + data, err := fetcher.FetchJSON(target) if err != nil { http.Error(w, "Failed to fetch JSON response. TARGET: "+target+", ERROR: "+err.Error(), http.StatusServiceUnavailable) return diff --git a/cmd/main_test.go b/cmd/main_test.go index 595b9ae..6bb03d8 100644 --- a/cmd/main_test.go +++ b/cmd/main_test.go @@ -224,29 +224,29 @@ func TestHTTPHeaders(t *testing.T) { // Test is the body template is correctly rendered func TestBodyPostTemplate(t *testing.T) { bodyTests := []struct { - Body config.ConfigBody + Body config.Body ShouldSucceed bool Result string }{ { - Body: config.ConfigBody{Content: "something static like pi, 3.14"}, + Body: config.Body{Content: "something static like pi, 3.14"}, ShouldSucceed: true, }, { - Body: config.ConfigBody{Content: "arbitrary dynamic value pass: {{ randInt 12 30 }}", Templatize: false}, + Body: config.Body{Content: "arbitrary dynamic value pass: {{ randInt 12 30 }}", Templatize: false}, ShouldSucceed: true, }, { - Body: config.ConfigBody{Content: "arbitrary dynamic value fail: {{ randInt 12 30 }}", Templatize: true}, + Body: config.Body{Content: "arbitrary dynamic value fail: {{ randInt 12 30 }}", Templatize: true}, ShouldSucceed: false, }, { - Body: config.ConfigBody{Content: "templatized mutated value: {{ upper `hello` }} is now all caps", Templatize: true}, + Body: config.Body{Content: "templatized mutated value: {{ upper `hello` }} is now all caps", Templatize: true}, Result: "templatized mutated value: HELLO is now all caps", ShouldSucceed: true, }, { - Body: config.ConfigBody{Content: "value should be {{ lower `All Small` | trunc 3 }}", Templatize: true}, + Body: config.Body{Content: "value should be {{ lower `All Small` | trunc 3 }}", Templatize: true}, Result: "value should be all", ShouldSucceed: true, }, @@ -283,58 +283,58 @@ func TestBodyPostTemplate(t *testing.T) { // Test is the query parameters are correctly replaced in the provided body template func TestBodyPostQuery(t *testing.T) { bodyTests := []struct { - Body config.ConfigBody + Body config.Body ShouldSucceed bool Result string QueryParams map[string]string }{ { - Body: config.ConfigBody{Content: "pi has {{ .piValue | first }} value", Templatize: true}, + Body: config.Body{Content: "pi has {{ .piValue | first }} value", Templatize: true}, ShouldSucceed: true, Result: "pi has 3.14 value", QueryParams: map[string]string{"piValue": "3.14"}, }, { - Body: config.ConfigBody{Content: `{ "pi": "{{ .piValue | first }}" }`, Templatize: true}, + Body: config.Body{Content: `{ "pi": "{{ .piValue | first }}" }`, Templatize: true}, ShouldSucceed: true, Result: `{ "pi": "3.14" }`, QueryParams: map[string]string{"piValue": "3.14"}, }, { - Body: config.ConfigBody{Content: "pi has {{ .anotherQuery | first }} value", Templatize: true}, + Body: config.Body{Content: "pi has {{ .anotherQuery | first }} value", Templatize: true}, ShouldSucceed: true, Result: "pi has very high value", QueryParams: map[string]string{"piValue": "3.14", "anotherQuery": "very high"}, }, { - Body: config.ConfigBody{Content: "pi has {{ .piValue }} value", Templatize: true}, + Body: config.Body{Content: "pi has {{ .piValue }} value", Templatize: true}, ShouldSucceed: false, QueryParams: map[string]string{"piValue": "3.14", "anotherQuery": "dummy value"}, }, { - Body: config.ConfigBody{Content: "pi has {{ .piValue }} value", Templatize: true}, + Body: config.Body{Content: "pi has {{ .piValue }} value", Templatize: true}, ShouldSucceed: true, Result: "pi has [3.14] value", QueryParams: map[string]string{"piValue": "3.14", "anotherQuery": "dummy value"}, }, { - Body: config.ConfigBody{Content: "value of {{ upper `pi` | repeat 3 }} is {{ .anotherQuery | first }}", Templatize: true}, + Body: config.Body{Content: "value of {{ upper `pi` | repeat 3 }} is {{ .anotherQuery | first }}", Templatize: true}, ShouldSucceed: true, Result: "value of PIPIPI is dummy value", QueryParams: map[string]string{"piValue": "3.14", "anotherQuery": "dummy value"}, }, { - Body: config.ConfigBody{Content: "pi has {{ .piValue }} value", Templatize: true}, + Body: config.Body{Content: "pi has {{ .piValue }} value", Templatize: true}, ShouldSucceed: true, Result: "pi has [] value", }, { - Body: config.ConfigBody{Content: "pi has {{ .piValue | first }} value", Templatize: true}, + Body: config.Body{Content: "pi has {{ .piValue | first }} value", Templatize: true}, ShouldSucceed: true, Result: "pi has value", }, { - Body: config.ConfigBody{Content: "value of pi is 3.14", Templatize: true}, + Body: config.Body{Content: "value of pi is 3.14", Templatize: true}, ShouldSucceed: true, }, } diff --git a/config/config.go b/config/config.go index eb465ec..5d320a6 100644 --- a/config/config.go +++ b/config/config.go @@ -42,10 +42,10 @@ type Config struct { Headers map[string]string `yaml:"headers,omitempty"` Metrics []Metric `yaml:"metrics"` HTTPClientConfig pconfig.HTTPClientConfig `yaml:"http_client_config,omitempty"` - Body ConfigBody `yaml:"body,omitempty"` + Body Body `yaml:"body,omitempty"` } -type ConfigBody struct { +type Body struct { Content string `yaml:"content"` Templatize bool `yaml:"templatize,omitempty"` } diff --git a/exporter/collector.go b/exporter/collector.go index 5941f1d..7d61bf7 100644 --- a/exporter/collector.go +++ b/exporter/collector.go @@ -23,31 +23,31 @@ import ( "k8s.io/client-go/util/jsonpath" ) -type JsonMetricCollector struct { - JsonMetrics []JsonMetric +type JSONMetricCollector struct { + JSONMetrics []JSONMetric Data []byte Logger log.Logger } -type JsonMetric struct { +type JSONMetric struct { Desc *prometheus.Desc - KeyJsonPath string - ValueJsonPath string - LabelsJsonPaths []string + KeyJSONPath string + ValueJSONPath string + LabelsJSONPaths []string } -func (mc JsonMetricCollector) Describe(ch chan<- *prometheus.Desc) { - for _, m := range mc.JsonMetrics { +func (mc JSONMetricCollector) Describe(ch chan<- *prometheus.Desc) { + for _, m := range mc.JSONMetrics { ch <- m.Desc } } -func (mc JsonMetricCollector) Collect(ch chan<- prometheus.Metric) { - for _, m := range mc.JsonMetrics { - if m.ValueJsonPath == "" { // ScrapeType is 'value' - value, err := extractValue(mc.Logger, mc.Data, m.KeyJsonPath, false) +func (mc JSONMetricCollector) Collect(ch chan<- prometheus.Metric) { + for _, m := range mc.JSONMetrics { + if m.ValueJSONPath == "" { // ScrapeType is 'value' + value, err := extractValue(mc.Logger, mc.Data, m.KeyJSONPath, false) if err != nil { - level.Error(mc.Logger).Log("msg", "Failed to extract value for metric", "path", m.KeyJsonPath, "err", err, "metric", m.Desc) + level.Error(mc.Logger).Log("msg", "Failed to extract value for metric", "path", m.KeyJSONPath, "err", err, "metric", m.Desc) continue } @@ -57,14 +57,14 @@ func (mc JsonMetricCollector) Collect(ch chan<- prometheus.Metric) { m.Desc, prometheus.UntypedValue, floatValue, - extractLabels(mc.Logger, mc.Data, m.LabelsJsonPaths)..., + extractLabels(mc.Logger, mc.Data, m.LabelsJSONPaths)..., ) } else { - level.Error(mc.Logger).Log("msg", "Failed to convert extracted value to float64", "path", m.KeyJsonPath, "value", value, "err", err, "metric", m.Desc) + level.Error(mc.Logger).Log("msg", "Failed to convert extracted value to float64", "path", m.KeyJSONPath, "value", value, "err", err, "metric", m.Desc) continue } } else { // ScrapeType is 'object' - values, err := extractValue(mc.Logger, mc.Data, m.KeyJsonPath, true) + values, err := extractValue(mc.Logger, mc.Data, m.KeyJSONPath, true) if err != nil { level.Error(mc.Logger).Log("msg", "Failed to extract json objects for metric", "err", err, "metric", m.Desc) continue @@ -75,12 +75,12 @@ func (mc JsonMetricCollector) Collect(ch chan<- prometheus.Metric) { for _, data := range jsonData { jdata, err := json.Marshal(data) if err != nil { - level.Error(mc.Logger).Log("msg", "Failed to marshal data to json", "path", m.ValueJsonPath, "err", err, "metric", m.Desc, "data", data) + level.Error(mc.Logger).Log("msg", "Failed to marshal data to json", "path", m.ValueJSONPath, "err", err, "metric", m.Desc, "data", data) continue } - value, err := extractValue(mc.Logger, jdata, m.ValueJsonPath, false) + value, err := extractValue(mc.Logger, jdata, m.ValueJSONPath, false) if err != nil { - level.Error(mc.Logger).Log("msg", "Failed to extract value for metric", "path", m.ValueJsonPath, "err", err, "metric", m.Desc) + level.Error(mc.Logger).Log("msg", "Failed to extract value for metric", "path", m.ValueJSONPath, "err", err, "metric", m.Desc) continue } @@ -89,10 +89,10 @@ func (mc JsonMetricCollector) Collect(ch chan<- prometheus.Metric) { m.Desc, prometheus.UntypedValue, floatValue, - extractLabels(mc.Logger, jdata, m.LabelsJsonPaths)..., + extractLabels(mc.Logger, jdata, m.LabelsJSONPaths)..., ) } else { - level.Error(mc.Logger).Log("msg", "Failed to convert extracted value to float64", "path", m.ValueJsonPath, "value", value, "err", err, "metric", m.Desc) + level.Error(mc.Logger).Log("msg", "Failed to convert extracted value to float64", "path", m.ValueJSONPath, "value", value, "err", err, "metric", m.Desc) continue } } diff --git a/exporter/util.go b/exporter/util.go index 00fd8b5..aa3e898 100644 --- a/exporter/util.go +++ b/exporter/util.go @@ -39,24 +39,22 @@ func MakeMetricName(parts ...string) string { } func SanitizeValue(s string) (float64, error) { + var err error var value float64 var resultErr string - if value, err := strconv.ParseFloat(s, 64); err == nil { + if value, err = strconv.ParseFloat(s, 64); err == nil { return value, nil - } else { - resultErr = fmt.Sprintf("%s", err) } + resultErr = fmt.Sprintf("%s", err) if boolValue, err := strconv.ParseBool(s); err == nil { if boolValue { return 1.0, nil - } else { - return 0.0, nil } - } else { - resultErr = resultErr + "; " + fmt.Sprintf("%s", err) + return 0.0, nil } + resultErr = resultErr + "; " + fmt.Sprintf("%s", err) if s == "" { return math.NaN(), nil @@ -64,8 +62,8 @@ func SanitizeValue(s string) (float64, error) { return value, fmt.Errorf(resultErr) } -func CreateMetricsList(c config.Config) ([]JsonMetric, error) { - var metrics []JsonMetric +func CreateMetricsList(c config.Config) ([]JSONMetric, error) { + var metrics []JSONMetric for _, metric := range c.Metrics { switch metric.Type { case config.ValueScrape: @@ -74,15 +72,15 @@ func CreateMetricsList(c config.Config) ([]JsonMetric, error) { variableLabels = append(variableLabels, k) variableLabelsValues = append(variableLabelsValues, v) } - jsonMetric := JsonMetric{ + jsonMetric := JSONMetric{ Desc: prometheus.NewDesc( metric.Name, metric.Help, variableLabels, nil, ), - KeyJsonPath: metric.Path, - LabelsJsonPaths: variableLabelsValues, + KeyJSONPath: metric.Path, + LabelsJSONPaths: variableLabelsValues, } metrics = append(metrics, jsonMetric) case config.ObjectScrape: @@ -93,16 +91,16 @@ func CreateMetricsList(c config.Config) ([]JsonMetric, error) { variableLabels = append(variableLabels, k) variableLabelsValues = append(variableLabelsValues, v) } - jsonMetric := JsonMetric{ + jsonMetric := JSONMetric{ Desc: prometheus.NewDesc( name, metric.Help, variableLabels, nil, ), - KeyJsonPath: metric.Path, - ValueJsonPath: valuePath, - LabelsJsonPaths: variableLabelsValues, + KeyJSONPath: metric.Path, + ValueJSONPath: valuePath, + LabelsJSONPaths: variableLabelsValues, } metrics = append(metrics, jsonMetric) } @@ -113,7 +111,7 @@ func CreateMetricsList(c config.Config) ([]JsonMetric, error) { return metrics, nil } -type jsonFetcher struct { +type JSONFetcher struct { config config.Config ctx context.Context logger log.Logger @@ -121,9 +119,9 @@ type jsonFetcher struct { body io.Reader } -func NewJsonFetcher(ctx context.Context, logger log.Logger, c config.Config, tplValues url.Values) *jsonFetcher { +func NewJSONFetcher(ctx context.Context, logger log.Logger, c config.Config, tplValues url.Values) *JSONFetcher { method, body := renderBody(logger, c.Body, tplValues) - return &jsonFetcher{ + return &JSONFetcher{ config: c, ctx: ctx, logger: logger, @@ -132,7 +130,7 @@ func NewJsonFetcher(ctx context.Context, logger log.Logger, c config.Config, tpl } } -func (f *jsonFetcher) FetchJson(endpoint string) ([]byte, error) { +func (f *JSONFetcher) FetchJSON(endpoint string) ([]byte, error) { httpClientConfig := f.config.HTTPClientConfig client, err := pconfig.NewClientFromConfig(httpClientConfig, "fetch_json", pconfig.WithKeepAlivesDisabled(), pconfig.WithHTTP2Disabled()) if err != nil { @@ -181,7 +179,7 @@ func (f *jsonFetcher) FetchJson(endpoint string) ([]byte, error) { // Use the configured template to render the body if enabled // Do not treat template errors as fatal, on such errors just log them // and continue with static body content -func renderBody(logger log.Logger, body config.ConfigBody, tplValues url.Values) (method string, br io.Reader) { +func renderBody(logger log.Logger, body config.Body, tplValues url.Values) (method string, br io.Reader) { method = "POST" if body.Content == "" { return "GET", nil diff --git a/go.mod b/go.mod index cc6988e..ce5969c 100644 --- a/go.mod +++ b/go.mod @@ -6,11 +6,11 @@ require ( github.com/Masterminds/sprig/v3 v3.2.2 github.com/go-kit/log v0.2.0 github.com/prometheus/client_golang v1.11.0 - github.com/prometheus/common v0.30.0 + github.com/prometheus/common v0.31.1 github.com/prometheus/exporter-toolkit v0.6.1 gopkg.in/alecthomas/kingpin.v2 v2.2.6 gopkg.in/yaml.v2 v2.4.0 - k8s.io/client-go v0.22.0 + k8s.io/client-go v0.22.2 ) exclude ( diff --git a/go.sum b/go.sum index 27b5bfc..88d735e 100644 --- a/go.sum +++ b/go.sum @@ -248,8 +248,8 @@ github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8 github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/common v0.29.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.30.0 h1:JEkYlQnpzrzQFxi6gnukFPdQ+ac82oRhzMcIduJu/Ug= -github.com/prometheus/common v0.30.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= +github.com/prometheus/common v0.31.1 h1:d18hG4PkHnNAKNMOmFuXFaiY8Us0nird/2m60uS1AMs= +github.com/prometheus/common v0.31.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/exporter-toolkit v0.6.1 h1:Aqk75wQD92N9CqmTlZwjKwq6272nOGrWIbc8Z7+xQO0= github.com/prometheus/exporter-toolkit v0.6.1/go.mod h1:ZUBIj498ePooX9t/2xtDjeQYwvRpiPP2lh5u4iblj2g= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= @@ -594,15 +594,15 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.22.0/go.mod h1:0AoXXqst47OI/L0oGKq9DG61dvGRPXs7X4/B7KyjBCU= -k8s.io/apimachinery v0.22.0/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0= -k8s.io/client-go v0.22.0 h1:sD6o9O6tCwUKCENw8v+HFsuAbq2jCu8cWC61/ydwA50= -k8s.io/client-go v0.22.0/go.mod h1:GUjIuXR5PiEv/RVK5OODUsm6eZk7wtSWZSaSJbpFdGg= +k8s.io/api v0.22.2/go.mod h1:y3ydYpLJAaDI+BbSe2xmGcqxiWHmWjkEeIbiwHvnPR8= +k8s.io/apimachinery v0.22.2/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0= +k8s.io/client-go v0.22.2 h1:DaSQgs02aCC1QcwUdkKZWOeaVsQjYvWv8ZazcZ6JcHc= +k8s.io/client-go v0.22.2/go.mod h1:sAlhrkVDf50ZHx6z4K0S40wISNTarf1r800F+RlCF6U= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= -k8s.io/utils v0.0.0-20210707171843-4b05e18ac7d9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=