diff --git a/CHANGELOG.md b/CHANGELOG.md index fdd9853..41cdd3a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Change Log +## [5.0.2] - 2025-02-27 + +- Chore: Fix error source for parsing of invalid json response +- Chore: Update github.com/grafana/grafana-plugin-sdk-go to v0.268.0 + ## [5.0.1] - 2025-02-24 - Bug fix: Fixed host groups not showing in problems panel diff --git a/go.mod b/go.mod index fee8875..40a7aa9 100644 --- a/go.mod +++ b/go.mod @@ -5,11 +5,11 @@ go 1.23.5 require ( github.com/bitly/go-simplejson v0.5.1 github.com/dlclark/regexp2 v1.10.0 - github.com/grafana/grafana-plugin-sdk-go v0.266.0 + github.com/grafana/grafana-plugin-sdk-go v0.268.0 github.com/patrickmn/go-cache v2.1.0+incompatible github.com/prometheus/client_golang v1.20.5 github.com/stretchr/testify v1.10.0 - golang.org/x/net v0.34.0 + golang.org/x/net v0.35.0 gotest.tools v2.2.0+incompatible ) @@ -23,7 +23,7 @@ require ( github.com/chromedp/cdproto v0.0.0-20230914224007-a15a36ccbc2e // indirect github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/elazarl/goproxy v1.7.0 // indirect + github.com/elazarl/goproxy v1.7.1 // indirect github.com/fatih/color v1.15.0 // indirect github.com/getkin/kin-openapi v0.129.0 // indirect github.com/go-logr/logr v1.4.2 // indirect @@ -34,7 +34,7 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/flatbuffers v24.3.25+incompatible // indirect - github.com/google/go-cmp v0.6.0 // indirect + github.com/google/go-cmp v0.7.0 // indirect github.com/google/uuid v1.6.0 // indirect github.com/gorilla/mux v1.8.1 // indirect github.com/grafana/otel-profiling-go v0.5.1 // indirect @@ -93,13 +93,13 @@ require ( golang.org/x/mod v0.22.0 // indirect golang.org/x/sync v0.11.0 // indirect golang.org/x/sys v0.30.0 // indirect - golang.org/x/text v0.21.0 // indirect + golang.org/x/text v0.22.0 // indirect golang.org/x/tools v0.28.0 // indirect golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect google.golang.org/grpc v1.70.0 // indirect - google.golang.org/protobuf v1.36.4 // indirect + google.golang.org/protobuf v1.36.5 // indirect gopkg.in/fsnotify/fsnotify.v1 v1.4.7 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 28f1448..ea06ed2 100644 --- a/go.sum +++ b/go.sum @@ -29,8 +29,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dlclark/regexp2 v1.10.0 h1:+/GIL799phkJqYW+3YbOd8LCcbHzT0Pbo8zl70MHsq0= github.com/dlclark/regexp2 v1.10.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= -github.com/elazarl/goproxy v1.7.0 h1:EXv2nV4EjM60ZtsEVLYJG4oBXhDGutMKperpHsZ/v+0= -github.com/elazarl/goproxy v1.7.0/go.mod h1:X/5W/t+gzDyLfHW4DrMdpjqYjpXsURlBt9lpBDxZZZQ= +github.com/elazarl/goproxy v1.7.1 h1:1P7LPSxbqtNxusFnXclj6O56pjfq1xOQZ6a0mwwKUlY= +github.com/elazarl/goproxy v1.7.1/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= @@ -62,8 +62,9 @@ github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/flatbuffers v24.3.25+incompatible h1:CX395cjN9Kke9mmalRoL3d81AtFUxJM+yDthflgJGkI= github.com/google/flatbuffers v24.3.25+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -71,8 +72,8 @@ github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e h1:JKmoR8x90Iww1 github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= -github.com/grafana/grafana-plugin-sdk-go v0.266.0 h1:YP+iEpXH3HRX9Xo4NHjsrJhN2W7uVTtkLNzMHYbmiLI= -github.com/grafana/grafana-plugin-sdk-go v0.266.0/go.mod h1:bxkXrBQ4QSmOncsWdIOcpgP+M6wajQNMAPXlbWrqAWY= +github.com/grafana/grafana-plugin-sdk-go v0.268.0 h1:N8z+WNgEEqRe+y2ZXzVfJ2FKEK5fuo84ewAOQyJZODY= +github.com/grafana/grafana-plugin-sdk-go v0.268.0/go.mod h1:OuwS4c/JYgn0rr/w5zhJBpLo4gKm/vw15RsfpYAvK9Q= github.com/grafana/otel-profiling-go v0.5.1 h1:stVPKAFZSa7eGiqbYuG25VcqYksR6iWvF3YH66t4qL8= github.com/grafana/otel-profiling-go v0.5.1/go.mod h1:ftN/t5A/4gQI19/8MoWurBEtC6gFw8Dns1sJZ9W4Tls= github.com/grafana/pyroscope-go/godeltaprof v0.1.8 h1:iwOtYXeeVSAeYefJNaxDytgjKtUuKQbJqgAIjlnicKg= @@ -260,8 +261,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= -golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= +golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= +golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -283,8 +284,8 @@ golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= -golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= +golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= @@ -305,8 +306,8 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1: google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50= google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= -google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= -google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= +google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/package.json b/package.json index 90c36de..a26ffff 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "grafana-zabbix", - "version": "5.0.1", + "version": "5.0.2", "description": "Zabbix plugin for Grafana", "homepage": "http://grafana-zabbix.org", "bugs": { diff --git a/pkg/datasource/datasource.go b/pkg/datasource/datasource.go index 2ed8042..9b17dc7 100644 --- a/pkg/datasource/datasource.go +++ b/pkg/datasource/datasource.go @@ -117,23 +117,23 @@ func (ds *ZabbixDatasource) QueryData(ctx context.Context, req *backend.QueryDat query, err := ReadQuery(q) ds.logger.Debug("DS query", "query", q) if err != nil { - res.Error = err + res = backend.ErrorResponseWithErrorSource(err) } else if query.QueryType == MODE_METRICS { frames, err := zabbixDS.queryNumericItems(ctx, &query) if err != nil { - res.Error = err + res = backend.ErrorResponseWithErrorSource(err) } else { res.Frames = append(res.Frames, frames...) } } else if query.QueryType == MODE_ITEMID { frames, err := zabbixDS.queryItemIdData(ctx, &query) if err != nil { - res.Error = err + res = backend.ErrorResponseWithErrorSource(err) } else { res.Frames = append(res.Frames, frames...) } } else { - res.Error = backend.DownstreamError(ErrNonMetricQueryNotSupported) + res = backend.ErrorResponseWithErrorSource(backend.DownstreamError(ErrNonMetricQueryNotSupported)) } qdr.Responses[q.RefID] = res } diff --git a/pkg/datasource/models.go b/pkg/datasource/models.go index 6f3cc1b..af6d837 100644 --- a/pkg/datasource/models.go +++ b/pkg/datasource/models.go @@ -118,13 +118,13 @@ func ReadQuery(query backend.DataQuery) (QueryModel, error) { Interval: query.Interval, } if err := json.Unmarshal(query.JSON, &model); err != nil { - return model, fmt.Errorf("could not read query: %w", err) + return model, backend.DownstreamError(fmt.Errorf("could not read query: %w", err)) } if model.QueryType == "" { queryJSON, err := simplejson.NewJson(query.JSON) if err != nil { - return model, fmt.Errorf("could not read query JSON: %w", err) + return model, backend.DownstreamError(fmt.Errorf("could not read query JSON: %w", err)) } queryType, err := queryJSON.Get("queryType").Int64() diff --git a/pkg/zabbix/zabbix.go b/pkg/zabbix/zabbix.go index 5eed99f..dcb291e 100644 --- a/pkg/zabbix/zabbix.go +++ b/pkg/zabbix/zabbix.go @@ -125,7 +125,7 @@ func (zabbix *Zabbix) Authenticate(ctx context.Context) error { } err = zabbix.api.AuthenticateWithToken(ctx, token) if err != nil { - zabbix.logger.Error("Zabbix authentication error", "error", err) + zabbix.logger.Error("Zabbix authentication token error", "error", err) return err } zabbix.logger.Debug("Using API token for authentication") diff --git a/pkg/zabbixapi/zabbix_api.go b/pkg/zabbixapi/zabbix_api.go index 9f4bab0..e64f8dc 100644 --- a/pkg/zabbixapi/zabbix_api.go +++ b/pkg/zabbixapi/zabbix_api.go @@ -196,7 +196,8 @@ func isDeprecatedUserParamError(err error) bool { func handleAPIResult(response []byte) (*simplejson.Json, error) { jsonResp, err := simplejson.NewJson([]byte(response)) if err != nil { - return nil, err + // Response is not valid JSON + return nil, backend.DownstreamError(err) } if errJSON, isError := jsonResp.CheckGet("error"); isError { errMessage := fmt.Errorf("%s %s", errJSON.Get("message").MustString(), errJSON.Get("data").MustString()) diff --git a/pkg/zabbixapi/zabbix_api_test.go b/pkg/zabbixapi/zabbix_api_test.go index 77cf1a2..177fc4c 100644 --- a/pkg/zabbixapi/zabbix_api_test.go +++ b/pkg/zabbixapi/zabbix_api_test.go @@ -71,3 +71,54 @@ func TestZabbixAPI(t *testing.T) { }) } } + +func TestHandleAPIResult(t *testing.T) { + tests := []struct { + name string + response string + expectedData interface{} + expectedError string + isDownstream bool + }{ + { + name: "Valid JSON with result", + response: `{"result": {"data": "test"}}`, + expectedData: map[string]interface{}{"data": "test"}, + }, + { + name: "Invalid JSON", + response: `{"result": invalid}`, + expectedError: "invalid character 'i' looking for beginning of value", + isDownstream: true, + }, + { + name: "API error response", + response: `{"error": {"message": "Authentication failed", "data": "Session terminated"}}`, + expectedError: "Authentication failed Session terminated", + isDownstream: true, + }, + { + name: "Empty result", + response: `{"result": []}`, + expectedData: []interface{}{}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result, err := handleAPIResult([]byte(tt.response)) + + if tt.expectedError != "" { + assert.Error(t, err) + assert.Equal(t, tt.expectedError, err.Error()) + if tt.isDownstream { + assert.True(t, backend.IsDownstreamError(err), "error should be a downstream error") + } + return + } + + assert.NoError(t, err) + assert.Equal(t, tt.expectedData, result.Interface()) + }) + } +}