backend: proxy Zabbix API requests through the backend
This commit is contained in:
1
go.mod
1
go.mod
@@ -3,6 +3,7 @@ module github.com/alexanderzobnin/grafana-zabbix
|
|||||||
go 1.12
|
go 1.12
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/bitly/go-simplejson v0.5.0
|
||||||
github.com/grafana/grafana_plugin_model v0.0.0-20180518082423-84176c64269d
|
github.com/grafana/grafana_plugin_model v0.0.0-20180518082423-84176c64269d
|
||||||
github.com/hashicorp/go-hclog v0.9.2
|
github.com/hashicorp/go-hclog v0.9.2
|
||||||
github.com/hashicorp/go-plugin v1.0.1
|
github.com/hashicorp/go-plugin v1.0.1
|
||||||
|
|||||||
2
go.sum
2
go.sum
@@ -1,3 +1,5 @@
|
|||||||
|
github.com/bitly/go-simplejson v0.5.0 h1:6IH+V8/tVMab511d5bn4M7EwGXZf9Hj6i2xSwkNEM+Y=
|
||||||
|
github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
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/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
simplejson "github.com/bitly/go-simplejson"
|
||||||
"github.com/grafana/grafana_plugin_model/go/datasource"
|
"github.com/grafana/grafana_plugin_model/go/datasource"
|
||||||
hclog "github.com/hashicorp/go-hclog"
|
hclog "github.com/hashicorp/go-hclog"
|
||||||
plugin "github.com/hashicorp/go-plugin"
|
plugin "github.com/hashicorp/go-plugin"
|
||||||
@@ -13,5 +16,52 @@ type ZabbixDatasource struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ds *ZabbixDatasource) Query(ctx context.Context, tsdbReq *datasource.DatasourceRequest) (*datasource.DatasourceResponse, error) {
|
func (ds *ZabbixDatasource) Query(ctx context.Context, tsdbReq *datasource.DatasourceRequest) (*datasource.DatasourceResponse, error) {
|
||||||
return nil, ctx.Err()
|
queryType, err := GetQueryType(tsdbReq)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
dsInfo := tsdbReq.GetDatasource()
|
||||||
|
ds.logger.Debug("createRequest", "dsInfo", dsInfo)
|
||||||
|
|
||||||
|
ds.logger.Debug("createRequest", "queryType", queryType)
|
||||||
|
|
||||||
|
switch queryType {
|
||||||
|
case "zabbixAPI":
|
||||||
|
return ds.ZabbixAPIQuery(ctx, tsdbReq)
|
||||||
|
default:
|
||||||
|
return nil, errors.New("Query is not implemented yet")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetQueryType(tsdbReq *datasource.DatasourceRequest) (string, error) {
|
||||||
|
queryType := "query"
|
||||||
|
if len(tsdbReq.Queries) > 0 {
|
||||||
|
firstQuery := tsdbReq.Queries[0]
|
||||||
|
queryJson, err := simplejson.NewJson([]byte(firstQuery.ModelJson))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
queryType = queryJson.Get("queryType").MustString("query")
|
||||||
|
}
|
||||||
|
return queryType, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ds *ZabbixDatasource) ZabbixAPIQuery(ctx context.Context, tsdbReq *datasource.DatasourceRequest) (*datasource.DatasourceResponse, error) {
|
||||||
|
jsonQueries := make([]*simplejson.Json, 0)
|
||||||
|
for _, query := range tsdbReq.Queries {
|
||||||
|
json, err := simplejson.NewJson([]byte(query.ModelJson))
|
||||||
|
apiMethod := json.GetPath("target", "method").MustString()
|
||||||
|
apiParams := json.GetPath("target", "params")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ds.logger.Debug("ZabbixAPIQuery", "method", apiMethod, "params", apiParams)
|
||||||
|
|
||||||
|
jsonQueries = append(jsonQueries, json)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, errors.New("ZabbixAPIQuery is not implemented yet")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ export class ZabbixDatasource {
|
|||||||
/** @ngInject */
|
/** @ngInject */
|
||||||
constructor(instanceSettings, templateSrv, backendSrv, datasourceSrv, zabbixAlertingSrv) {
|
constructor(instanceSettings, templateSrv, backendSrv, datasourceSrv, zabbixAlertingSrv) {
|
||||||
this.templateSrv = templateSrv;
|
this.templateSrv = templateSrv;
|
||||||
|
this.backendSrv = backendSrv;
|
||||||
this.zabbixAlertingSrv = zabbixAlertingSrv;
|
this.zabbixAlertingSrv = zabbixAlertingSrv;
|
||||||
|
|
||||||
this.enableDebugLog = config.buildInfo.env === 'development';
|
this.enableDebugLog = config.buildInfo.env === 'development';
|
||||||
@@ -25,6 +26,7 @@ export class ZabbixDatasource {
|
|||||||
this.replaceTemplateVars = _.partial(replaceTemplateVars, this.templateSrv);
|
this.replaceTemplateVars = _.partial(replaceTemplateVars, this.templateSrv);
|
||||||
|
|
||||||
// General data source settings
|
// General data source settings
|
||||||
|
this.datasourceId = instanceSettings.id;
|
||||||
this.name = instanceSettings.name;
|
this.name = instanceSettings.name;
|
||||||
this.url = instanceSettings.url;
|
this.url = instanceSettings.url;
|
||||||
this.basicAuth = instanceSettings.basicAuth;
|
this.basicAuth = instanceSettings.basicAuth;
|
||||||
@@ -74,7 +76,7 @@ export class ZabbixDatasource {
|
|||||||
dbConnectionRetentionPolicy: this.dbConnectionRetentionPolicy,
|
dbConnectionRetentionPolicy: this.dbConnectionRetentionPolicy,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.zabbix = new Zabbix(zabbixOptions, datasourceSrv, backendSrv);
|
this.zabbix = new Zabbix(zabbixOptions, datasourceSrv, backendSrv, this.datasourceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////
|
////////////////////////
|
||||||
@@ -87,6 +89,9 @@ export class ZabbixDatasource {
|
|||||||
* @return {Object} Grafana metrics object with timeseries data for each target.
|
* @return {Object} Grafana metrics object with timeseries data for each target.
|
||||||
*/
|
*/
|
||||||
query(options) {
|
query(options) {
|
||||||
|
// console.log('invoking doTsdbRequest()');
|
||||||
|
// this.doTsdbRequest(options);
|
||||||
|
|
||||||
// Get alerts for current panel
|
// Get alerts for current panel
|
||||||
if (this.alertingEnabled) {
|
if (this.alertingEnabled) {
|
||||||
this.alertQuery(options).then(alert => {
|
this.alertQuery(options).then(alert => {
|
||||||
@@ -166,6 +171,27 @@ export class ZabbixDatasource {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
doTsdbRequest(options) {
|
||||||
|
const tsdbRequestData = {
|
||||||
|
queries: options.targets.map(target => {
|
||||||
|
target.datasourceId = this.datasourceId;
|
||||||
|
target.queryType = 'zabbixAPI';
|
||||||
|
return target;
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (options.range) {
|
||||||
|
tsdbRequestData.from = options.range.from.valueOf().toString();
|
||||||
|
tsdbRequestData.to = options.range.to.valueOf().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.backendSrv.datasourceRequest({
|
||||||
|
url: '/api/tsdb/query',
|
||||||
|
method: 'POST',
|
||||||
|
data: tsdbRequestData
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Query target data for Metrics mode
|
* Query target data for Metrics mode
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { ZBX_ACK_ACTION_NONE, ZBX_ACK_ACTION_ACK, ZBX_ACK_ACTION_ADD_MESSAGE, MI
|
|||||||
* Wraps API calls and provides high-level methods.
|
* Wraps API calls and provides high-level methods.
|
||||||
*/
|
*/
|
||||||
export class ZabbixAPIConnector {
|
export class ZabbixAPIConnector {
|
||||||
constructor(api_url, username, password, version, basicAuth, withCredentials, backendSrv) {
|
constructor(api_url, username, password, version, basicAuth, withCredentials, backendSrv, datasourceId) {
|
||||||
this.url = api_url;
|
this.url = api_url;
|
||||||
this.username = username;
|
this.username = username;
|
||||||
this.password = password;
|
this.password = password;
|
||||||
@@ -22,6 +22,9 @@ export class ZabbixAPIConnector {
|
|||||||
withCredentials: withCredentials
|
withCredentials: withCredentials
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.datasourceId = datasourceId;
|
||||||
|
this.backendSrv = backendSrv;
|
||||||
|
|
||||||
this.loginPromise = null;
|
this.loginPromise = null;
|
||||||
this.loginErrorCount = 0;
|
this.loginErrorCount = 0;
|
||||||
this.maxLoginAttempts = 3;
|
this.maxLoginAttempts = 3;
|
||||||
@@ -37,6 +40,8 @@ export class ZabbixAPIConnector {
|
|||||||
//////////////////////////
|
//////////////////////////
|
||||||
|
|
||||||
request(method, params) {
|
request(method, params) {
|
||||||
|
this.tsdbRequest(method, params);
|
||||||
|
|
||||||
return this.zabbixAPICore.request(this.url, method, params, this.requestOptions, this.auth)
|
return this.zabbixAPICore.request(this.url, method, params, this.requestOptions, this.auth)
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
if (isNotAuthorized(error.data)) {
|
if (isNotAuthorized(error.data)) {
|
||||||
@@ -55,6 +60,25 @@ export class ZabbixAPIConnector {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tsdbRequest(method, params) {
|
||||||
|
const tsdbRequestData = {
|
||||||
|
queries: [{
|
||||||
|
datasourceId: this.datasourceId,
|
||||||
|
queryType: 'zabbixAPI',
|
||||||
|
target: {
|
||||||
|
method,
|
||||||
|
params,
|
||||||
|
},
|
||||||
|
}],
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.backendSrv.datasourceRequest({
|
||||||
|
url: '/api/tsdb/query',
|
||||||
|
method: 'POST',
|
||||||
|
data: tsdbRequestData
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When API unauthenticated or auth token expired each request produce login()
|
* When API unauthenticated or auth token expired each request produce login()
|
||||||
* call. But auth token is common to all requests. This function wraps login() method
|
* call. But auth token is common to all requests. This function wraps login() method
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ const REQUESTS_TO_BIND = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
export class Zabbix {
|
export class Zabbix {
|
||||||
constructor(options, datasourceSrv, backendSrv) {
|
constructor(options, datasourceSrv, backendSrv, datasourceId) {
|
||||||
let {
|
let {
|
||||||
url,
|
url,
|
||||||
username,
|
username,
|
||||||
@@ -49,7 +49,7 @@ export class Zabbix {
|
|||||||
};
|
};
|
||||||
this.cachingProxy = new CachingProxy(cacheOptions);
|
this.cachingProxy = new CachingProxy(cacheOptions);
|
||||||
|
|
||||||
this.zabbixAPI = new ZabbixAPIConnector(url, username, password, zabbixVersion, basicAuth, withCredentials, backendSrv);
|
this.zabbixAPI = new ZabbixAPIConnector(url, username, password, zabbixVersion, basicAuth, withCredentials, backendSrv, datasourceId);
|
||||||
|
|
||||||
this.proxyfyRequests();
|
this.proxyfyRequests();
|
||||||
this.cacheRequests();
|
this.cacheRequests();
|
||||||
|
|||||||
Reference in New Issue
Block a user