diff --git a/CHANGELOG.md b/CHANGELOG.md index 458f2e7..babbe40 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Change Log +## [4.6.1] - 2025-01-07 + +- Bug fix: Fixed a compatibility issue with zabbix 7. ( Fixes [#1935](https://github.com/grafana/grafana-zabbix/issues/1935) ) + ## [4.6.0] - 2024-12-16 - Feature: Added support for Zabbix 7. ( Fixes [#1914](https://github.com/grafana/grafana-zabbix/issues/1914) ) diff --git a/package.json b/package.json index 5bff7fb..fd6a00c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "grafana-zabbix", - "version": "4.6.0", + "version": "4.6.1", "description": "Zabbix plugin for Grafana", "homepage": "http://grafana-zabbix.org", "bugs": { diff --git a/pkg/zabbix/methods.go b/pkg/zabbix/methods.go index 5f98dd9..53f263e 100644 --- a/pkg/zabbix/methods.go +++ b/pkg/zabbix/methods.go @@ -494,13 +494,7 @@ func (ds *Zabbix) GetAllGroups(ctx context.Context) ([]Group, error) { params := ZabbixAPIParams{ "output": []string{"name", "groupid"}, "sortfield": "name", - } - - // Zabbix v7.0 and later removed `real_hosts` parameter and replaced it with `with_hosts` - if ds.version < 70 { - params["real_hosts"] = true - } else { - params["with_hosts"] = true + "with_hosts": true, } result, err := ds.Request(ctx, &ZabbixAPIRequest{Method: "hostgroup.get", Params: params}) diff --git a/pkg/zabbixapi/migration.go b/pkg/zabbixapi/migration.go new file mode 100644 index 0000000..1663acc --- /dev/null +++ b/pkg/zabbixapi/migration.go @@ -0,0 +1,84 @@ +package zabbixapi + +import ( + "context" + + "github.com/grafana/grafana-plugin-sdk-go/backend/log" +) + +func normalizeParams(ctx context.Context, method string, params ZabbixAPIParams, version int) ZabbixAPIParams { + logger := log.New().FromContext(ctx) + logger.Debug("performing query params migration", "method", method, "version", version) + switch method { + case "trigger.get": + newKey := "selectHostGroups" + deprecatedKey := "selectGroups" + deprecatedKeyValue, deprecatedKeyExists := params[deprecatedKey] + newKeyValue, newKeyExists := params[newKey] + if version < 70 && newKeyExists { + if deprecatedKeyExists { + delete(params, newKey) + } + if !deprecatedKeyExists { + params[deprecatedKey] = newKeyValue + delete(params, newKey) + } + } + if version >= 70 && deprecatedKeyExists { + if newKeyExists { + delete(params, deprecatedKey) + } + if !newKeyExists { + params[newKey] = deprecatedKeyValue + delete(params, deprecatedKey) + } + } + case "event.get": + newKey := "selectAcknowledges" + deprecatedKey := "select_acknowledges" + deprecatedKeyValue, deprecatedKeyExists := params[deprecatedKey] + newKeyValue, newKeyExists := params[newKey] + if version < 70 && newKeyExists { + if deprecatedKeyExists { + delete(params, newKey) + } + if !deprecatedKeyExists { + params[deprecatedKey] = newKeyValue + delete(params, newKey) + } + } + if version >= 70 && deprecatedKeyExists { + if newKeyExists { + delete(params, deprecatedKey) + } + if !newKeyExists { + params[newKey] = deprecatedKeyValue + delete(params, deprecatedKey) + } + } + case "hostgroup.get": + newKey := "with_hosts" + deprecatedKey := "real_hosts" + deprecatedKeyValue, deprecatedKeyExists := params[deprecatedKey] + newKeyValue, newKeyExists := params[newKey] + if version < 70 && newKeyExists { + if deprecatedKeyExists { + delete(params, newKey) + } + if !deprecatedKeyExists { + params[deprecatedKey] = newKeyValue + delete(params, newKey) + } + } + if version >= 70 && deprecatedKeyExists { + if newKeyExists { + delete(params, deprecatedKey) + } + if !newKeyExists { + params[newKey] = deprecatedKeyValue + delete(params, deprecatedKey) + } + } + } + return params +} diff --git a/pkg/zabbixapi/zabbix_api.go b/pkg/zabbixapi/zabbix_api.go index f0c9bca..72bb8fa 100644 --- a/pkg/zabbixapi/zabbix_api.go +++ b/pkg/zabbixapi/zabbix_api.go @@ -92,7 +92,7 @@ func (api *ZabbixAPI) request(ctx context.Context, method string, params ZabbixA "jsonrpc": "2.0", "id": 2, "method": method, - "params": params, + "params": normalizeParams(ctx, method, params, version), } // Zabbix v7.2 and later deprecated `auth` parameter and replaced it with using Auth header @@ -115,7 +115,7 @@ func (api *ZabbixAPI) request(ctx context.Context, method string, params ZabbixA if auth != "" { req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", auth)) - } + } req.Header.Set("Content-Type", "application/json") req.Header.Set("User-Agent", "Grafana/grafana-zabbix") diff --git a/src/datasource/zabbix/connectors/zabbix_api/zabbixAPIConnector.ts b/src/datasource/zabbix/connectors/zabbix_api/zabbixAPIConnector.ts index 58798ad..055413f 100644 --- a/src/datasource/zabbix/connectors/zabbix_api/zabbixAPIConnector.ts +++ b/src/datasource/zabbix/connectors/zabbix_api/zabbixAPIConnector.ts @@ -9,6 +9,7 @@ import { APIExecuteScriptResponse, JSONRPCError, ZBXScript } from './types'; import { BackendSrvRequest, getBackendSrv } from '@grafana/runtime'; import { rangeUtil } from '@grafana/data'; import { parseItemTag } from '../../../utils'; +import { zabbixMethodName } from 'datasource/zabbix/types'; const DEFAULT_ZABBIX_VERSION = '3.0.0'; @@ -47,7 +48,7 @@ export class ZabbixAPIConnector { // Core method wrappers // ////////////////////////// - request(method: string, params?: any) { + request(method: zabbixMethodName, params?: any) { if (!this.version) { return this.initVersion().then(() => this.request(method, params)); } @@ -55,7 +56,7 @@ export class ZabbixAPIConnector { return this.backendAPIRequest(method, params); } - async backendAPIRequest(method: string, params: any = {}) { + async backendAPIRequest(method: zabbixMethodName, params: any = {}) { const requestOptions: BackendSrvRequest = { url: this.backendAPIUrl, method: 'POST', @@ -142,15 +143,9 @@ export class ZabbixAPIConnector { const params = { output: ['name', 'groupid'], sortfield: 'name', + [getParamsKeyByVersion('with_hosts', this.version, 'hostgroup.get')]: true, }; - // Zabbix v7.0 and later deprecated `real_hosts` parameter and replaced it with `with_hosts` - if (semver.gte(this.version, '7.0.0')) { - params['with_hosts'] = true; - } else { - params['real_hosts'] = true; - } - return this.request('hostgroup.get', params); } @@ -545,7 +540,7 @@ export class ZabbixAPIConnector { expandExpression: true, monitored: true, skipDependent: true, - selectGroups: ['name', 'groupid'], + [getParamsKeyByVersion('selectHostGroups', this.version, 'trigger.get')]: ['name', 'groupid'], selectHosts: ['hostid', 'name', 'host', 'maintenance_status', 'description'], selectItems: ['itemid', 'name', 'key_', 'lastvalue'], // selectLastEvent: 'extend', @@ -580,7 +575,7 @@ export class ZabbixAPIConnector { filter: { value: 1, }, - selectGroups: ['groupid', 'name'], + [getParamsKeyByVersion('selectHostGroups', this.version, 'trigger.get')]: ['groupid', 'name'], selectHosts: ['hostid', 'name', 'host', 'maintenance_status'], selectItems: ['itemid', 'name', 'key_', 'lastvalue'], selectLastEvent: 'extend', @@ -619,9 +614,9 @@ export class ZabbixAPIConnector { time_till: timeTo, objectids: objectids, selectHosts: 'extend', + [getParamsKeyByVersion('selectAcknowledges', this.version, 'event.get')]: 'extend', value: showEvents, }; - params[getSelectAcknowledgesKey(this.version)] = 'extend'; if (limit) { params.limit = limit; @@ -646,12 +641,12 @@ export class ZabbixAPIConnector { sortfield: ['eventid'], sortorder: 'DESC', selectTags: 'extend', + [getParamsKeyByVersion('selectAcknowledges', this.version, 'event.get')]: 'extend', selectSuppressionData: ['maintenanceid', 'suppress_until'], groupids, hostids, applicationids, }; - params[getSelectAcknowledgesKey(this.version)] = 'extend'; if (limit) { params.limit = limit; @@ -682,12 +677,11 @@ export class ZabbixAPIConnector { eventids: eventids, preservekeys: true, selectTags: 'extend', + [getParamsKeyByVersion('selectAcknowledges', this.version, 'event.get')]: 'extend', sortfield: 'clock', sortorder: 'DESC', }; - params[getSelectAcknowledgesKey(this.version)] = 'extend'; - return this.request('event.get', params); } @@ -708,8 +702,8 @@ export class ZabbixAPIConnector { preservekeys: true, sortfield: 'clock', sortorder: 'DESC', + [getParamsKeyByVersion('selectAcknowledges', this.version, 'event.get')]: 'extend', }; - params[getSelectAcknowledgesKey(this.version)] = 'extend'; return this.request('event.get', params).then((events) => { return _.filter(events, (event) => event.acknowledges.length); @@ -753,7 +747,7 @@ export class ZabbixAPIConnector { monitored: true, skipDependent: true, selectLastEvent: 'extend', - selectGroups: 'extend', + [getParamsKeyByVersion('selectHostGroups', this.version, 'trigger.get')]: 'extend', selectHosts: ['hostid', 'host', 'name'], }; @@ -801,7 +795,7 @@ export class ZabbixAPIConnector { monitored: true, skipDependent: true, selectLastEvent: 'extend', - selectGroups: 'extend', + [getParamsKeyByVersion('selectHostGroups', this.version, 'trigger.get')]: 'extend', selectHosts: ['host', 'name'], selectItems: ['name', 'key_'], }; @@ -851,7 +845,7 @@ export class ZabbixAPIConnector { monitored: true, skipDependent: true, selectLastEvent: 'extend', - selectGroups: 'extend', + [getParamsKeyByVersion('selectHostGroups', this.version, 'trigger.get')]: 'extend', selectHosts: ['host', 'name'], selectItems: ['name', 'key_'], }; @@ -984,6 +978,23 @@ export class ZabbixAPIError { } } -function getSelectAcknowledgesKey(version: string) { - return semver.gte(version, '7.0.0') ? 'selectAcknowledges' : 'select_acknowledges'; +function getParamsKeyByVersion( + key: 'selectAcknowledges' | 'with_hosts' | 'selectHostGroups', + version: string, + event_name?: zabbixMethodName +): string { + if (!version) { + console.log(`Version not detected`, 'key', key, 'event_name', event_name); + version = '0.0.0'; + } + switch (key) { + case 'selectHostGroups': + return semver.gte(version, '7.0.0') ? 'selectHostGroups' : 'selectGroups'; + case 'selectAcknowledges': + return semver.gte(version, '7.0.0') ? 'selectAcknowledges' : 'select_acknowledges'; + case 'with_hosts': + return semver.gte(version, '7.0.0') ? 'with_hosts' : 'real_hosts'; + default: + return ''; + } } diff --git a/src/datasource/zabbix/types.ts b/src/datasource/zabbix/types.ts index 32c2166..8e09d78 100644 --- a/src/datasource/zabbix/types.ts +++ b/src/datasource/zabbix/types.ts @@ -1,3 +1,27 @@ +export type zabbixMethodName = + | 'alert.get' + | 'apiinfo.version' + | 'application.get' + | 'event.acknowledge' + | 'event.get' + | 'history.get' + | 'host.get' + | 'hostgroup.get' + | 'item.get' + | 'problem.get' + | 'proxy.get' + | 'script.execute' + | 'script.get' + | 'service.get' + | 'service.getsla' + | 'sla.get' + | 'sla.getsli' + | 'trend.get' + | 'trigger.get' + | 'user.get' + | 'usermacro.get' + | 'valuemap.get'; + export interface ZabbixConnector { getHistory: (items, timeFrom, timeTill) => Promise; getTrend: (items, timeFrom, timeTill) => Promise;