diff --git a/src/datasource-zabbix/config.controller.js b/src/datasource-zabbix/config.controller.js index 926d5b0..68b692e 100644 --- a/src/datasource-zabbix/config.controller.js +++ b/src/datasource-zabbix/config.controller.js @@ -1,4 +1,5 @@ import _ from 'lodash'; +import { getDataSourceSrv } from '@grafana/runtime'; import { migrateDSConfig } from './migrations'; const SUPPORTED_SQL_DS = ['mysql', 'postgres', 'influxdb']; @@ -23,9 +24,7 @@ const defaultConfig = { export class ZabbixDSConfigController { /** @ngInject */ - constructor($scope, $injector, datasourceSrv) { - this.datasourceSrv = datasourceSrv; - + constructor() { this.current.jsonData = migrateDSConfig(this.current.jsonData); _.defaults(this.current.jsonData, defaultConfig); @@ -39,7 +38,7 @@ export class ZabbixDSConfigController { } getSupportedDBDataSources() { - let datasources = this.datasourceSrv.getAll(); + let datasources = getDataSourceSrv().getAll(); return _.filter(datasources, ds => { return _.includes(SUPPORTED_SQL_DS, ds.type); }); @@ -53,7 +52,7 @@ export class ZabbixDSConfigController { loadCurrentDBDatasource() { const dsName= this.current.jsonData.dbConnectionDatasourceName; - this.datasourceSrv.loadDatasource(dsName) + getDataSourceSrv().loadDatasource(dsName) .then(ds => { if (ds) { this.dbConnectionDatasourceId = ds.id; @@ -66,7 +65,7 @@ export class ZabbixDSConfigController { return; } - this.datasourceSrv.loadDatasource(this.current.name) + getDataSourceSrv().loadDatasource(this.current.name) .then(ds => { return ds.getVersion(); }) diff --git a/src/datasource-zabbix/datasource.js b/src/datasource-zabbix/datasource.js index f30e45a..6a9def4 100644 --- a/src/datasource-zabbix/datasource.js +++ b/src/datasource-zabbix/datasource.js @@ -16,7 +16,7 @@ const DEFAULT_ZABBIX_VERSION = 3; export class ZabbixDatasource { /** @ngInject */ - constructor(instanceSettings, templateSrv, datasourceSrv, zabbixAlertingSrv) { + constructor(instanceSettings, templateSrv, zabbixAlertingSrv) { this.templateSrv = templateSrv; this.zabbixAlertingSrv = zabbixAlertingSrv; @@ -75,7 +75,7 @@ export class ZabbixDatasource { dbConnectionRetentionPolicy: this.dbConnectionRetentionPolicy, }; - this.zabbix = new Zabbix(zabbixOptions, datasourceSrv); + this.zabbix = new Zabbix(zabbixOptions); } //////////////////////// diff --git a/src/datasource-zabbix/specs/dbConnector.test.js b/src/datasource-zabbix/specs/dbConnector.test.ts similarity index 51% rename from src/datasource-zabbix/specs/dbConnector.test.js rename to src/datasource-zabbix/specs/dbConnector.test.ts index b41276c..8233708 100644 --- a/src/datasource-zabbix/specs/dbConnector.test.js +++ b/src/datasource-zabbix/specs/dbConnector.test.ts @@ -1,11 +1,17 @@ -import mocks from '../../test-setup/mocks'; import { DBConnector } from '../zabbix/connectors/dbConnector'; +const loadDatasourceMock = jest.fn().mockResolvedValue({ id: 42, name: 'foo', meta: {} }); +const getAllMock = jest.fn().mockReturnValue([{ id: 42, name: 'foo', meta: {} }]); + +jest.mock('@grafana/runtime', () => ({ + getDataSourceSrv: () => ({ + loadDatasource: loadDatasourceMock, + getAll: getAllMock + }), +})); + describe('DBConnector', () => { - let ctx = {}; - const datasourceSrv = mocks.datasourceSrvMock; - datasourceSrv.loadDatasource.mockResolvedValue({ id: 42, name: 'foo', meta: {} }); - datasourceSrv.getAll.mockReturnValue([{ id: 42, name: 'foo' }]); + const ctx: any = {}; describe('When init DB connector', () => { beforeEach(() => { @@ -13,34 +19,34 @@ describe('DBConnector', () => { datasourceId: 42, datasourceName: undefined }; + + loadDatasourceMock.mockClear(); + getAllMock.mockClear(); }); it('should try to load datasource by name first', () => { - ctx.options = { - datasourceName: 'bar' - }; - const dbConnector = new DBConnector(ctx.options, datasourceSrv); + const dbConnector = new DBConnector({ datasourceName: 'bar' }); dbConnector.loadDBDataSource(); - expect(datasourceSrv.getAll).not.toHaveBeenCalled(); - expect(datasourceSrv.loadDatasource).toHaveBeenCalledWith('bar'); + expect(getAllMock).not.toHaveBeenCalled(); + expect(loadDatasourceMock).toHaveBeenCalledWith('bar'); }); it('should load datasource by id if name not present', () => { - const dbConnector = new DBConnector(ctx.options, datasourceSrv); + const dbConnector = new DBConnector({ datasourceId: 42 }); dbConnector.loadDBDataSource(); - expect(datasourceSrv.getAll).toHaveBeenCalled(); - expect(datasourceSrv.loadDatasource).toHaveBeenCalledWith('foo'); + expect(getAllMock).toHaveBeenCalled(); + expect(loadDatasourceMock).toHaveBeenCalledWith('foo'); }); it('should throw error if no name and id specified', () => { ctx.options = {}; - const dbConnector = new DBConnector(ctx.options, datasourceSrv); + const dbConnector = new DBConnector(ctx.options); return expect(dbConnector.loadDBDataSource()).rejects.toBe('Data Source name should be specified'); }); it('should throw error if datasource with given id is not found', () => { ctx.options.datasourceId = 45; - const dbConnector = new DBConnector(ctx.options, datasourceSrv); + const dbConnector = new DBConnector(ctx.options); return expect(dbConnector.loadDBDataSource()).rejects.toBe('Data Source with ID 45 not found'); }); }); diff --git a/src/datasource-zabbix/specs/influxdbConnector.test.js b/src/datasource-zabbix/specs/influxdbConnector.test.js index a259b6a..6e39913 100644 --- a/src/datasource-zabbix/specs/influxdbConnector.test.js +++ b/src/datasource-zabbix/specs/influxdbConnector.test.js @@ -1,17 +1,20 @@ import { InfluxDBConnector } from '../zabbix/connectors/influxdb/influxdbConnector'; import { compactQuery } from '../utils'; +jest.mock('@grafana/runtime', () => ({ + getDataSourceSrv: jest.fn(() => ({ + loadDatasource: jest.fn().mockResolvedValue( + { id: 42, name: 'InfluxDB DS', meta: {} } + ), + })), +})); + describe('InfluxDBConnector', () => { let ctx = {}; beforeEach(() => { ctx.options = { datasourceName: 'InfluxDB DS', retentionPolicy: 'longterm' }; - ctx.datasourceSrvMock = { - loadDatasource: jest.fn().mockResolvedValue( - { id: 42, name: 'InfluxDB DS', meta: {} } - ), - }; - ctx.influxDBConnector = new InfluxDBConnector(ctx.options, ctx.datasourceSrvMock); + ctx.influxDBConnector = new InfluxDBConnector(ctx.options); ctx.influxDBConnector.invokeInfluxDBQuery = jest.fn().mockResolvedValue([]); ctx.defaultQueryParams = { itemids: ['123', '234'], diff --git a/src/datasource-zabbix/zabbix/connectors/dbConnector.js b/src/datasource-zabbix/zabbix/connectors/dbConnector.js index c4039a1..7b9a235 100644 --- a/src/datasource-zabbix/zabbix/connectors/dbConnector.js +++ b/src/datasource-zabbix/zabbix/connectors/dbConnector.js @@ -1,4 +1,5 @@ import _ from 'lodash'; +import { getDataSourceSrv } from '@grafana/runtime'; export const DEFAULT_QUERY_LIMIT = 10000; export const HISTORY_TO_TABLE_MAP = { @@ -34,31 +35,30 @@ export const consolidateByTrendColumns = { * `testDataSource()` methods, which describe how to fetch data from source other than Zabbix API. */ export class DBConnector { - constructor(options, datasourceSrv) { - this.datasourceSrv = datasourceSrv; + constructor(options) { this.datasourceId = options.datasourceId; this.datasourceName = options.datasourceName; this.datasourceTypeId = null; this.datasourceTypeName = null; } - static loadDatasource(dsId, dsName, datasourceSrv) { + static loadDatasource(dsId, dsName) { if (!dsName && dsId !== undefined) { - let ds = _.find(datasourceSrv.getAll(), {'id': dsId}); + let ds = _.find(getDataSourceSrv().getAll(), {'id': dsId}); if (!ds) { return Promise.reject(`Data Source with ID ${dsId} not found`); } dsName = ds.name; } if (dsName) { - return datasourceSrv.loadDatasource(dsName); + return getDataSourceSrv().loadDatasource(dsName); } else { return Promise.reject(`Data Source name should be specified`); } } loadDBDataSource() { - return DBConnector.loadDatasource(this.datasourceId, this.datasourceName, this.datasourceSrv) + return DBConnector.loadDatasource(this.datasourceId, this.datasourceName) .then(ds => { this.datasourceTypeId = ds.meta.id; this.datasourceTypeName = ds.meta.name; diff --git a/src/datasource-zabbix/zabbix/connectors/influxdb/influxdbConnector.js b/src/datasource-zabbix/zabbix/connectors/influxdb/influxdbConnector.js index 512f2da..94068d3 100644 --- a/src/datasource-zabbix/zabbix/connectors/influxdb/influxdbConnector.js +++ b/src/datasource-zabbix/zabbix/connectors/influxdb/influxdbConnector.js @@ -11,8 +11,8 @@ const consolidateByFunc = { }; export class InfluxDBConnector extends DBConnector { - constructor(options, datasourceSrv) { - super(options, datasourceSrv); + constructor(options) { + super(options); this.retentionPolicy = options.retentionPolicy; super.loadDBDataSource().then(ds => { this.influxDS = ds; diff --git a/src/datasource-zabbix/zabbix/connectors/sql/sqlConnector.js b/src/datasource-zabbix/zabbix/connectors/sql/sqlConnector.js index 3377ec1..9b38bdc 100644 --- a/src/datasource-zabbix/zabbix/connectors/sql/sqlConnector.js +++ b/src/datasource-zabbix/zabbix/connectors/sql/sqlConnector.js @@ -11,8 +11,8 @@ const supportedDatabases = { }; export class SQLConnector extends DBConnector { - constructor(options, datasourceSrv) { - super(options, datasourceSrv); + constructor(options) { + super(options); this.limit = options.limit || DEFAULT_QUERY_LIMIT; this.sqlDialect = null; diff --git a/src/datasource-zabbix/zabbix/zabbix.js b/src/datasource-zabbix/zabbix/zabbix.js index 39a4f80..2176649 100644 --- a/src/datasource-zabbix/zabbix/zabbix.js +++ b/src/datasource-zabbix/zabbix/zabbix.js @@ -25,7 +25,7 @@ const REQUESTS_TO_BIND = [ ]; export class Zabbix { - constructor(options, datasourceSrv) { + constructor(options) { let { url, username, @@ -57,7 +57,7 @@ export class Zabbix { if (enableDirectDBConnection) { const connectorOptions = { dbConnectionRetentionPolicy }; - this.initDBConnector(dbConnectionDatasourceId, dbConnectionDatasourceName, datasourceSrv, connectorOptions) + this.initDBConnector(dbConnectionDatasourceId, dbConnectionDatasourceName, connectorOptions) .then(() => { this.getHistoryDB = this.cachingProxy.proxyfyWithCache(this.dbConnector.getHistory, 'getHistory', this.dbConnector); this.getTrendsDB = this.cachingProxy.proxyfyWithCache(this.dbConnector.getTrends, 'getTrends', this.dbConnector); @@ -65,15 +65,15 @@ export class Zabbix { } } - initDBConnector(datasourceId, datasourceName, datasourceSrv, options) { - return DBConnector.loadDatasource(datasourceId, datasourceName, datasourceSrv) + initDBConnector(datasourceId, datasourceName, options) { + return DBConnector.loadDatasource(datasourceId, datasourceName) .then(ds => { let connectorOptions = { datasourceId, datasourceName }; if (ds.type === 'influxdb') { connectorOptions.retentionPolicy = options.dbConnectionRetentionPolicy; - this.dbConnector = new InfluxDBConnector(connectorOptions, datasourceSrv); + this.dbConnector = new InfluxDBConnector(connectorOptions); } else { - this.dbConnector = new SQLConnector(connectorOptions, datasourceSrv); + this.dbConnector = new SQLConnector(connectorOptions); } return this.dbConnector; }); diff --git a/src/panel-triggers/specs/migrations.spec.ts b/src/panel-triggers/specs/migrations.spec.ts index bd916e8..a309907 100644 --- a/src/panel-triggers/specs/migrations.spec.ts +++ b/src/panel-triggers/specs/migrations.spec.ts @@ -4,15 +4,20 @@ import {TriggerPanelCtrl} from '../triggers_panel_ctrl'; import {DEFAULT_TARGET, DEFAULT_SEVERITY, PANEL_DEFAULTS} from '../triggers_panel_ctrl'; import {CURRENT_SCHEMA_VERSION} from '../migrations'; +jest.mock('@grafana/runtime', () => { + return { + getDataSourceSrv: () => ({ + getMetricSources: () => { + return [{ meta: {id: 'alexanderzobnin-zabbix-datasource'}, value: {}, name: 'zabbix_default' }]; + }, + get: () => Promise.resolve({}) + }), + }; +}, {virtual: true}); + describe('Triggers Panel schema migration', () => { let ctx: any = {}; let updatePanelCtrl; - const datasourceSrvMock = { - getMetricSources: () => { - return [{ meta: {id: 'alexanderzobnin-zabbix-datasource'}, value: {}, name: 'zabbix_default' }]; - }, - get: () => Promise.resolve({}) - }; const timeoutMock = () => {}; @@ -43,7 +48,7 @@ describe('Triggers Panel schema migration', () => { } }; - updatePanelCtrl = (scope) => new TriggerPanelCtrl(scope, {}, timeoutMock, datasourceSrvMock, {}, {}, {}, mocks.timeSrvMock); + updatePanelCtrl = (scope) => new TriggerPanelCtrl(scope, {}, timeoutMock, {}, {}, {}, mocks.timeSrvMock); }); it('should update old panel schema', () => { diff --git a/src/panel-triggers/specs/panel_ctrl.spec.ts b/src/panel-triggers/specs/panel_ctrl.spec.ts index 67283c9..a52707d 100644 --- a/src/panel-triggers/specs/panel_ctrl.spec.ts +++ b/src/panel-triggers/specs/panel_ctrl.spec.ts @@ -4,9 +4,16 @@ import {TriggerPanelCtrl} from '../triggers_panel_ctrl'; import {PANEL_DEFAULTS, DEFAULT_TARGET} from '../triggers_panel_ctrl'; // import { create } from 'domain'; +let datasourceSrvMock, zabbixDSMock; + +jest.mock('@grafana/runtime', () => { + return { + getDataSourceSrv: () => datasourceSrvMock, + }; +}, {virtual: true}); + describe('TriggerPanelCtrl', () => { let ctx: any = {}; - let datasourceSrvMock, zabbixDSMock; const timeoutMock = () => {}; let createPanelCtrl; @@ -31,7 +38,8 @@ describe('TriggerPanelCtrl', () => { }, get: () => Promise.resolve(zabbixDSMock) }; - createPanelCtrl = () => new TriggerPanelCtrl(ctx.scope, {}, timeoutMock, datasourceSrvMock, {}, {}, {}, mocks.timeSrvMock); + + createPanelCtrl = () => new TriggerPanelCtrl(ctx.scope, {}, timeoutMock, {}, {}, {}, mocks.timeSrvMock); const getTriggersResp = [ [ diff --git a/src/panel-triggers/triggers_panel_ctrl.js b/src/panel-triggers/triggers_panel_ctrl.js index e6b03b7..25d86a9 100644 --- a/src/panel-triggers/triggers_panel_ctrl.js +++ b/src/panel-triggers/triggers_panel_ctrl.js @@ -2,6 +2,7 @@ import React from 'react'; import ReactDOM from 'react-dom'; import _ from 'lodash'; import moment from 'moment'; +import { getDataSourceSrv } from '@grafana/runtime'; import * as dateMath from 'grafana/app/core/utils/datemath'; import * as utils from '../datasource-zabbix/utils'; import { PanelCtrl } from 'grafana/app/plugins/sdk'; @@ -96,9 +97,8 @@ const triggerStatusMap = { export class TriggerPanelCtrl extends PanelCtrl { /** @ngInject */ - constructor($scope, $injector, $timeout, datasourceSrv, templateSrv, contextSrv, dashboardSrv, timeSrv) { + constructor($scope, $injector, $timeout, templateSrv, contextSrv, dashboardSrv, timeSrv) { super($scope, $injector); - this.datasourceSrv = datasourceSrv; this.templateSrv = templateSrv; this.contextSrv = contextSrv; this.dashboardSrv = dashboardSrv; @@ -151,7 +151,7 @@ export class TriggerPanelCtrl extends PanelCtrl { const targetDatasources = _.compact(this.panel.targets.map(target => target.datasource)); let promises = targetDatasources.map(ds => { // Load datasource - return this.datasourceSrv.get(ds) + return getDataSourceSrv().get(ds) .then(datasource => { this.datasources[ds] = datasource; return datasource; @@ -161,7 +161,7 @@ export class TriggerPanelCtrl extends PanelCtrl { } getZabbixDataSources() { - return _.filter(this.datasourceSrv.getMetricSources(), datasource => { + return _.filter(getDataSourceSrv().getMetricSources(), datasource => { return datasource.meta.id === ZABBIX_DS_ID && datasource.value; }); } @@ -251,7 +251,7 @@ export class TriggerPanelCtrl extends PanelCtrl { const ds = target.datasource; let proxies; let showAckButton = true; - return this.datasourceSrv.get(ds) + return getDataSourceSrv().get(ds) .then(datasource => { const zabbix = datasource.zabbix; const showEvents = this.panel.showEvents.value; @@ -524,7 +524,7 @@ export class TriggerPanelCtrl extends PanelCtrl { const triggerids = [problem.triggerid]; const timeFrom = Math.ceil(dateMath.parse(this.range.from) / 1000); const timeTo = Math.ceil(dateMath.parse(this.range.to) / 1000); - return this.datasourceSrv.get(problem.datasource) + return getDataSourceSrv().get(problem.datasource) .then(datasource => { return datasource.zabbix.getEvents(triggerids, timeFrom, timeTo, [0, 1], PROBLEM_EVENTS_LIMIT); }); @@ -535,7 +535,7 @@ export class TriggerPanelCtrl extends PanelCtrl { return Promise.resolve([]); } const eventids = [problem.lastEvent.eventid]; - return this.datasourceSrv.get(problem.datasource) + return getDataSourceSrv().get(problem.datasource) .then(datasource => { return datasource.zabbix.getEventAlerts(eventids); }); @@ -622,7 +622,7 @@ export class TriggerPanelCtrl extends PanelCtrl { let eventid = trigger.lastEvent ? trigger.lastEvent.eventid : null; let grafana_user = this.contextSrv.user.name; let ack_message = grafana_user + ' (Grafana): ' + message; - return this.datasourceSrv.get(trigger.datasource) + return getDataSourceSrv().get(trigger.datasource) .then(datasource => { const userIsEditor = this.contextSrv.isEditor || this.contextSrv.isGrafanaAdmin; if (datasource.disableReadOnlyUsersAck && !userIsEditor) {