diff --git a/pkg/datasource/zabbix.go b/pkg/datasource/zabbix.go
index 7ac18a182..9972a8e82 100644
--- a/pkg/datasource/zabbix.go
+++ b/pkg/datasource/zabbix.go
@@ -167,7 +167,10 @@ func (ds *ZabbixDatasourceInstance) getItems(ctx context.Context, groupFilter st
}
apps, err := ds.getApps(ctx, groupFilter, hostFilter, appFilter)
- if err != nil {
+ // Apps not supported in Zabbix 5.4 and higher
+ if isAppMethodNotFoundError(err) {
+ apps = []map[string]interface{}{}
+ } else if err != nil {
return nil, err
}
var appids []string
@@ -505,3 +508,12 @@ func isNotAuthorized(err error) bool {
strings.Contains(message, "Not authorised.") ||
strings.Contains(message, "Not authorized.")
}
+
+func isAppMethodNotFoundError(err error) bool {
+ if err == nil {
+ return false
+ }
+
+ message := err.Error()
+ return message == `Method not found. Incorrect API "application".`
+}
diff --git a/src/datasource-zabbix/partials/query.editor.html b/src/datasource-zabbix/partials/query.editor.html
index ec91acd77..a3bb8cdf5 100644
--- a/src/datasource-zabbix/partials/query.editor.html
+++ b/src/datasource-zabbix/partials/query.editor.html
@@ -122,6 +122,7 @@
{
- return response?.data?.result;
- });
+ if (!this.version) {
+ return this.initVersion().then(() => this.request(method, params));
+ }
+
+ return this.backendAPIRequest(method, params);
}
- backendAPIRequest(method: string, params: any = {}) {
+ async backendAPIRequest(method: string, params: any = {}) {
const requestOptions: BackendSrvRequest = {
url: this.backendAPIUrl,
method: 'POST',
@@ -74,14 +76,15 @@ export class ZabbixAPIConnector {
requestOptions.headers.Authorization = this.requestOptions.basicAuth;
}
- return getBackendSrv().datasourceRequest(requestOptions);
+ const response = await getBackendSrv().datasourceRequest(requestOptions);
+ return response?.data?.result;
}
/**
* Get Zabbix API version
*/
getVersion() {
- return this.request('apiinfo.version');
+ return this.backendAPIRequest('apiinfo.version');
}
initVersion(): Promise {
@@ -147,7 +150,11 @@ export class ZabbixAPIConnector {
return this.request('host.get', params);
}
- getApps(hostids): Promise {
+ async getApps(hostids): Promise {
+ if (semver.gte(this.version, '5.4.0')) {
+ return [];
+ }
+
const params = {
output: 'extend',
hostids: hostids
diff --git a/src/datasource-zabbix/zabbix/types.ts b/src/datasource-zabbix/zabbix/types.ts
index f1ab2dd20..7cd65d320 100644
--- a/src/datasource-zabbix/zabbix/types.ts
+++ b/src/datasource-zabbix/zabbix/types.ts
@@ -19,4 +19,6 @@ export interface ZabbixConnector {
getApps: (groupFilter?, hostFilter?, appFilter?) => any;
getItems: (groupFilter?, hostFilter?, appFilter?, itemFilter?, options?) => any;
getSLA: (itservices, timeRange, target, options?) => any;
+
+ supportsApplications: () => boolean;
}
diff --git a/src/datasource-zabbix/zabbix/zabbix.ts b/src/datasource-zabbix/zabbix/zabbix.ts
index 00e86aa39..392858579 100644
--- a/src/datasource-zabbix/zabbix/zabbix.ts
+++ b/src/datasource-zabbix/zabbix/zabbix.ts
@@ -1,5 +1,6 @@
import _ from 'lodash';
import moment from 'moment';
+import semver from 'semver';
import * as utils from '../utils';
import responseHandler from '../responseHandler';
import { CachingProxy } from './proxy/cachingProxy';
@@ -29,7 +30,7 @@ const REQUESTS_TO_CACHE = [
const REQUESTS_TO_BIND = [
'getHistory', 'getTrend', 'getMacros', 'getItemsByIDs', 'getEvents', 'getAlerts', 'getHostAlerts',
- 'getAcknowledges', 'getITService', 'getVersion', 'acknowledgeEvent', 'getProxies', 'getEventAlerts',
+ 'getAcknowledges', 'getITService', 'acknowledgeEvent', 'getProxies', 'getEventAlerts',
'getExtendedEventData', 'getScripts', 'executeScript', 'getValueMappings'
];
@@ -40,6 +41,7 @@ export class Zabbix implements ZabbixConnector {
getHistoryDB: any;
dbConnector: any;
getTrendsDB: any;
+ version: string;
getHistory: (items, timeFrom, timeTill) => Promise;
getTrend: (items, timeFrom, timeTill) => Promise;
@@ -54,7 +56,6 @@ export class Zabbix implements ZabbixConnector {
getEventAlerts: (eventids) => Promise;
getExtendedEventData: (eventids) => Promise;
getMacros: (hostids: any[]) => Promise;
- getVersion: () => Promise;
getValueMappings: () => Promise;
constructor(options) {
@@ -168,6 +169,17 @@ export class Zabbix implements ZabbixConnector {
});
}
+ async getVersion() {
+ if (!this.version) {
+ this.version = await this.zabbixAPI.initVersion();
+ }
+ return this.version;
+ }
+
+ supportsApplications() {
+ return this.version ? semver.lt(this.version, '5.4.0') : true;
+ }
+
getItemsFromTarget(target, options) {
const parts = ['group', 'host', 'application', 'item'];
const filters = _.map(parts, p => target[p].filter);
@@ -218,7 +230,12 @@ export class Zabbix implements ZabbixConnector {
/**
* Get list of applications belonging to given groups and hosts.
*/
- getAllApps(groupFilter, hostFilter) {
+ async getAllApps(groupFilter, hostFilter) {
+ await this.getVersion();
+ if (!this.supportsApplications()) {
+ return [];
+ }
+
return this.getHosts(groupFilter, hostFilter)
.then(hosts => {
const hostids = _.map(hosts, 'hostid');
@@ -226,11 +243,14 @@ export class Zabbix implements ZabbixConnector {
});
}
- getApps(groupFilter?, hostFilter?, appFilter?): Promise {
+ async getApps(groupFilter?, hostFilter?, appFilter?): Promise {
+ await this.getVersion();
+ const skipAppFilter = !this.supportsApplications();
+
return this.getHosts(groupFilter, hostFilter)
.then(hosts => {
const hostids = _.map(hosts, 'hostid');
- if (appFilter) {
+ if (appFilter && !skipAppFilter) {
return this.zabbixAPI.getApps(hostids)
.then(apps => filterByQuery(apps, appFilter));
} else {