Skip to content

Commit

Permalink
Fix compatibility with Zabbix 5.4 (skip applications filter) (#1214)
Browse files Browse the repository at this point in the history
* Fix queries in Zabbix 5.4 (applications not supported)

* Fix alerting queries in Zabbix 5.4
  • Loading branch information
alexanderzobnin committed May 18, 2021
1 parent e77990f commit d3e6c97
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 13 deletions.
14 changes: 13 additions & 1 deletion pkg/datasource/zabbix.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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".`
}
1 change: 1 addition & 0 deletions src/datasource-zabbix/partials/query.editor.html
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@
<label class="gf-form-label query-keyword width-7">Application</label>
<input type="text"
ng-model="ctrl.target.application.filter"
ng-disabled="ctrl.appFilterDisabled()"
bs-typeahead="ctrl.getApplicationNames"
ng-blur="ctrl.onTargetBlur()"
data-min-length=0
Expand Down
4 changes: 4 additions & 0 deletions src/datasource-zabbix/query.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -512,4 +512,8 @@ export class ZabbixQueryController extends QueryCtrl {
this.init();
this.targetChanged();
}

appFilterDisabled() {
return !this.zabbix.supportsApplications();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,14 @@ export class ZabbixAPIConnector {
//////////////////////////

request(method: string, params?: any) {
return this.backendAPIRequest(method, params).then(response => {
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',
Expand All @@ -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<string> {
Expand Down Expand Up @@ -147,7 +150,11 @@ export class ZabbixAPIConnector {
return this.request('host.get', params);
}

getApps(hostids): Promise<any[]> {
async getApps(hostids): Promise<any[]> {
if (semver.gte(this.version, '5.4.0')) {
return [];
}

const params = {
output: 'extend',
hostids: hostids
Expand Down
2 changes: 2 additions & 0 deletions src/datasource-zabbix/zabbix/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
30 changes: 25 additions & 5 deletions src/datasource-zabbix/zabbix/zabbix.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand Down Expand Up @@ -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'
];

Expand All @@ -40,6 +41,7 @@ export class Zabbix implements ZabbixConnector {
getHistoryDB: any;
dbConnector: any;
getTrendsDB: any;
version: string;

getHistory: (items, timeFrom, timeTill) => Promise<any>;
getTrend: (items, timeFrom, timeTill) => Promise<any>;
Expand All @@ -54,7 +56,6 @@ export class Zabbix implements ZabbixConnector {
getEventAlerts: (eventids) => Promise<any>;
getExtendedEventData: (eventids) => Promise<any>;
getMacros: (hostids: any[]) => Promise<any>;
getVersion: () => Promise<string>;
getValueMappings: () => Promise<any>;

constructor(options) {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -218,19 +230,27 @@ 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');
return this.zabbixAPI.getApps(hostids);
});
}

getApps(groupFilter?, hostFilter?, appFilter?): Promise<AppsResponse> {
async getApps(groupFilter?, hostFilter?, appFilter?): Promise<AppsResponse> {
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 {
Expand Down

0 comments on commit d3e6c97

Please sign in to comment.